next up previous
Next: Konfigurationsfile .caverc Up: Programmieren mit der CAVELib Previous: Performer (C API)

Unterabschnitte

Performer (C++ API)

Beispiel 1

Beispielprogramm

Ein kurzes Programm, das einen sich drehenden Wuerfel in die Mitte des CAVEs zeichnet.

cube.cc

// includes
#include <stdlib.h>
#include <math.h>

#include <Performer/pf/pfScene.h>
#include <Performer/pf/pfChannel.h>
#include <Performer/pf/pfDCS.h>
#include <Performer/pf/pfGeode.h>
#include <Performer/pr/pfGeoSet.h>

#include <Performer/pfdu.h>
#include <Performer/pfutil.h>

#include <cave_ogl.h>
#include <pfcave.h>

// globals 

// prototypes

// main 
int main(int argc, char **argv) {

  pfScene	*scene;
  pfDCS		*dcs;
  pfGeode	*geode;
  pfGeoSet	*gs;

  // initialise the Performer
  pfInit();

  // configure the CAVELib
  pfCAVEConfig(&argc, argv, NULL);	

  // configure the Performer
  pfConfig();	

  // initialises the channels and opens the graphic windows
  pfCAVEInitChannels();

  // generate a scene 
  scene = new pfScene;
  dcs = new pfDCS;
  scene->addChild(dcs);
  dcs->setTrans(0.0, 100.0, 0.0);
  dcs->setScale(50.0);

  geode = new pfGeode;
  dcs->addChild(geode);
  gs = pfdNewCube(pfGetSharedArena());
  geode->addGSet(gs);

  // attach scene to the CAVELib channels
  pfCAVEMasterChan()->setScene(scene);

  // start the simulation loop
  pfInitClock(0.0);
  while (!CAVEgetbutton(CAVE_ESCKEY)) {
    // update scene 
    dcs->setRot(50.0*pfGetTime(), 0.0, 0.0);

    // generate next frame
    pfCAVEPreFrame(); pfFrame(); pfCAVEPostFrame();
  }

  // halt the CAVE
  pfCAVEHalt();

  // exit the Performer 
  pfExit();

  // exit the Program 
  return(0);
}

Makefile

Ein kleines Makefile-Tutorial

Diese Makefile kompiliert das obige Beispielprogramm.

Makefile.perf++

TARGET  = cube
SRC     = $(TARGET).cc

CC      = CC
CFLAGS  = -mips3 -n32 $(OPT) -I/usr/local/CAVE/include
OPT     = -O 

DEFS    = -DN32 -DIRIX6_5

PERFLIB = -lpfdu_ogl -lpfui -lpfutil_ogl -lpf_ogl        
CAVELIB = -L/usr/local/CAVE/lib32 -lpf -lpfcave_ogl -lcave_ogl -lGL -lX11 -lXi -lm

LIBS    = -no_unresolved $(CAVELIB) $(PERFLIB) 

$(TARGET): $(SRC)
        $(CC) $(DEFS) $(CFLAGS) $? -o $@ $(LIBS)

run: $(TARGET)
        $(TARGET)

clean:

clobber:
        rm -f $(TARGET)

Abfrage der Position und Orientierung des Controllers

Beispielprogramm

Dieses einfache Programm erzeugt einen beleuchteten Szenengraph. Das dargestellte Objekt (ein Pfeil) folgt der Position des CAVE-Controllers und passt sich auch dessen Orientierung im Raum an.

arrow.cc

// includes
#include <stdlib.h>
#include <math.h>

#include <Performer/pf/pfScene.h>
#include <Performer/pf/pfChannel.h>
#include <Performer/pf/pfDCS.h>
#include <Performer/pf/pfGeode.h>
#include <Performer/pr/pfGeoSet.h>
#include <Performer/pr/pfGeoState.h>
#include <Performer/pf/pfLightSource.h>

#include <Performer/pfdu.h>
#include <Performer/pfutil.h>

#include <cave_ogl.h>
#include <pfcave.h>

// globals 

// prototypes

// main 
int main(int argc, char **argv) {

  pfScene       *scene;
  pfDCS         *dcs;
  pfGeode       *geode;
  pfGeoSet      *gs;
  pfGeoState    *gstate;
  void          *arena;  
  float          hpr[3], xyz[3];

  // initialise the Performer
  pfInit();

  // configure the CAVELib
  pfCAVEConfig(&argc, argv, NULL);      

  // configure the Performer
  pfConfig();   

  // initialises the channels and opens the graphic windows
  pfCAVEInitChannels();

  arena = pfGetSharedArena();

  // generate a scene 
  scene = new pfScene;  

  // enable lighting and add a lightsource
  gstate = new(arena) pfGeoState;
  gstate->setMode(PFSTATE_ENLIGHTING, PF_ON);
  scene->setGState(gstate);
  scene->addChild(new pfLightSource);

  dcs = new pfDCS;
  scene->addChild(dcs);
  dcs->setTrans(0.0, 100.0, 0.0);
  dcs->setScale(50.0);

  geode = new pfGeode;
  dcs->addChild(geode);
  gs = pfdNewArrow(10, arena);
  geode->addGSet(gs);

  // attach scene to the CAVELib channels
  pfCAVEMasterChan()->setScene(scene);

  // start the simulation loop
  while (!CAVEgetbutton(CAVE_ESCKEY)) {
    // update scene 

    // get orientation/position of the controller
    pfCAVEGetOrientation(CAVE_WAND, hpr);
    pfCAVEGetPosition(CAVE_WAND, xyz);

    // set orientation/position of the arrow
    dcs->setRot(hpr[2], hpr[0]-90.0, hpr[1]);
    dcs->setTrans(xyz[0], xyz[1], xyz[2]);

    // generate next frame
    pfCAVEPreFrame(); pfFrame(); pfCAVEPostFrame();
  }

  // halt the CAVE
  pfCAVEHalt();

  // exit the Performer 
  pfExit();

  // exit the Program 
  return(0);
}

Makefile

Makefile.arrow

TARGET  = arrow
SRC     = $(TARGET).cc

CC      = CC
CFLAGS  = -mips3 -n32 $(OPT) -I/usr/local/CAVE/include
OPT     = -O 

DEFS    = -DN32 -DIRIX6_5

PERFLIB = -lpfdu_ogl -lpfui -lpfutil_ogl -lpf_ogl       
CAVELIB = -L/usr/local/CAVE/lib32 -lpf -lpfcave_ogl -lcave_ogl -lGL -lX11 -lXi -lm

LIBS    = -no_unresolved $(CAVELIB) $(PERFLIB)   

$(TARGET): $(SRC)
        $(CC) $(DEFS) $(CFLAGS) $? -o $@ $(LIBS)

run: $(TARGET)
        $(TARGET)

Erzeugen einer Geometrie (pfGeoSet)

Es muß darauf geachtet werden, daß die Arrays mit den Werten für die Koordinaten der Eckpunkte, der Farbwerte, und der Normalvektoren in der Shared Arena allociert werden.

Beispielprogramm

Diese kleine Programm zeichnet drei Linien entlang der x-, y- und z-Achse.

axis.cc

// includes
#include <stdlib.h>
#include <math.h>

#include <Performer/pf/pfScene.h>
#include <Performer/pf/pfChannel.h>
#include <Performer/pf/pfDCS.h>
#include <Performer/pf/pfGeode.h>
#include <Performer/pr/pfGeoSet.h>

#include <Performer/pfdu.h>
#include <Performer/pfutil.h>

#include <cave_ogl.h>
#include <pfcave.h>

// globals 
void 	*arena;

// prototypes
pfGeode *makeAxis(void);

// main 
int main(int argc, char **argv) {

  pfScene	*scene;
  pfDCS		*dcs;

  // initialise the Performer
  pfInit();

  // configure the CAVELib
  pfCAVEConfig(&argc, argv, NULL);	

  // configure the Performer
  pfConfig();	

  // initialises the channels and opens the graphic windows
  pfCAVEInitChannels();

  arena = pfGetSharedArena();

  // generate a scene 
  scene = new pfScene;
  dcs = new pfDCS;
  dcs->setScale(50.0);
  scene->addChild(dcs);

  dcs->addChild(makeAxis());

  // attach scene to the CAVELib channels
  pfCAVEMasterChan()->setScene(scene);

  // start the simulation loop
  while (!CAVEgetbutton(CAVE_ESCKEY)) {

    // generate next frame
    pfCAVEPreFrame(); pfFrame(); pfCAVEPostFrame();
  }

  // halt the CAVE
  pfCAVEHalt();

  // exit the Performer 
  pfExit();

  // exit the Program 
  return(0);
}

pfGeode *makeAxis(void) {

  pfVec4	*color;
  pfVec3	*coords;
  pfGeoSet	*gs;
  pfGeode	*geode;

  geode = new pfGeode;
  gs = new(arena) pfGeoSet;

  gs->setPrimType(PFGS_LINES);
  gs->setNumPrims(3);

  color  = (pfVec4 *)pfMalloc(6*sizeof(pfVec4), arena);
  coords = (pfVec3 *)pfMalloc(6*sizeof(pfVec3), arena);
  // x axis
  coords[0].set(-1.0, 0.0, 0.0);
  coords[1].set( 1.0, 0.0, 0.0);
  color[0].set(0.0, 0.0, 0.0, 1.0);
  color[1].set(1.0, 0.0, 0.0, 1.0);

  // y axis
  coords[2].set(0.0, -1.0, 0.0);
  coords[3].set(0.0,  1.0, 0.0);
  color[2].set(0.0, 0.0, 0.0, 1.0);
  color[3].set(0.0, 1.0, 0.0, 1.0);

  // z axis
  coords[4].set(0.0, 0.0, -1.0);
  coords[5].set(0.0, 0.0,  1.0);
  color[4].set(0.0, 0.0, 0.0, 1.0);
  color[5].set(0.0, 0.0, 1.0, 1.0);

  gs->setAttr(PFGS_COORD3, PFGS_PER_VERTEX, coords, NULL);
  // gs->setAttr(PFGS_COLOR4, PFGS_OVERALL, color, NULL);  
  // gs->setAttr(PFGS_COLOR4, PFGS_PER_PRIM, color, NULL);
  gs->setAttr(PFGS_COLOR4, PFGS_PER_VERTEX, color, NULL);

  geode->addGSet(gs);

  return(geode);

}

Makefile

Makefile.axis

TARGET	= axis
SRC	= $(TARGET).cc

CC	= CC
CFLAGS  = -mips3 -n32 $(OPT) -I/usr/local/CAVE/include
OPT	= -O 

DEFS	= -DN32 -DIRIX6_5

PERFLIB	= -lpfdu_ogl -lpfui -lpfutil_ogl -lpf_ogl	
CAVELIB = -L/usr/local/CAVE/lib32 -lpf -lpfcave_ogl -lcave_ogl -lGL -lX11 -lXi -lm

LIBS	= -no_unresolved $(CAVELIB) $(PERFLIB)   

$(TARGET): $(SRC)
	$(CC) $(DEFS) $(CFLAGS) $? -o $@ $(LIBS)
	
run: $(TARGET)
	./$(TARGET)

Navigation durch eine Szene

navigate.cc

Diese kleine Programm erzeugt eine simple Geometrie (ein Schachbrett) und ermöglicht es, sich mit Hilfe des Contollers darueber hinwegzubewegen.

Sourcecode navigate.cc und Makefile.navigate.

// includes
#include <stdlib.h>
#include <math.h>

#include <Performer/pf/pfScene.h>
#include <Performer/pf/pfChannel.h>
#include <Performer/pf/pfDCS.h>
#include <Performer/pf/pfGeode.h>
#include <Performer/pr/pfGeoSet.h>
#include <Performer/pr/pfGeoState.h>
#include <Performer/pf/pfLightSource.h>

#include <Performer/pfdu.h>
#include <Performer/pfutil.h>

#include <cave_ogl.h>
#include <pfcave.h>

// globals 
void 	*arena;

// prototypes
pfGroup *makeArrow(void);
pfGroup *makeChessBoard(int size);

// main 
int main(int argc, char **argv) {

  pfScene	*scene;
  pfDCS		*dcs, *nav;
  pfGeoState	*gstate;
  pfMatrix	 matrix;
  float          hpr[3], xyz[3];

  // initialise the Performer
  pfInit();

  // configure the CAVELib
  pfCAVEConfig(&argc, argv, NULL);	

  // configure the Performer
  pfConfig();	

  // initialises the channels and opens the graphic windows
  pfCAVEInitChannels();

  arena = pfGetSharedArena();

  // generate a scene 
  scene = new pfScene;

  // enable lighting and add a lightsource
  gstate = new(arena) pfGeoState;
  gstate->setMode(PFSTATE_ENLIGHTING, PF_ON);
  scene->setGState(gstate);
  scene->addChild(new pfLightSource);

  dcs = new pfDCS;
  dcs->setScale(50.0);
  dcs->addChild(makeArrow());

  scene->addChild(dcs);

  nav = new pfDCS;
  scene->addChild(nav);

  // create a simple gemoetry
  nav->addChild(makeChessBoard(16));

  // attach scene to the CAVELib channels
  pfCAVEMasterChan()->setScene(scene);

  // start the simulation loop
  while (!CAVEgetbutton(CAVE_ESCKEY)) {

    pfCAVEDCSWandTransform(dcs);

    pfCAVEGetOrientation(CAVE_WAND, hpr);
    pfCAVEGetPosition(CAVE_WAND, xyz); 

    // controller orientation to the left -> rotate scene to the right
    if (hpr[2]<-10.0) {
      matrix.makeRot(+3.0, 0.0, 0.0, 1.0);    
      matrix.postTrans(matrix, xyz[0], xyz[1], xyz[2]);
      matrix.preTrans(-xyz[0], -xyz[1], -xyz[2], matrix);

      matrix.preMult(*(nav->getMatPtr()));
      nav->setMat(matrix);
    }

    // and vice versa
    if (hpr[2]>+10.0) {
      matrix.makeRot(-3.0, 0.0, 0.0, 1.0);        
      matrix.postTrans(matrix, xyz[0], xyz[1], xyz[2]);
      matrix.preTrans(-xyz[0], -xyz[1], -xyz[2], matrix);

      matrix.preMult(*(nav->getMatPtr()));
      nav->setMat(matrix);
    }

    // if button is pressed move forward
    if (CAVEBUTTON3) {
      matrix.makeTrans(0.0, -10.0, 0.0);

      matrix.preMult(*(nav->getMatPtr()));
      nav->setMat(matrix);
    }

    // generate next frame
    pfCAVEPreFrame(); pfFrame(); pfCAVEPostFrame();
  }

  // halt the CAVE
  pfCAVEHalt();

  // exit the Performer 
  pfExit();

  // exit the Program 
  return(0);
}

// ---------------------------------------------------------------------------

pfGroup *makeArrow(void) {

  pfGeode	*geode;
  pfGeoSet	*gs;
  pfSCS		*scs;
  pfMatrix	*matrix;
  pfVec4	*color;

  color = new(arena)pfVec4(0.3, 0.3, 1.0, 1.0);

  geode = new pfGeode;
  gs = pfdNewArrow(10, arena);
  gs->setAttr(PFGS_COLOR4, PFGS_OVERALL, color, NULL);
  geode->addGSet(gs);

  matrix = new pfMatrix;
  matrix->makeRot(-90.0, 1.0, 0.0, 0.0);

  scs = new pfSCS(*matrix);
  scs->addChild(geode);

  return(scs);

}

pfGroup *makeChessBoard(int size) {

  pfGeode	*blackNode, *whiteNode;
  pfGeoSet	*blackGS, *whiteGS;
  pfVec4	*black, *white;
  pfSCS		*scs;
  pfMatrix	*matrix;
  pfGroup	*group;

  group = new pfGroup;

  black = new(arena) pfVec4(0.3, 0.3, 1.0, 1.0);
  blackNode = new pfGeode;
  blackGS = pfdNewCube(arena);
  blackGS->setAttr(PFGS_COLOR4, PFGS_OVERALL, black, NULL); 
  blackNode->addGSet(blackGS); 

  white = new(arena) pfVec4(1.0, 1.0, 1.0, 1.0);
  whiteNode = new pfGeode;
  whiteGS = pfdNewCube(arena);
  whiteGS->setAttr(PFGS_COLOR4, PFGS_OVERALL, white, NULL);
  whiteNode->addGSet(whiteGS); 

  for (int i=0; i<size; i++)
    for (int j=0; j<size; j++) {
      matrix = new pfMatrix;
      matrix->makeTrans(100.0*(i-size/2), 100.0*(j-size/2), 0.0);
      matrix->preScale(99.0, 99.0, 1.0, *matrix);

      scs = new pfSCS(*matrix);
      if ((i+j+(size%2))%2)
scs->addChild(blackNode);  
      else
        scs->addChild(whiteNode);
      group->addChild(scs);
    }

  return(group);

}


next up previous
Next: Konfigurationsfile .caverc Up: Programmieren mit der CAVELib Previous: Performer (C API)
Mail to: Oliver Schönbrunner
Virtual Reality Center