Each function in PS-ERT is documented in $BDI_PEOPLESHOP/doc/psert or here. Unfortunately, the official documentation is vague and incomplete. This primer will hopefully fill in the gaps and describe in more detail how to use PS-ERT in the VR-Lab lab. A complete example of a Performer program using PS-ERT is pplhi, which, at the time of writing this, is located in the repository under vrlab/src/mainprogs/examples/pplhi.
PS-ERT is capable of running on top of DirectX, OpenGL, or Performer. This primer will only cover PS-ERT running on top of Performer.
PS-ERT consists of several C++ classes:
Makefile.ppl contains all the libraries and includes needed to compile PS-ERT into a Performer program. It is based on the makefiles in $BDI_PEOPLESHOP/psert_examples/pf_examples.
There are two important variables defined in Makefile.ppl:
The PS-ERT library is written in C++, but it seems to need to link
against the C version of the Performer library. Compile using
-DPF_CPLUSPLUS_API=0.
This tells Performer to use the C version of the library even when compiling
in C++.
#include<Performer/pf.h>
//Main Performer header file
#include<peopleshop_ert_pf.h> //PS-ERT
classes and PS-ERT/Performer connection
#include<peopleshop_ert_exface.h> //Required for expressive
faces
#include<peopleshop_ert_perl.h> //Only required
if using Perl scripts
#include<libbdilog.h>
//Required for debugging output
#include <Performer/pf.h>
#include <Performer/pfdu.h>
#include <3dsound.h>
#include "psert_util.h"
main(){
pfScene*scene;
pfChannel*channel;
/* set up performer scene and channel
...
*/
/*****************/
/** setup psert **/
/*****************/
//initialize PSERT with performer channel and scene
PSERT psert(channel,scene);
//load first .pss file
psert.sp()->load("bob.pss");
//merge other .pss files
psert.sp()->merge("alan.pss");
//get handles to character by character name in scenario file(s)
CharWrapper*bob=psert.get_char("bob");
CharWrapper*alan=psert.get_char("alan");
//set position, heading, and sound_objnum (see 3dsound.h)
bob.setup(1,1,0,90,1); // setup(x,y,z,heading,sound_objnum)
alan.setup(4,1,0,90,2);
/***********************************/
/** setup 3dsound (see 3dsound.h) **/
/***********************************/
// s3d_init(nose_axis,top_axis,3dsound_server);
s3d_init(PF_Y,PF_Z,"hoover");
//associate sounds with sound objects
// s3d_obj_init(objnum,sndnum,TRIGGERED/LOOP,remote_filename)
s3d_obj_init(1,0,TRIGGERED,"sound1.wav"); //bob's sound 0
s3d_obj_init(1,1,TRIGGERED,"sound2.wav"); //bob's sound 1
s3d_obj_init(1,2,LOOP, "sound3.wav"); //bob's sound 2
s3d_obj_init(2,0,TRIGGERED,"sound4.wav"); //alan's sound 0
s3d_obj_init(2,1,LOOP, "sound5.wav"); //alan's sound 1
for(long frame=0;;frame++){
/************/
/** timing **/
/************/
static float lasttime=0;
float t = pfGetTime(); //current time (according to performer)
float dt = t-lasttime; //frametime
lasttime = t;
/*************************/
/** character behaviors **/
/*************************/
//CharWrapper can use both CharWrapper methods and
// psScenarioCharacter methods
if(frame==100) bob->set_desired_action_by_name("walk");
if(frame==200) alan->set_emotion("Smile",1.0);
if(frame==300) {
alan->set_emotion("all",0.0);
alan->say("greetings.phn",1);
}
psert.update(t); //updates characters' 3dsound position
// and graphical positions
/*********************************************************/
/** update 3dsound positions and commit (see 3dsound.h) **/
/*********************************************************/
pfCoord viewer_head_position;
/* get viewer_head_position;
...
*/
//tell 3dsound utility position of listener's head
s3d_head(viewer_head_position,dt);
//commit 3dsound changes
s3d_commit();
/*******************************************************/ /* performer draw commands ... */ } }