Skip to content
Snippets Groups Projects
szgPartiview.cc 42.6 KiB
Newer Older
		 fpt.x[0],fpt.x[1],fpt.x[2], minlen);


  } else if(!strncmp( argv[0], "jump", 4 )) {
    Point xyz;
    float aer[3];
    static int stupid[3] = {1,0,2};	/* aer -> rx ry rz */
    Matrix c2w;
    parti_getc2w( &c2w );
    tfm2xyzaer( &xyz, aer, &c2w );
    if(argc>1) {
      for(i=1; i<argc && i<4+3; i++) {
	if(i-1<3) xyz.x[i-1] = getfloat(argv[i], xyz.x[i-1]);
	else aer[stupid[i-4]] = getfloat(argv[i], aer[stupid[i-4]]);
      }
      xyzaer2tfm( &c2w, &xyz, aer );
      parti_setc2w( &c2w );
    }
    msg("jump %g %g %g  %g %g %g  (XYZ RxRyRz)",
	xyz.x[0],xyz.x[1],xyz.x[2],
	aer[1],aer[0],aer[2]);
   
  } else if(!strncmp( argv[0], "home", 4 )) {//marx version 0.7.03
    Point xyz;
    float aer[3];
    static int stupid[3] = {1,0,2};	/* aer -> rx ry rz */
    Matrix c2w;
    parti_getc2w( &c2w );
    tfm2xyzaer( &xyz, aer, &c2w );
    if(argc>1) {
      for(i=1; i<argc && i<4+3; i++) {
	if(i-1<3) xyz.x[i-1] = getfloat(argv[i], xyz.x[i-1]);
	else aer[stupid[i-4]] = getfloat(argv[i], aer[stupid[i-4]]);
      }
      xyzaer2tfm( &c2w, &xyz, aer );
      parti_setc2w( &c2w );
      ppszg.home[0] = xyz.x[0]; ppszg.home[1] = xyz.x[1];  ppszg.home[2]  = xyz.x[2];

    //ppszg.home[3] = aer[0];   ppszg.home[4] = aer[1];    ppszg.home[5]  = aer[2]; bug in releases >= 0.7.03 
      ppszg.home[3] = aer[1];   ppszg.home[4] = aer[0];    ppszg.home[5]  = aer[2]; //version 0.7.05 fix for the line above

    }
    msg("home %g %g %g  %g %g %g  (XYZ RxRyRz)", ppszg.home[0], ppszg.home[1], ppszg.home[2], ppszg.home[3], ppszg.home[4], ppszg.home[5]);  

  } else if((!strcmp( argv[0], "rdata" ) || !strcmp(argv[0], "readpath"))
		&& argc>1) {
	bool freet = false;
	char *tfname = argv[1];
	char *realfile = findfile( fromfname, tfname );
	if(realfile == NULL) {
	    tfname = (char *)malloc(strlen(argv[1]) + 32);
	    freet = true;
	    sprintf(tfname, "data/record/%s%s", argv[1],
		strstr(argv[1], ".wf") ? "" : ".wf");
	    realfile = findfile( NULL, tfname+12 );
	}
	if(realfile == NULL)
	    realfile = findfile( fromfname, tfname );
	if(realfile)
	    parti_readpath( realfile );
	else
	    msg("%s: can't find \"%s\" nor data/record/... nor ...wf",
		argv[0],argv[1]);
	if(freet)
	    free(tfname);

  } else if(!strcmp( argv[0], "play" )) {
	parti_play( argc>1 ? rejoinargs(1, argc, argv) : NULL );

  } else if(!strcmp( argv[0], "frame" )) {
	CONST struct wfpath *pp;
	i = parti_frame( argv[1], &pp );
	msg("frame %d (of %d..%d)", pp->curframe,
		pp->frame0, pp->nframes + pp->frame0 - 1);

  } else if(!strcmp( argv[0], "interest") || !strcmp( argv[0], "int" ) ||
		!strcmp( argv[0], "center" ) ||
		!strcmp( argv[0], "cen" )) {
	Point cen;
	float censize = parti_getcensize();
	parti_getcenter( &cen );
	if(argc > 1) {
	    sscanf(argv[1], "%f%*c%f%*c%f%*c%f",
		&cen.x[0],&cen.x[1],&cen.x[2], &censize);
	    if(argc > 3)
		for(i=0;i<3;i++)
		    cen.x[i] = getfloat(argv[i+1], cen.x[i]);
	    if(argc == 3 || argc == 5)
		sscanf(argv[argc-1], "%f", &censize);
	    parti_center( &cen );
	    if(censize != parti_getcensize())
		parti_censize( censize );
	}
	msg("center %g %g %g  %g(radius)", cen.x[0],cen.x[1],cen.x[2], censize);

  } else if(!strcmp( argv[0], "censize" )) {
	if(argc>1)
	    parti_censize( getfloat(argv[1], parti_getcensize()));
	msg("censize %g  (interest-marker size)", parti_getcensize());

  } else {
	return 0;
  }

  return 1;
}

void pp_ui_postinit() {
  parti_set_timebase( ppszg.st, 0.0 );
  parti_set_timestep( ppszg.st, 0.0 );
  parti_set_running( ppszg.st, 0 );
  parti_set_fwd( ppszg.st, 1 );
}

void clearBuffer(char* buf, int bufsize)
{
  for(int i=0; i < bufsize; i++)
  {
    buf[i] = '\0';
  }
}

PpCmd::PpCmd( CmdType type, int argc, char **argv )
{
    this->type = type;
    this->argc = argc;
    this->argv = argv;
}

PpCmd::~PpCmd() {
}

int PpCmd::frozenLen() const {
    int len = 2*argc+2;
    for(int i = 0; i < argc; i++)
	len += strlen(argv[i]);
    return len;
}

/* Serialize the command, and append result to 'buf' */
int PpCmd::freezeInto( string &buf ) const { 
    int ineed = buf.size() + frozenLen() + 1;
    if(buf.capacity() < ineed)
	buf.reserve( 2*ineed+1 );

    for(int i = 0; i < argc; i++) {
	buf.append( 1, (char)type );
	buf.append( argv[i], strlen(argv[i]) );
	buf.append( 1, '\000' );
    buf.append( 1, '\000' );	// mark end of last arg
    return buf.size();
int PpCmd::thawFrom( char *buf, int &offset, bool copystrings ) {
    int p = offset;

    argc = 0;
    argv = 0;
    type = (CmdType) buf[p];
    switch(type) {
    case CMD_DATA:
    case CMD_CONTROL:
	break;		// OK.

    default:
	msg("PpCmd::thawFrom(): Trouble decoding %p at offset %d (got 0x%x not 0/1/2)", buf, p, buf[p]);
	type = CMD_NONE;
	return -1;
    }

    // count args
    do {
	p++;
	p += strlen( &buf[p] ) + 1;
	argc++;
    } while(buf[p] != 0);
    argv = new char *[argc+1];
    // msg("Found %d args in thawing %d bytes from offset %d", argc, p-offset, offset);
    // copy args
    p = offset;
    for(int a = 0; a < argc; a++) {
	p++;
	argv[a] = copystrings ? strdup(&buf[p]) : &buf[p];
	p += strlen(&buf[p]) + 1;
    }
    argv[argc] = 0;
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////

Ppszg::~Ppszg() {
    delete scene;
    // delete clk;  Don't delete the clock -- might be shared with other objects
}
Ppszg::Ppszg() {
    scene = new PvScene();
    st = NULL;
    clipnear_ = 0.1;
    clipfar_ = 2500;
    focallen_ = 3;

    snapfmt = NULL;
    snapfno = 0;
    pickrange = 3.5;
    memset(home, 0, sizeof(home));

    clk = new SClock();
    clock_init( clk );
    clock_set_speed( clk, 1.0 );
    clk->continuous = 1;
    clk->walltimed = 1;

    memset( &path, 0, sizeof(path) );
    playing = 0;
    playevery = 0;
    playidling = 0;
    playspeed = 20;
    framebase = 1;
    playtimebase = 0;
    playloop = 0;

    timebasetime = 0;

    subcam = 0;
    /* List of connected arSockets */
    socketList = NULL;
bool Ppszg::onStart( arSZGClient& SZGClient ) {
  /*
   * Add Transfer Fields to Framework so data is
   * accessible and syncronized to all clients
   * Added July 23, 2008 William Davis
   */
  processid = SZGClient.getProcessID();	// for msg() log files

  addTransferField("curtime", &(ppszg.clk->curtime), AR_DOUBLE, 1);
  addTransferField("running", &(ppszg.clk->running), AR_INT, 1);
  addTransferField("continuous", &(ppszg.clk->continuous), AR_INT, 1);
  addTransferField("center_", &(ppszg.scene->center_), AR_FLOAT, 3);
  addTransferField("censize_", &(ppszg.scene->censize_), AR_FLOAT, 1);
  addTransferField("quitnow", &(ppszg.quitnow_), AR_INT, 1);
  addInternalTransferField( "commands", AR_CHAR, 1 );
  parti_bgcolor( "0 0 0" );

  parti_add_commands( pp_parse_args, "partiview", NULL );
  parti_add_reader( pp_read, "partiview", NULL );
  plugin_init();


  // pp_ui_init();
  // ppui.view->pickbuffer( COUNT(pickbuffer), pickbuffer );

  parti_clip( "0.1", "2500" );
  parti_censize( 1.0 );
  // parti_pickrange( 3.5 );

  parti_object( "g1", NULL, 1 );
  readrc( &ppszg.st );

  for(int i = 1; i < globalArgc; i++) {
    if(0==strcmp(globalArgv[i], "-c") && i+1 < globalArgc) {
	i++;
	int len = strlen(globalArgv[i]);
	int maxargs = len/2 + 2;    // max possible number of args
	char **av = new char *[maxargs];
	char tbuf[ 2*len + 1024 ];
	int ac = tokenize( globalArgv[i], tbuf, maxargs, av, NULL );
	if(! specks_parse_args( &ppszg.st, ac, av )) {
	    msg("-c: Unrecognized control command: %s", globalArgv[i]);
	}
	delete av;
    } else if(0 == strcmp(globalArgv[i], "-fly")) {
	flyer.config( globalArgv[++i] );
    } else if(0 == strcmp(globalArgv[i], "-plog")) {
	partiLog++;
    } else {
	specks_read( &ppszg.st, globalArgv[i] );
    }

#if 0
bool arMasterSlaveFramework::addInternalTransferField( std::string fieldName,
                                                         arDataType dataType,
                                                         int numElements );

The pointer argument is omitted, and the numElements argument now denotes the initial size. The size can be changed by calling:

  bool arMasterSlaveFramework::setInternalTransferFieldSize( std::string fieldName,
                                                             arDataType dataType,
                                                             int newSize );
#endif


void Ppszg::onWindowStartGL( arGUIWindowInfo * ) {
  set_dsp_context( 0 );	/* assign a display context, so texture code can track window changes */
}

void Ppszg::onPreExchange( void ) {	// called on master only
  // do navigation...
  // process commands read from network...
  //   and package any with
  /* Here we want to do the listening on the sockets to interpret
   * any commands we might receive over them
   */
  static int socketid = 0;
  if(ppszg.listenSocket == 0) {
    // Create listener socket.  Do this only in a *live* master
    /* arSockets - originally from salimiman by Jim Crowell */
    msg("master on pid %d listening on port 8675", processid);
    listenSocket = new arSocket(AR_LISTENING_SOCKET);
    listenSocket->ar_create();
    listenSocket->setSendBufferSize(2048);
    listenSocket->setReceiveBufferSize(2048);
    listenSocket->reuseAddress(true);
    list<string> acceptMask;
    listenSocket->setAcceptMask(acceptMask);
    /* Bind to port 8675 */
    listenSocket->ar_bind(NULL, 8675);
    listenSocket->ar_listen(256);
  }

  if(ppszg.listenSocket->readable())
  {
    bufferedSocket* sockp = new bufferedSocket();
    arSocketAddress addr;
    ppszg.listenSocket->ar_accept(sockp, &addr);
    msg("process %d accepted connection", processid);
    sockp->setID(socketid++);
    sockp->next = ppszg.socketList;
    ppszg.socketList = sockp;
  /* "fly" navigation if selected */
  flyer.navUpdate();

  cmdbuf_.clear();		// wipe master->slaves buffer for this cycle

  /* Now read data into the buffer */
  bufferedSocket* sock = ppszg.socketList;
  bufferedSocket** previousSocketp = &ppszg.socketList;
  while( sock != NULL ) {
	int len = sock->poll();
	while(len >= 0) {		// repeat for all the lines in buffer
            int maxargs = len/2 + 2;    // max possible number of args
            char **av = new char *[maxargs];
            char tbuf[ 2*len + 1024 ];
		// temp buffer.  Extra room allows for $expansion etc.
		// XXX should pass this length to tokenize!

            int ac = tokenize( sock->str(), tbuf, maxargs, av, NULL );

            if(ac > 0) {
		// Not a comment nor a blank line.  Try to parse it locally.
		if( ! specks_parse_args( &ppszg.st, ac, av ) ) {
		    msg("Unrecognized control command: %s", sock->str());
		}
		// In any case, pass it on to slaves
		PpCmd cmd( CMD_CONTROL, ac, av );
		cmd.freezeInto( cmdbuf_ );
            }
	    delete av;

            len = sock->consume();      // Done processing that line.  Got another on hand?
	}
	   *previousSocketp = sock->next;
	   delete sock;
	} else {
	    previousSocketp = &sock->next;
	}
	sock = *previousSocketp;
  }

  // Now ship bundled commands to slaves

  if(cmdbuf_.size() == 0)
      cmdbuf_.append( 1, '\000' );	// ensure nonzero size

  setInternalTransferFieldSize( "commands", AR_CHAR, cmdbuf_.size() );

  if(cmdbuf_.size() > 1 && getenv("CMDTEST")) {
	PpCmd tcmd;
	int offset = 0;
	int room = cmdbuf_.size();
	    msg("Got %d-bytes of command packet", room-1);	// XXX DEBUG
	while(offset+1 < room) {
	    int oof = offset;
	    if( tcmd.thawFrom( &cmdbuf_[0], offset, false ) < 0)
		break;
	    // false -> build argc/argv which point into cmdp string directly
	    msg("Offset %d..%d: command [%d] %s", oof,offset, tcmd.argc, rejoinargs( 0, tcmd.argc, tcmd.argv ));
            if(tcmd.argc <= 0 || oof == offset) {
                msg("Had enough: tcmd.argc=%d, offset %d, room %d", tcmd.argc, offset, room);
                break;
            }
        }
  int room = 0;
  char *cmdp = (char *)getTransferField( "commands", AR_CHAR, room );
  if(cmdp == 0 || room != cmdbuf_.size()) {
    msg("panic: transfer field size %d != the size %d we told it to be!\n",
		room, cmdbuf_.size());
  } else {
       memcpy( cmdp, &cmdbuf_[0], room );
  }

  /*
   * Added July 23, 2008 William Davis
   * Forces the framework to listen to updates to navigation matrix
   * changed from a "jump" command
   */ 
  navUpdate();

  clock_tick( ppszg.clk );		// let time advance
void Ppszg::onPostExchange( void )	// called on master + slaves
{
    if(! this->getMaster() ) {
	// We're a slave.  Decode any commands passed by master this cycle.
	int room = 0;
	char *cmdp = (char *)getTransferField( "commands", AR_CHAR, room );
	if(cmdp == 0) {
	    static int once = 1;
	    if(once) msg("Ppszg::onPostExchange: can't get transfer field \"commands\"");
	    once = 0;
	    return;
	}

#if 0
	if(room > 1) {
	    msg("postExchange: GOT %d-bytes of cmd pkt", room-1);
	    char unk[512];
	    int u,uu;
	    for(u=uu=0; u<room; u++)
		uu += sprintf(&unk[uu], cmdp[u]<' ' ? "\\x%02x" : "%c", cmdp[u]);
	    unk[uu] = '\0';
	    msg("Received: \"%s\"", unk); // XXX debug
	}
#endif

	int offset = 0;
	while(offset+1 < room) {
            int oof = offset;
	    bool done;
	    done = (pp.thawFrom( cmdp, offset, false ) < 0);
	    // false -> build argc/argv which point into cmdp string directly
            if(done || oof >= offset || pp.argc <= 0) {
              msg("Had enough of cmd pkt: done %d offset %d was %d, room %d, argc %d, type 0x%x", done, offset, oof, room, pp.argc, pp.type);
              break;
            }
	    msg("postExchange: processing '%s'", rejoinargs(0,pp.argc,pp.argv));
	    if(pp.type == CMD_CONTROL) {
		if(! specks_parse_args( &ppszg.st, pp.argc, pp.argv ) ) {
		    warn("Unrecognized control command on slave: %s",
			rejoinargs( 0, pp.argc, pp.argv ));
		}
	    } else {
		warn("can only handle control cmds, not: %s",
		    rejoinargs(0, pp.argc, pp.argv));
	    }
	}
    }

    /* terminate if we're asked to... */
    /* is this the right way to do this? */
    if(ppszg.quitnow_)
	exit(0);
void Ppszg::onWindowInit( void ) {	// clear to background...
    glClearColor( bgcolor.x[0], bgcolor.x[1], bgcolor.x[2], 1 );
    ar_defaultWindowInitCallback();
}

void Ppszg::onDraw( arGraphicsWindow& win, arViewport& vp ) {
     * Added July 23, 2008 William Davis
     * Loads the navigation matrix into the framework, making
     * sure we listen to the changes enacted by the "jump" command
     * in parti_setc2w()
     */
    loadNavMatrix();

void Ppszg::onDisconnectDraw( void ) {
    glClearColor( 1, .1, .1, 1 );
    glClear( GL_COLOR_BUFFER_BIT );
}

void Ppszg::onCleanup( void ) {
void Ppszg::onUserMessage( const string& messageBody ) {
    // called in master on "dex <N> user <some message for this program>"
    // parse messageBody, add to command queue for next preExchange time
}

#ifdef __linux__
#include <GL/glut.h>	// hack: Syzygy uses glutWireSphere() in simulator mode, but freeglut insists on glutInit() first
#endif

#ifdef __linux__
    int targc = 1;		// rest of hack.
    glutInit( &targc, argv );
#endif
    globalArgc = argc; //Make these two variables accessible to the
    globalArgv = argv; // onStart callback

    if( ! ppszg.init( argc, argv ) ) {
	fprintf(stderr, "arMasterSlaveFramework::init() failed, giving up...\n");
	exit(1);
    }

    if( ! ppszg.start() ) {
	fprintf(stderr, "arMasterSlaveFramework::start() failed, giving up...\n");
	exit(1);
    }
    // Shouldn't reach here.
    fprintf(stderr, "Shouldn't reach here.\n");
    exit(2);
}