From: Dan Johnston (dan.johnston++at++nrc.ca)
Date: 03/25/2003 06:25:44
Jürgen Gotschlich wrote:
> Goncalo,
>
> well, I guess you're right in implementing this threading model. So I'll
> have to look forward in this way.
> But I read in some older articles that performer internally is based on
> sproc threading and therefore can get into seriously troubles when
> mixing with pthreads. Did they change their internal coding with respect
> to pthreads ?
>
> Again a question about shared memory: Infact, using 2 communicating
> processes will need to implement an interprocess communication based on
> shared memory. But aren't 2 threads (spawned from 1 process) actually
> using the same portion of memory ?
>
> I posted this as well directly to info-performer++at++sgi.com to read for
> other interested users.
>
> Thanks for your help
>
> Juergen
> -------------------------------------------
>
> Goncalo Carvalho wrote:
> >
> > Hey,
> >
> > >
> > > What are you using to spawn this ?
> > >
> >
> > Pthreads, but you can fork if you like.
> >
>
Well... I wasn't going to add to this thread, but the discussion has
continued for a few days and several messages now. I guess I
can add another option.
I also found it very useful to have UDP messages to update
pfDCS values so that objects in a virtual environment move
in "real time" (i.e. fast enough) in response to tracker data
from hardware.
So I added two UDP sockets to my rapid development
library pfAPC (mars.imti.nrc.ca, anonymous ftp) and
allow any application built with this library to use
them.
It is very simple to do, and I will attach the source of
one such example below. My experience is that the
objects move smoothly and fast as long as the sender
of data is running at something like 150ms. This was
run on both Onyx and Octane computers (and Linux)
OK, So it is not my best code. I just slapped the test application
together a few weeks ago to show one object moving in
a semi-complex environment.
It should work on MS-Windows platforms also, but I'm
still testing WinSock support for my library.
Hope this helps!.
--
___|__ |
/ | \ ||\ Daniel (Dan) Johnston
/___|___\ || \ Dan.Johnston++at++nrc.ca
_____|____ || \ National Research Council of Canada, London, ON
| | | || \ Integrated Manufacturing Technologies Institute
\___| | | ||____\ Tel: (519) 430-7081 Fax: (519) 430-7090
\_o_\___|____|_|______\_ Inst: http://www.nrc.ca/imti
\ o / These opinions are my own! Not those of NRC.
\________________/ Virtual Reality:
http://www.nrc.ca/imti/vetc/home.html
More Tall Ships - Fewer Computers!
++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++/*
*
* interaction.c: simple Performer program from programmer's guide
* Modified to make use of pfAPC library for pipe/window setup and
* frustrum calculations.
* This version will provide an interactive window on top of
* the user-specified display pipe. This extra, 2D winow can be
* used for GUI interaction.
*
* Used for the pfAPC documentation. Copy, but do not modify!
*
* Copyright National Research Council of Canada
* All rights reserved!
* Author: Dan Johnston 2001-Jan-02
*
* $Revision: 1.4 $
* $Date: 2001/08/15 19:32:58 $
*
*/
#include "./include/pfapc.h"
/* a 'global reference to the interactive window */
APCipipe ipipe;
APCsetup setup;
pfDCS *objDCS, *offsetDCS;
pfVec3 offsetXYZ;
pfVec3 offsetHPR;
static void
handleMessage(char *messageBuffer,int messageSize )
{
int value;
static pfVec3 initLoc;
static pfVec3 initRot;
pfVec3 offsetLoc;
pfVec3 offsetRot;
pfVec3 fobLoc;
pfVec3 fobRot;
int dummy;
static int counter = 0;
// printf( "Received message of size %d \n", messageSize);
sscanf( messageBuffer, "%d %f %f %f %f %f %f %f %f %f %f %f %f",
&dummy, &offsetLoc[0], &offsetLoc[1], &offsetLoc[2],
&offsetRot[0], &offsetRot[1], &offsetRot[2],
&fobLoc[0], &fobLoc[1], &fobLoc[2],
&fobRot[0], &fobRot[1], &fobRot[2]);
// printf( "X %f", offsetLoc[0] );
// printf( " Y %f", offsetLoc[1] );
// printf( " Z %f \n", offsetLoc[2] );
// printf( "H %f", offsetRot[0] );
// printf( " P %f", offsetRot[1] );
// printf( " R %f \n", offsetRot[2] );
// printf( "fX %f", fobLoc[0] );
// printf( " fY %f", fobLoc[1] );
// printf( " fZ %f \n", fobLoc[2] );
// printf( "fH %f", fobRot[0] );
// printf( " fP %f", fobRot[1] );
// printf( " fR %f \n", fobRot[2] );
/* set the position and orientation of the object from fob sensor */
if( counter == 0 )
{
initLoc[0] = 0.0f;
initLoc[1] = 0.0f;
initLoc[2] = 0.0f;
initRot[0] = 0.0f;
initRot[1] = 0.0f;
initRot[2] = 0.0f;
counter++;
}
else if( counter < 11 )
{
/* average the reading (if not zero) as our initial position */
if( fobLoc[0] == 0.0f )
printf("Waiting for fob...\n");
else
{
/* average the measured values */
initLoc[0] = (initLoc[0] + fobLoc[0]) / 2.0f;
initLoc[1] = (initLoc[1] + fobLoc[1]) / 2.0f;
initLoc[2] = (initLoc[2] + fobLoc[2]) / 2.0f;
initRot[0] = (initRot[0] + fobRot[0]) / 2.0f;
initRot[1] = (initRot[1] + fobRot[1]) / 2.0f;
initRot[2] = (initRot[2] + fobRot[2]) / 2.0f;
// printf( "Avg X %f", initLoc[0] );
// printf( " Avg Y %f", initLoc[1] );
// printf( " Avg Z %f\n", initLoc[2] );
// printf( "Avg H %f", initRot[0] );
// printf( " Avg P %f", initRot[1] );
// printf( " Avg R %f\n", initRot[2] );
counter++;
}
}
else
{
/* use the fob data to set position of object */
/* Add the default marker offset to the fob delta value */
pfDCSTrans( offsetDCS, offsetXYZ[0]+offsetLoc[0]+initLoc[0]-fobLoc[0],
offsetXYZ[1]+offsetLoc[1]+initLoc[1]-fobLoc[1],
offsetXYZ[2]+offsetLoc[2]+initLoc[2]-fobLoc[2] );
pfDCSRot( offsetDCS, offsetHPR[0]+offsetRot[0]+initRot[0]+fobRot[0],
offsetHPR[1]+offsetRot[1]+initRot[1]+fobRot[1],
offsetHPR[2]+offsetRot[2]+initRot[2]+fobRot[2] );
// printf( "Xobj %f", initLoc[0]+fobLoc[0]);
// printf( " Yobj %f", initLoc[1]+fobLoc[1] );
// printf( " Zobj %f \n", initLoc[2]+fobLoc[2] );
}
// for( value = 0; value < messageSize; value++)
// printf("%d %x\n", value, messageBuffer[value]);
}
static void
myEventHandler ( APCsetup setup )
{
int i, j;
int key, dev, val, numDevs;
pfuEventStream *pEvents;
static int isVisible = PF_OFF;
pEvents = apSetupEventGetEventStream( setup );
numDevs = pEvents->numDevs;
for ( j=0; j < numDevs; ++j)
{
dev = pEvents->devQ[j];
val = pEvents->devVal[j];
if ( pEvents->devCount[dev] > 0 )
{
switch ( dev )
{
case PFUDEV_KEYBD:
for ( i=0; i < pEvents->numKeys; ++i )
{
key = pEvents->keyQ[i];
if ( pEvents->keyCount[key] )
{
switch ( key )
{
case 'z':
/* toggle visibility of the interaction window */
isVisible = !isVisible;
apIPipeVisible( ipipe, isVisible );
break;
default:
break;
}
}
}
pEvents->devCount[dev] = 0;
break;
default:
break;
}
}
}
pEvents->numKeys = 0;
pEvents->numDevs = 0;
}
/*
* Usage() -- print usage advice and exit. This
* procedure is executed in the application process.
*/
static void
Usage (void)
{
pfNotify(PFNFY_FATAL, PFNFY_USAGE, "Usage: interaction file.ext\n");
exit(1);
}
int
main (int argc, char *argv[])
{
pfNode *model, *model1, *model2;
pfGroup *sceneRoot;
pfDCS *robotDCS;
int messageSize;
char messageBuffer[4096];
if (argc < 4)
Usage();
/* now load the default setup config file (if any) into the structure */
setup = apLoadSetup( ".apsetup" );
/* open a socket for object position messages */
/* define the port for object markers */
apSetupSetUserPort( setup, 10035 );
apSetupPreMultiprocess( setup );
/* Load all loader DSO's before pfConfig() forks */
pfdInitConverter(argv[1]);
pfdInitConverter("obj");
pfdInitConverter("flt");
apSetupPostMultiprocess( setup );
/* Read a single file, of any known type. */
if ((model = pfdLoadFile(argv[1])) == NULL)
{
apSetupExit( setup );
exit(-1);
}
/* Attach loaded file to a new pfScene. */
sceneRoot = apSetupScene( setup );
pfAddChild( sceneRoot, model);
offsetDCS = pfNewDCS();
offsetXYZ[0] = 90.0f;
offsetXYZ[1] = -80.0f;
offsetXYZ[2] = 0.0f;
offsetHPR[0] = -180.0f;
offsetHPR[1] = 0.0f;
offsetHPR[2] = 0.0f;
pfDCSTrans( offsetDCS, offsetXYZ[0], offsetXYZ[1], offsetXYZ[2] );
pfDCSRot( offsetDCS, offsetHPR[0], offsetHPR[1], offsetHPR[2] );
pfDCSScale( offsetDCS, 20.0f );
pfAddChild( sceneRoot, offsetDCS );
objDCS = pfNewDCS();
/* add model of object, at selected scale */
if ((model1 = pfdLoadFile(argv[2])) == NULL)
{
apSetupExit( setup );
exit(-1);
}
pfAddChild( offsetDCS, objDCS );
pfAddChild( objDCS, model1 );
robotDCS = pfNewDCS();
/* add model of robot, at selected scale */
if ((model2 = pfdLoadFile(argv[3])) == NULL)
{
apSetupExit( setup );
exit(-1);
}
pfAddChild( sceneRoot, robotDCS );
pfAddChild( robotDCS, model2 );
pfDCSScale( robotDCS, 1.0f );
/* now set up the interaction window(s) */
apSetupInitPipes( setup );
apSetupEventHandler( setup, myEventHandler );
apSetupTetherViewpoint( setup, (pfNode *)offsetDCS );
apSetupInitViewpoint(setup, model2);
/* Simulate until the user exits */
while ( apSetupQuit( setup ) == PF_OFF )
{
/* Go to sleep until next frame time. */
pfSync();
/* handle other latency critical stuff - ie setting viewpoint */
apUpdateViewpoint( setup );
/* Initiate cull/draw for this frame. */
pfFrame();
apHandleEvents( setup );
if( apSetupCheckUserMessage( setup, messageBuffer, &messageSize ) )
handleMessage( messageBuffer, messageSize );
}
/* Terminate parallel processes and exit. */
apIPipeDelete( ipipe );
apSetupExit( setup );
}
+++++++++++++++++++++++++++++++++++++++++++++++
This archive was generated by hypermail 2b29 : Tue Mar 25 2003 - 06:28:06 PST