pfTraverser(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
NAME
pfTraverser, pfCullResult, pfGetCullResult, pfGetParentCullResult - Set
and get traversal masks, callback functions and callback data, and get
pfTraverser attributes.
FUNCTION SPECIFICATION
#include <Performer/pf/pfTraverser.h>
pfChannel * pfTraverser::getChan(void);
void pfTraverser::getMat(pfMatrix &mat);
pfNode * pfTraverser::getNode(void);
int pfTraverser::getIndex(void);
const pfPath * pfTraverser::getPath(void);
void pfCullResult(int result);
int pfGetCullResult(void);
int pfGetParentCullResult(void);
typedef int (*pfNodeTravFuncType)(pfTraverser *trav, void *userData);
PARAMETERS
which identifies the traversal: PFTRAV_ISECT, PFTRAV_APP, PFTRAV_CULL or
PFTRAV_DRAW, denoting the intersection, application, cull or draw
traversals respectively.
DESCRIPTION
OpenGL Performer provides four major traversals: intersection,
application, cull, and draw that are often abbreviated as ISECT, APP,
CULL, and DRAW. A traversal is typically an in-order traversal of a
directed acyclic graph of pfNodes otherwise known as a subgraph. The
actual traversal method, traverser structure, and traversal initiation
used depends on the traversal type as well as the multiprocessing mode as
shown in the following table.
Page 1
pfTraverser(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
Traversal Traverser Traversee Trigger
________________________________________________________________________
PFTRAV_ISECT pfSegSet subgraph pfNode::isect(),
pfChanNodeIsectSegs
PFTRAV_APP pfTraverser pfScene pfApp()
CULL_DL_DRAW is set
PFTRAV_CULL pfChannel pfScene pfCull()
PFTRAV_DRAW pfChannel pfDispList pfDraw()
CULL_DL_DRAW is not set
PFTRAV_CULL pfChannel pfScene pfDraw()
PFTRAV_DRAW
|
|
|
Typical traversal callback usage:
ISECT
Collision detection, terrain following, line of sight
APP Application-specific behavior, motors
CULL Custom level-of-detail selection, culling
DRAW Custom rendering
When PFMPCULL_DL_DRAW is not set in the multiprocessing mode argument to
pfMultiprocess (and the cull and draw stages are in the same process),
then pfDraw simultaneously culls and draws the pfScene attached to the
pfChannel by pfChannel::setScene. Otherwise, pfCull culls and builds up
a pfDispList which is later rendered by pfDraw.
If the traversal CULL mask and node CULL mask AND to zero at a node, the
CULL traversal disables view culling and trivially accepts the node and
all its descendents. Note that unlike other traversals, a mask result of
0 does not prune the node.
If the traversal DRAW mask and node DRAW mask AND to zero at a node, the
CULL traversal prunes the node, so descendents are neither CULL-traversed
nor drawn.
If the traversal APP mask and the node APP mask AND to zero, the APP
traversal prunes the node and its descendents.
If the ISECT masks AND to zero, the ISECT traversal prunes the node. The
intersection mask is typically used to control traversals of different
types of objects, e.g. different bits may indicate ground, water,
foliage, and buildings, so they may be intersected selectively. See (-
pfNode::setTravMask).
In many respects a traversal appears to the user as an atomic action.
The user configures a traverser, triggers it with the appropriate routine
Page 2
pfTraverser(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
and awaits the results. Node callbacks are supported to provide user
extensibility and configuration into this scenario. They are user-
supplied routines that are invoked in the course of a traversal.
Callbacks return a value which can control traversal on a coarse-grained
basis. In addition, draw callbacks can render custom geometry and cull
callbacks can substitute custom culling for the default OpenGL Performer
culling.
The pre- or post-callbacks for the cull and intersection traversals may
return PFTRAV_CONT, PFTRAV_PRUNE, PFTRAV_TERM to indicate that traversal
should continue normally, skip this node or terminate the traversal,
respectively. PFTRAV_PRUNE is equivalent to PFTRAV_CONT for the post-
callback. Currently, the return value from the draw callbacks is ignored.
pfCullResult, pfGetCullResult, and pfGetParentCullResult can all be
called in the pre-cull callback and all but pfCullResult may be called in
the post-cull callback. pfGetCullResult returns the result of the cull
for the node that the cull callback is associated with.
pfGetParentCullResult returns the cull result for the parent of the node
that the cull callback is associated with. When called within the pre-
cull callback, pfCullResult specifies the result of cull for the node
that the pre-cull callback is associated with. This essentially replaces
default OpenGL Performer cull processing with user-defined culling.
result is a token which specifies the result of the cull test and should
be one of:
PFIS_FALSE
Node is entirely outside the viewing frustum and should be
pruned.
PFIS_MAYBE | PFIS_TRUE
Node is partially inside the viewing frustum and the children
of the node should be cull-tested.
PFIS_MAYBE | PFIS_TRUE | PFIS_ALL_IN
Node is totally inside the viewing frustum so all the children
of the node should be trivially accepted without further cull
testing.
If pfCullResult is not called within the pre-cull callback, OpenGL
Performer will use its default geometric culling mechanism that compares
node bounding volumes to the current culling frustum to determine if the
node may be within view.
In the post-cull callback pfGetCullResult will return the result of the
cull set by pfCullResult or the result of the default cull if
pfCullResult was not called.
The evaluation order of the cull and draw traversal masks and callbacks
is illustrated in the following pseudo-code:
Example 1: Cull and draw traversal mask and callback evaluation order.
Page 3
pfTraverser(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
/* Return if draw mask test fails */
if ((drawMask & nodeDrawMask) == 0)
return PFTRAV_CONT;
/* Call pre-cull callback */
if (preCull)
{
rtn = (*preCull)(traverser, cullData);
if (rtn == PFTRAV_PRUNE)
return PFTRAV_CONT;
else if (rtn == PFTRAV_TERM)
return PFTRAV_TERM;
}
/* Disable view culling if cull mask test fails */
if ((cullMask & nodeCullMask) == 0)
disableViewCulling();
/* Perform default culling if pfCullResult was not called */
if (!userCalledpfCullResultInThePreCullCallback)
cullResult = cullTest(node);
if (cullResult == PFIS_FALSE)
{
/* Call post-cull callback */
if (postCull)
{
rtn = (*postCull)(traverser, cullData);
if (rtn == PFTRAV_PRUNE)
return PFTRAV_CONT;
else if (rtn == PFTRAV_TERM)
return PFTRAV_TERM;
}
return PFTRAV_CONT;
}
else
/* Trivially accept node and all its children */
if (cullResult == PFIS_ALL_IN)
disableViewCulling();
/* Call pre-draw callback */
if (preDraw)
(*preDraw)(traverser, drawData);
evaluateNodeAndItsChildren();
/* Call post-draw callback */
if (postDraw)
(*postDraw)(traverser, drawData);
Page 4
pfTraverser(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
/* Call post-cull callback */
if (postCull)
{
rtn = (*postCull)(traverser, cullData);
if (rtn == PFTRAV_PRUNE)
return PFTRAV_CONT;
else
if (rtn == PFTRAV_TERM)
return PFTRAV_TERM;
}
return PFTRAV_CONT;
Example 2: Use of DRAW callbacks to save and restore state.
extern int
preDraw(pfTraverser *trav, void *data)
{
pfPushState();
pfEnable(PFEN_TEXGEN);
((pfTexGen*)data)->apply;
return PFTRAV_CONT;
}
extern int
postDraw(pfTraverser *trav, void *data)
{
pfPopState();
return PFTRAV_CONT;
}
/*
* Set up draw callbacks and user data to draw 'geode' in
* EYE_LINEAR texgen mode.
*/
pfTexGen *tgen;
tgen = new pfTexGen(pfGetSharedArena());
tgen->setMode(PF_S, PFTG_EYE_LINEAR);
tgen->setMode(PF_T, PFTG_EYE_LINEAR);
geode->setTravFuncs(PFTRAV_DRAW, preDraw, postDraw);
geode->setTravData(PFTRAV_DRAW, tgen);
Page 5
pfTraverser(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
libpr graphics calls like pfTexGen::apply should be made in a DRAW
callback only. Specifically, libpr graphics calls made in a CULL callback
are not legal and have undefined behavior.
The intersection, application, cull and draw callbacks are passed a
pfTraverser which can be used to query the channel, current
transformation matrix and current node. pfTraverser::getChan returns the
current channel for the cull, and draw traversal. It returns the current
channel for intersection traversals initiated with pfChanNodeIsectSegs
and NULL for intersection traversals initiated with pfNode::isect.
pfTraverser::getMat sets mat to the current transformation matrix, which
is the concatenation of the matrices from the root of the scene down to
and including the current node. Since no transformation hierarchy is
retained in the draw process, in a draw callback, the current matrix
should be queried using the getmatrix or pfGetModelMat/pfGetViewMat
routines.
pfTraverser::getNode returns the current node being traversed and
pfTraverser::getIndex returns the child index of the current node, i.e.-
the index of the current node in its parent's list of children.
pfTraverser::getPath returns a pointer to the list of nodes which defines
the path from the scene graph root to the current node.
NOTES
The post-cull callback is a good place to implement custom level-of-
detail mechanisms.
BUGS
The path returned by pfGetTravPath is valid only when invoked from a cull
callback.
SEE ALSO
pfGroup, pfClone, pfFrame, pfNode
Page 6