From: Paolo Farinelli (paolo++at++sgi.com)
Date: 02/27/2002 16:22:33
Hi Bram,
Performer should guarantee that the entire sub-tree of a group
node for which DRAW callbacks are bound is rendered between
calls to node's pre-draw and post-draw callbacks.
From man pfNode (page 11):
> Note that in contrast [to pre- and post- CULL funcs], pre- and
> post-DRAW funcs on a node are guaranteed to bracket the contents
> of the node, and therefore they prevent the interleaving of the
> contents of the node with the contents of other nodes.
I have also put together a small example that:
1. loads a model,
2. creates several DCSs and adds the model as a child to each DCS,
3. allows user to pick to select one instance of the loaded model,
4. Binds DRAW callbacks to the selected DCS, unbinds when deselected.
5. pre-draw callback overrides highlighting and forces it ON.
6. post-draw callback sets highlighting override OFF.
This seems to work ok, so maybe it will help you understand why
this method didn't work for you..
Regards,
Paolo
Bram Stolk wrote:
>
> Yair, Paolo,
>
> Many thanks for the suggestion.
> I have implemented it, but it turns out to be unusable.
>
> The problem is that DRAW traversals have no relation
> to the scene-graph, as I understand it.
>
> This means, that when putting callbacks on a DCS, there
> is no garantee that the entire sub-tree is drawn during
> pre and post visits of the DCS.
> I do not only want the geometry directly under the DCS
> to lit up, but all geometry of tree below it.
>
> So that would leave me only with a clone-hack?
> I'm affraid that calling the pfNode::clone() member
> func won't cut it as it will share geometry?
>
> thanks,
>
> Bram
>
> On Wed, 20 Feb 2002 18:20:31 -0800 (PST)
> Yair Kurzion <yair++at++polygon.engr.sgi.com> wrote:
>
> > Hi Bram !
> >
> > Why not add draw callbacks on the selected DCS ? You can add and remove
> > DRAW callbacks from nodes in an MP-safe way.
> >
> > In the pre-draw callback, do:
> >
> > pfOverride(PFSTATE_HIGHLIGHT |
> > PFSTATE_ENHIGHLIGHTING,
> > PF_OFF);
> >
> > pfApplyHlight(hl); /* Some highlight object */
> > pfEnable(PFEN_HIGHLIGHTING);
> >
> > pfOverride(PFSTATE_HIGHLIGHT |
> > PFSTATE_ENHIGHLIGHTING,
> > PF_ON);
> >
> > and in the post-draw callback do:
> >
> > pfOverride(PFSTATE_HIGHLIGHT |
> > PFSTATE_ENHIGHLIGHTING,
> > PF_OFF);
> >
> > OR, if you want to be more efficient, create one new geode and make it a clone
> > of your original instanced geode. Set highlight on the new geode. When you pick
> > a geode, remove it from its DCS and place the new geode instead. When you
> > un-pick the geode, restore the original un-highlighted geode to its DCS.
> >
> > -yair
> >
> >
> >
> > > I have a performer scene with hundreds of DCSes, which all contain the
> > > same geode.
> > >
> > > When implementing picking, I want a single geode to light up, when touched
> > > with a cursor (CAVE wand in my case).
> > >
> > > I currently use pfHighlight, and I enable highlighting for the geostates
> > > of the geosets of the selected geode.
> > >
> > > Ofcourse, ALL the geometry in my scene lights up, as I reuse a single
> > > piece of geometry in a lot of DCSes.
> > >
> > > How can I achieve the desired highlighting without replicating the geometry?
> > >
> > > I'm affraid I will have to remove and add children from the affected DCS?
> > >
> > > Thanks,
> > >
> > > Bram
> > >
-- Paolo Farinelli paolo++at++sgi.com Member of Technical Staff, OpenGL Performer 1-650-933-1808 Silicon Graphics 1600 Amphitheatre Pkwy, Mountain View, CA 94043
/* * Copyright 1995, Silicon Graphics, Inc. * ALL RIGHTS RESERVED * * This source code ("Source Code") was originally derived from a * code base owned by Silicon Graphics, Inc. ("SGI") * * LICENSE: SGI grants the user ("Licensee") permission to reproduce, * distribute, and create derivative works from this Source Code, * provided that: (1) the user reproduces this entire notice within * both source and binary format redistributions and any accompanying * materials such as documentation in printed or electronic format; * (2) the Source Code is not to be used, or ported or modified for * use, except in conjunction with OpenGL Performer; and (3) the * names of Silicon Graphics, Inc. and SGI may not be used in any * advertising or publicity relating to the Source Code without the * prior written permission of SGI. No further license or permission * may be inferred or deemed or construed to exist with regard to the * Source Code or the code base of which it forms a part. All rights * not expressly granted are reserved. * * This Source Code is provided to Licensee AS IS, without any * warranty of any kind, either express, implied, or statutory, * including, but not limited to, any warranty that the Source Code * will conform to specifications, any implied warranties of * merchantability, fitness for a particular purpose, and freedom * from infringement, and any warranty that the documentation will * conform to the program, or any warranty that the Source Code will * be error free. * * IN NO EVENT WILL SGI BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO * USE, THE SOURCE CODE. * * Contact information: Silicon Graphics, Inc., * 1600 Amphitheatre Pkwy, Mountain View, CA 94043, * or: http://www.sgi.com * * simple.c: simple Performer program for programmer's guide * * $Revision: 1.50 $ $Date: 2000/10/06 21:26:37 $ * */ #include <Performer/pf.h> #include <Performer/pfutil.h> #include <Performer/pfdu.h>
#define GAPWIDTH 0.5f
typedef struct ModelData { pfNode *root; pfDCS *dcs; pfSphere bsphere;
} ModelData;
static ModelData *models; static int numModels; static pfHighlight *hl; static pfDCS* selectedDcs = NULL;
static pfHighlight** sharedHl = NULL;
static void Usage( char* prgName ) { pfNotify(PFNFY_FATAL, PFNFY_USAGE, "Usage: %s modelfile.ext \n", prgName); exit(-1); }
pfDCS* OLD_WhichModelHaveIPickedOn( pfNode* node ) { int i; while( node != NULL ) { /* go up to next DCS */ while( node!=NULL && !pfIsExactType( node, pfGetDCSClassType() ) ) node = (pfNode*)pfGetParent( node, 0 ); if( node == NULL ) return NULL; for( i=0; i<numModels; i++ ) if( models[i].dcs == (pfDCS*)node ) return (pfDCS*) node; node = (pfNode*)pfGetParent( node, 0 ); } return NULL; }
pfDCS* WhichModelHaveIPickedOn( pfPath* pickpath ) { int i, j, n; pfNode* node; if(pickpath==NULL) return NULL; if((n=pfGetNum(pickpath))<1) return NULL; for( i=0; i<n; i++ ) { node = pfGet(pickpath, i); if( (node!=NULL) && (pfIsExactType( node, pfGetDCSClassType())) ) { for( j=0; j<numModels; j++ ) { if( models[j].dcs == (pfDCS*)node ) return (pfDCS*) node; } } } return NULL; }
int SelectedPreDrawFunc(pfTraverser *trav, void *userData) { pfOverride(PFSTATE_ENHIGHLIGHTING, 0); pfEnable(PFEN_HIGHLIGHTING); pfOverride(PFSTATE_ENHIGHLIGHTING, 1); pfApplyHlight(*sharedHl); return PFTRAV_CONT; }
int SelectedPostDrawFunc(pfTraverser *trav, void *userData) { pfOverride(PFSTATE_ENHIGHLIGHTING, 0); pfDisable(PFEN_HIGHLIGHTING); return PFTRAV_CONT; }
int main (int argc, char *argv[]) { int i;
pfScene *scene; pfPipe *p; pfPipeWindow *pw; pfChannel *chan;
pfSphere bsphere; float t = 0.0f; float width = 0.0f; float offset;
if (argc != 2) Usage(argv[0]);
pfInit(); pfMultiprocess( PFMP_DEFAULT );
numModels = 6; pfdInitConverter(argv[1]);
sharedHl = (pfHighlight**)pfCalloc(1, sizeof(pfHighlight*), pfGetSharedArena());
pfConfig(); pfFilePath(".:/usr/share/Performer/data");
scene = pfNewScene();
if( (models=pfCalloc(numModels, sizeof(ModelData), pfGetSharedArena())) == NULL) { pfNotify( PFNFY_FATAL, PFNFY_PRINT, "%s: pfCalloc failed", argv[0] ); pfExit(); } for( i=0; i<numModels; i++ ) { if( i==0 ) { if((models[0].root = pfdLoadFile(argv[1])) == NULL) { pfNotify( PFNFY_FATAL, PFNFY_PRINT, "%s: Failed to load file %s ... aborting.", argv[0], argv[1] ); pfExit(); } } else { models[i].root = models[0].root; } pfGetNodeBSphere (models[i].root, &(models[i].bsphere)); width += (2.0f*models[i].bsphere.radius);
if((models[i].dcs = pfNewDCS()) == NULL) { pfNotify( PFNFY_FATAL, PFNFY_PRINT, "%s: pfNewDCS failed.", argv[0] ); pfExit(); } pfAddChild( models[i].dcs, models[i].root ); pfAddChild( scene, models[i].dcs );
}
width += ((float)(numModels-1)*GAPWIDTH);
offset = -width/2.0f; for( i=0; i<numModels; i++ ) { pfDCSTrans( models[i].dcs, offset+models[i].bsphere.radius, 0.0f, 0.0f ); offset += (2.0f*models[i].bsphere.radius); offset += GAPWIDTH; }
if( (hl = pfNewHlight( pfGetSharedArena())) == NULL ) { pfNotify( PFNFY_FATAL, PFNFY_PRINT, "%s: pfNewHlight failed", argv[0]); pfExit(); }
*sharedHl = hl;
pfHlightMode( hl, PFHL_LINES ); pfHlightColor( hl, PFHL_FGCOLOR, 1.0f, 1.0f, 0.0f );
/* Create a pfLightSource and attach it to scene. */ pfAddChild(scene, pfNewLSource()); /* Configure and open GL window */ p = pfGetPipe(0); pw = pfNewPWin(p); pfPWinType(pw, PFPWIN_TYPE_X); pfPWinName(pw, "OpenGL Performer"); pfPWinOriginSize(pw, 0, 0, 500, 500); /* Open and configure the GL window. */ pfOpenPWin(pw);
/* Create and configure a pfChannel. */ chan = pfNewChan(p); pfChanScene(chan, scene); pfChanFOV(chan, 45.0f, 0.0f);
pfuInitInput(pw, PFUINPUT_X); pfNodePickSetup( scene );
/* determine extent of scene's geometry */ pfGetNodeBSphere (scene, &bsphere); pfChanNearFar(chan, 1.0f, 10.0f * bsphere.radius);
/* Simulate for twenty seconds. */ while (t < 20.0f) { pfCoord view; float s, c;
/* Go to sleep until next frame time. */ pfSync();
/* Initiate cull/draw for this frame. */ pfFrame(); /* pick on a model to select it, pick in the background to deselect */ { pfHit **picklist[32]; pfuMouse mouse; float normX, normY; pfuGetMouse(&mouse); if( mouse.click & PFUDEV_MOUSE_LEFT_DOWN ) { pfuCalcNormalizedChanXY( &normX, &normY, chan, mouse.xpos, mouse.ypos ); if( pfChanPick( chan, (PFTRAV_IS_PRIM|PFPK_M_NEAREST|PFTRAV_IS_PATH), normX, normY, 0.0f, picklist) == 0 ) { if( selectedDcs ) { pfNodeTravFuncs( selectedDcs, PFTRAV_DRAW, NULL, NULL ); selectedDcs = NULL; } } else { pfGeode* geode; pfDCS* dcs; pfPath* pickpath = NULL;
pfQueryHit(picklist[0][0], PFQHIT_PATH, &pickpath); pfNotify( PFNFY_INFO, PFNFY_PRINT, "PickPath = %x (len=%d)", pickpath, pfGetNum(pickpath) ); if( pickpath ) { int i, n; pfNotify( PFNFY_INFO, PFNFY_PRINT, "Path:"); for( i=0, n=pfGetNum(pickpath); i<n; i++ ) { pfNotify( PFNFY_INFO, PFNFY_PRINT, "%d: %x", i, pfGet(pickpath, i)); } } pfQueryHit(picklist[0][0], PFQHIT_NODE, &geode); if( (dcs = WhichModelHaveIPickedOn(pickpath)) != NULL ) { if( selectedDcs!=dcs ) { if( selectedDcs!=NULL ) pfNodeTravFuncs( selectedDcs, PFTRAV_DRAW, NULL, NULL ); selectedDcs = dcs; pfNodeTravFuncs( selectedDcs, PFTRAV_DRAW, SelectedPreDrawFunc, SelectedPostDrawFunc ); } } else { pfNodeTravFuncs( selectedDcs, PFTRAV_DRAW, NULL, NULL ); selectedDcs = NULL; } } } }
/* Compute new view position. */ t = pfGetTime(); pfSinCos(45.0f*t, &s, &c); pfSetVec3(view.hpr, 45.0f*t, -10.0f, 0); pfSetVec3(view.xyz, 2.0f * bsphere.radius * s, -2.0f * bsphere.radius *c, 0.5f * bsphere.radius); pfChanView(chan, view.xyz, view.hpr); }
/* Terminate parallel processes and exit. */ pfExit(); return 0; }
This archive was generated by hypermail 2b29 : Wed Feb 27 2002 - 16:22:41 PST