pfNode(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages pfNode(3pf)NAMEpfNode - Set and get pfNode parents and bounding spheres.
FUNCTION SPECIFICATION
#include <Performer/pf/pfNode.h>
static pfType * pfNode::getClassType(void);
pfGroup * pfNode::getParent(int i);
int pfNode::getNumParents(void);
void pfNode::setBound(pfSphere *bsph, int mode);
int pfNode::getBound(pfSphere *bsph);
pfNode* pfNode::clone(int mode);
pfNode* pfNode::bufferClone(int mode, pfBuffer *buf);
int pfNode::flatten(int mode);
int pfNode::setName(const char *name);
const char * pfNode::getName(void);
pfNode* pfNode::find(const char *pathName, pfType *type);
pfNode* pfNode::lookup(const char *name, pfType* type);
int pfNode::isect(pfSegSet *segSet, pfHit **hits[]);
void pfNode::setTravMask(int which, uint mask, int setMode,
int bitOp);
uint pfNode::getTravMask(int which);
void pfNode::setTravFuncs(int which, pfNodeTravFuncType pre,
pfNodeTravFuncType post);
void pfNode::getTravFuncs(int which,
pfNodeTravFuncType *pre, pfNodeTravFuncType *post);
void pfNode::setTravData(int which, void *data);
void * pfNode::getTravData(int which);
void pfNode::setTravMode(int which, int mode, int val);
int pfNode::getTravMode(int which, int mode) const;
Page 1
pfNode(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages pfNode(3pf)
which identifies the traversal: PFTRAV_ISECT, PFTRAV_APP, PFTRAV_CULL or
PFTRAV_DRAW, denoting the intersection, application, cull, and
draw processing stages respectively.
DESCRIPTION
A pfNode is an abstract type. OpenGL Performer does not provide any
means to explicitly create a pfNode. Rather, the pfNode routines operate
on the common aspects of other OpenGL Performer node types.
The complete list of OpenGL Performer nodes (all derived from pfNode) is:
pfBillboard
pfDCS
pfGeode
pfGroup
pfLayer
pfLightPoint
pfLightSource
pfLOD
pfMorph
pfPartition
pfScene
pfSCS
pfSequence
pfSwitch
pfText
Any OpenGL Performer node is implicitly a pfNode, and a pointer to any of
the above nodes may be used wherever a pfNode* is required as an
argument.
The various pfNode types have certain common properties such as a set of
parents, a name, an intersection mask, bounding geometry, callback
functions and callback data.
pfNode::getClassType returns the pfType* for the class pfNode. The
pfType* returned by pfNode::getClassType is the same as the pfType*
returned by invoking the virtual function getType on any instance of
Page 2
pfNode(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages pfNode(3pf)
class pfNode. Because OpenGL Performer allows subclassing of built-in
types, when decisions are made based on the type of an object, it is
usually better to use the member function isOfType to test if an object
is of a type derived from a Performer type rather than to test for strict
equality of the pfType*'s.
pfNode::getNumParents returns the number of parents the pfNode has in the
scene graph. A node may have multiple parents because it was explicitly
added to multiple parents with pfGroup::addChild. In such cases it said
to be 'instanced'. Also, leaf geometry nodes such as pfGeodes,
pfLightPoints, and pfBillboards, may have multiple parents as a result of
a pfNode::clone. pfNode::getParent returns the ith parent of the pfNode
or NULL if i is out of the range 0 to pfNode::getNumParents - 1.
pfNode::setBound sets the bounding volume of the pfNode. Each pfNode has
an associated bounding volume used for culling and intersection testing
and a bounding mode, either static or dynamic. By definition, the
bounding volume of a node encloses all the geometry parented by node,
which means that the node and all its children fit within the node's
bounding volume.
Only a subset of the pfNode types actually contain geometry. These are
known as "leaf nodes" in OpenGL Performer. They are:
pfBillboard
pfGeode
pfLightPoint
These and other nodes may indirectly contain geometry through user-
supplied function callbacks set by pfNode::setTravFuncs.
Normally OpenGL Performer automatically computes bounding volumes but
provides routines to explicitly set bounding volumes. This is useful for
pfNodes which draw custom geometry through node callbacks (-
pfNode::setTravFuncs).
The bsph argument to pfNode::setBound is the bounding sphere of the
pfNode. If the bsph is NULL, OpenGL Performer will compute the bounding
sphere of the pfNode.
The mode argument to pfNode::setBound specifies whether or not the
bounding volume for the pfNode should be recomputed when an attribute of
the pfNode changes or something in the scene graph below the pfNode
changes (if the pfNode is a pfGroup). If the mode is PFBOUND_STATIC,
OpenGL Performer will not modify the bound once it is set or computed.
If the mode is PFBOUND_DYNAMIC, OpenGL Performer will recompute the bound
after children are added or deleted or after the matrix in a pfDCS
changes. Changes in pfSwitches, pfLODs and pfSequences do not affect
bounds above them in the scene graph.
pfNode::getBound returns the current bounding mode and copies into bsph a
pfSphere which encloses the pfNode and its children The return value is
the bounding mode which is either PFBOUND_DYNAMIC or PFBOUND_STATIC
Page 3
pfNode(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages pfNode(3pf)
indicating whether or not the bounding volume is updated automatically
when its children change.
OpenGL Performer supports two methods of node instancing. The first
method is to simply add a node to more than one parent using
pfGroup::addChild or pfGroup::replaceChild (see pfGroup). In this case
the graph rooted by the instanced node is shared by all its parents.
This type of instancing is called shared instancing.
pfNode::clone provides instancing which shares geometry but not variable
state like transformations (pfDCS) and switches (pfSwitch).
pfNode::clone copies the entire scene graph from the pfNode down to, but
not including, leaf geometry nodes such as pfGeodes, pfBillboards and
pfLightPoints. These leaf nodes are instanced by reference in the cloned
scene graph. pfNode::clone returns the root pfNode of the cloned graph
or NULL to indicate error. This type of instancing is called common
geometry instancing. An attempt to clone a leaf geometry node simply
returns the handle to that node.
Cloning is recommended for instances of dynamic and articulated models.
For example: Shared instances of a model with pfDCSes in its hierarchy
will share the pfDCSes as well as the geometry. This means that all
instances will have the exact same articulation. However, a common
geometry instance will share only geometry and as a result of the cloning
process will have its own pfDCSes allowing manipulation independently of
any other instances. This example creates a cloned instance:
if ((clone = carModel->clone(0)) != NULL)
carDCS_3->addChild(clone);
The mode argument to pfNode::clone is reserved for future extensions and
must be 0 in this release of OpenGL Performer.
When cloning, if the global copy function (pfObject::setCopyFunc) is
NULL, user data pointers (pfObject::setUserData) are copied to each new
node and the reference counts of pfMemory-derived user data are
incremented. If pfObject::setCopyFunc is not NULL, it will be invoked
with the destination and source nodes as arguments. It is then the
responsibility of the copy function to handle the copy of user data.
pfNode::bufferClone is identical to pfNode::clone but allows cloning
across pfBuffers. buf identifies the pfBuffer which containsthe pfNode
and its subtree. The clone of the pfNode and its subtree is placed in the
current buffer set by pfBuffer::select. See the pfBuffer man page for
more details.
pfNode::flatten is a database pre-processing step which 'flattens' the
transformation hierarchy of the scene graph rooted by the pfNode.
Coordinates and normals contained in leaf geometry nodes such as
pfGeodes, pfBillboards and pfLightPoints are transformed by any inherited
Page 4
pfNode(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages pfNode(3pf)
static transformations (pfSCS). pfNode::flatten automatically clones any
pfNode or pfGeoSet that is multiply referenced. Specifically, if the
pfNode has multiple parents, node and its entire subtree will be cloned.
If a pfDCS is encountered, pfNode::flatten inserts a pfSCS in between the
pfDCS and its parent.
Flattening can substantially improve performance, especially when pfSCSes
are being used to instance a relatively small amount of geometry since
the cost of the transformation approaches the cost of drawing the
geometry. However, it can also increase the size of the database since
it copies instanced nodes and geometry. Flattening is highly recommended
for pfBillboards. Flattening also increases the ability of OpenGL
Performer to sort the database by mode (see pfChannel::setBinSort), often
a major performance enhancement, since sorting does not cross
transformation boundaries.
pfNode::flatten does not remove pfSCSes from the hierarchy; instead it
sets their transformations to the identity matrix. For improved
traversal performance, these flattened pfSCS nodes should be removed from
the hierarchy.
The mode argument to pfFlatten is currently ignored and should be 0.
All OpenGL Performer database nodes may be assigned a character string
name. Individual node names need not be unique but to access a node with
a non-unique name, an unambiguous pathname to the node must be given.
The pathname doesn't need to be a full path. All that's required is
enough to distinguish the node from others with the same name.
pfNode::setName sets the name of the pfNode to the string name. If the
name is unique a 1 will be returned and if the name is not unique, a 0
will be returned. Node names are kept in a global table which is used for
resolving the first path component of a path name by pfNode::lookup. In
this case, unambiguous resolution is only possible if the first path
component is unique. pfNode::getName returns the name of the node or NULL
if the name has not been set.
pfNode::find is a general search routine for finding named pfNodes.
pfNode::find begins searching for the node of type type and identified by
a '/'-separated path name pathName. The search begins at the pfNode and
uses a depth-first traversal. pfNode::find returns NULL if it cannot
find the node. Note that the type checking performed by pfNode::find is
equivalent to pfMemory::isOfType, not pfMemory::isExactType, e.g.
searching for a pfGroup includes derived classes such as pfSwitch.
The string pathName can be either a name or a '/'-separated pathname. If
the name contains no '/' characters, it is assumed to be unique and the
global name table is searched. If pathName contains '/' characters, it
is assumed to be a path. Paths are searched by first finding the node
corresponding to the first component of the path in a global name table.
The find routine then traverses the subtree rooted at that node,
searching for the rest of the path. The first node encountered during the
Page 5
pfNode(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages pfNode(3pf)
search traversal which matches pathName is returned.
Example 1:
pfNode *newhouse, *newdoor;
pfDCS *door;
/* Create "house" model with named subparts including "door" */
/* Create a new instance of "house" */
newhouse = house->clone(0);
/* Give cloned house a new name */
newhouse->setName("newhouse");
/* Find the door part of the new house */
door = (pfDCS*) newhouse->find("door", pfDCS::getClassType());
pfNode::isect intersects a group of line segments with a scene or portion
thereof. The intersection operation traverses the scene graph, testing a
group of segments against bounding geometry and eventually model geometry
within pfGeoSets.
pfNode::isect returns the number of segments which intersected something.
hits is an empty array supplied by the user through which results are
returned. The array must have an entry for each segment in segSet. Upon
return, hits[i][0] is a pfHit* which gives the intersection result for
the ith segment in segSet. The pfHit objects come from an internally
maintained pool and are reused on subsequent requests. Hence, the
contents are only valid until the next invocation of pfGSetIsectSegs in
the current process. They should not be freed by the application.
segSet is a pfSegSet structure specifying the intersection request. In
the structure, segs is an array of line segments to be intersected
against the pfGeoSet. activeMask is a bit vector specifying which
segments in the pfSegSet are to be active for the current request. If
bit[i] of the activeMask is set to 1, it indicates the corresponding
segment in the segs array is active.
The bit vector mode specifies the behavior of the intersection operation
and is a bitwise OR of the following:
PFTRAV_IS_PRIM
Intersect with quads or triangle geometry.
PFTRAV_IS_GSET
Intersect with pfGeoSet bounding boxes.
Page 6
pfNode(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages pfNode(3pf)
PFTRAV_IS_GEODE
Intersect with pfGeode bounding sphere.
PFTRAV_IS_NORM
Return normals in the pfHit structure.
PFTRAV_IS_CULL_BACK
Ignore back-facing polygons.
PFTRAV_IS_CULL_FRONT
Ignore front-facing polygons.
PFTRAV_IS_PATH
Retain traversal path information.
PFTRAV_IS_NO_PART
Do not use partitions for intersections.
For several types of pfGroups, the traversal of children can be
controlled for the traversal.
For pfSwitches, the default is to traverse only the child or children
specified by the current switch value. This can be changed OR-ing one of
the following into the mode argument.
PFTRAV_SW_ALL
Traverse all children of pfSwitches.
PFTRAV_SW_NONE
Don't traverse any children of pfSwitches.
For pfSequences, the default is to traverse only the current child in the
sequence. This can be changed OR-ing one of the following into the mode
argument.
PFTRAV_SEQ_ALL
Intersect with all children of pfSequences.
PFTRAV_SEQ_NONE
Intersect with no children of pfSequences.
For pfLODs, the default is to traverse only the child that would be
active at range 0. This can be changed OR-ing one of the following into
the mode argument. Also, see pfChannel::isect for child selection based
on range.
PFTRAV_LOD_ALL
Intersect with all children of pfLODs (default is range 0).
PFTRAV_LOD_NONE
Intersect with no children of pfLODs (default is range 0).
Page 7
pfNode(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages pfNode(3pf)
For pfLayers, the default is to traverse all children. This can be
changed OR-ing one of the following into the mode argument.
PFTRAV_LAYER_NONE
Intersect with no children of pfLayers (default is all).
PFTRAV_LAYER_BASE
Intersect with no children of pfLayers (default is all).
PFTRAV_LAYER_DECAL
Intersect with no children of pfLayers (default is all).
The bit fields PFTRAV_IS_PRIM, PFTRAV_IS_GSET, and PFTRAV_IS_GEODE
indicate the level at which intersections should be evaluated and
discriminator callbacks, if any, invoked. If none of these three fields
are specified, no intersection testing is done.
In the pfSegSet, isectMask is another bit vector which directs the
intersection traversal. At each stage of the intersection operation, the
mask is bit-wise AND-ed with the mask of the pfNode or pfGeoSet. If the
mask is non-zero the intersection continues with the next object, either
a pfNode within a pfGroup or a primitive within a pfGeoSet. The mask of
a pfNode is set using pfNode::setTravMask and that of a pfGeoSet by
pfGeoSet::setIsectMask. The mask can be used to distinguish parts of the
scene graph which might respond differently to vision or collision. For
example, as a wall would stop a truck but shrubbery would not.
The bound field in a pfSegSet is an optional user-provided bounding
volume around the set of segments. Currently, the only supported volume
is a cylinder. To use a bounding cylinder, perform a bitwise OR of
PFTRAV_IS_BCYL into the mode field of the pfSegSet and assign the pointer
to the bounding volume to the bound field.
pfCylinder::around will construct a cylinder around the segments. When a
bounding volume is supplied, the intersection traversal may use the
cylinder to improve performance. The largest improvement is for groups
of at least several segments which are closely grouped segments. Placing
a bounding cylinder around small groups or widely dispersed segments can
decrease performance.
The userData pointer allows an application to associate other data with
the pfSegSet. Upon return and in discriminator callbacks, the pfSegSet's
userData pointer can be obtained from the returned pfHit with
pfObject::getUserData.
discFunc is a user supplied callback function which provides a more
powerful means for controlling intersections than the simple mask test.
If discFunc is NULL, the default behavior clips the end of the segment
after each successful intersection at the finest resolution (pfGeode
bounding volume , pfGeoSet bounding box, pfGeoSet geometry) specified in
mode. Thus, the segment is clipped by each successful intersection so
Page 8
pfNode(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages pfNode(3pf)
that the intersection point nearest the starting point of the segment is
returned upon completion.
If a discriminator callback is specified, whenever an intersection
occurs, the discFunc callback is invoked with a pfHit structure
containing information about the intersection. The discriminator may
then return a value which indicates whether and how the intersection
should continue. The continuation selectors are PFTRAV_CONT,
PFTRAV_PRUNE, and PFTRAV_TERM.
PFTRAV_CONT
Indicates that the traversal should continue traversing the
pfGeoSets beneath a pfGeode. The discriminator function can
examine information about candidate intersections and judge
their validity and control the continuation of the traversal
with its return value.
PFTRAV_PRUNE
Indicates the traversal should return from the current level of
the search and continue. If returned on a pfGeoSet primitive
or bounding box test, PFTRAV_PRUNE stops further testing of the
line segment against that pfGeoSet. If returned on the test
against a pfGeode bounding volume, the pfGeode is not traversed
for that line segment.
PFTRAV_TERM
Indicates that the search should terminate for this segment of
the pfSegSet. To have PFTRAV_TERM or PFTRAV_PRUNE apply to all
segments, PFTRAV_IS_ALL_SEGS can be OR-ed into the
discriminator return value. This causes the entire traversal
to be terminated or pruned.
The callback may OR other bitfields into the status return value:
PFTRAV_IS_IGNORE
Indicates that the current intersection should be ignored,
otherwise the intersection is taken as valid.
PFTRAV_IS_CLIP_START
Indicates for pruned and continued traversals that before
proceeding the segment should be clipped to start at the
current intersection point.
PFTRAV_IS_CLIP_END
Indicates for pruned and continued traversals that before
proceeding the segment should be clipped to end at the current
intersection point.
If discFunc is NULL, the behavior is the same as if the discriminator
returned PFTRAV_CONT | PFTRAV_IS_CLIP_END, so that the intersection
nearest the start of the segment will be returned.
Page 9
pfNode(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages pfNode(3pf)
In addition to the discriminator callback, pre- and post- intersection
callbacks are available for each node. These behave identically to the
pre- and post-callbacks for the cull traversal and can be used to prune,
continue or terminate the traversal at any node.
Both pfNode::isect and the discriminator callback return information
about an intersection in a pfHit object which can be examined using the
pfHit::query and pfHit::mQuery calls. The information includes the
intersection point, current matrix transformation, scene graph, and path.
See the man page for pfHit for further details.
In multiprocess applications, pfNode::isect should be called from the APP
process or from the ISECT process (in the callback specified by
pfIsectFunc). When called in the APP process, pfNode::isect should be
called after pfFrame and before pfSync for best system throughput.
pfNode::setTravMask sets the traversal masks of node which are used to
control traversal during the intersection, cull, and draw traversals. If
the bitwise AND of the node's mask for that traversal type and the mask
for the current traversal is zero, the traversal is disabled at that
node. By default, the node masks are all 1's. Traverser masks are set
by pfNode::isect/pfChanNodeIsectSegs for the intersection traversal and
pfChannel::setTravMask for the CULL and DRAW traversals.
pfNode::getTravMask returns the specified traversal mask for the node.
Bits in the setMode argument indicate whether the set operation should be
carried out for just the specified pfNode (PFTRAV_SELF), just its
descendents (PFTRAV_DESCEND) or both itself and descendents. The
descendent traversal goes down into pfGeoSets.
The bitOp argument is one of PF_AND, PF_OR, or PF_SET and indicates
whether the new mask should be AND-ed with the old mask, OR-ed with the
old mask or set outright, respectively.
Efficient intersections require that information be cached for each
pfGeoSet to be intersected with. To create this cache, PFTRAV_IS_CACHE
should be OR-ed into the setMode when first setting the intersection
mask. Because of the computation involved, the cache is best created at
setup time. Subsequent changes to the masks themselves do not require
PFTRAV_IS_CACHE to be specified. However, for dynamic objects whose
geometry changes (e.g. pfGeoSets whose vertex arrays are being changed),
additional calls with the PFTRAV_IS_CACHE in setMode should be used to
recompute the cached information. PFTRAV_IS_UNCACHE can be OR-ed into
the setMode to disable caching. PFTRAV_IS_CACHE and PFTRAV_IS_UNCACHE
can only be specified when which is PFTRAV_ISECT.
pfNode::setTravFuncs specify the user supplied functions which are to be
invoked during the traversal indicated by which. For each traversal,
there is a pre and post traversal callback. pre is invoked before node
and its children are processed while post is invoked after. The pre- and
post- methodology supports save and restore or push and pop programming
constructs. Node callbacks are passed pointers to the user supplied
Page 10
pfNode(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages pfNode(3pf)
traversal data pointer for that node and a pfTraverser which defines the
current traversal state. pfNode::getTravFuncs copies the pfNode's pre
and post callbacks of traversal type which into pre and post
respectively.
The data argument to pfNode::setTravData is the pointer which is passed
to the traversal callbacks indicated by which. Both pre- and post-
callbacks will be passed data in addition to a pfTraverser*. When
multiprocessing, data should point to memory in a shared arena.
pfNode::getTravData returns the current data pointer for the specified
traversal.
setTravMode is used to set additional mode information to control
traversals. Currently the which argument must be PFTRAV_CONT and the
mode argument must be PFN_CULL_SORT; the possible choices for the value
argument are:
PFN_CULL_SORT_UNCONTAINED
This is the default value. It means that pre- and post-CULL
traversal funcs on a node do not prevent the contents of the
node from being interleaved with the contents of other nodes
during CULL sorting. This means that (surprise!) the contents
of the node are not necessarily bracketed by the graphics calls
made in the pre- and post-CULL node trav funcs. This behavior
is for the benefit of CULL funcs whose purpose is to return a
cull result but that don't make any graphics calls. (Note that
in contrast, 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.)
PFN_CULL_SORT_CONTAINED
This is the opposite of PFN_CULL_SORT_UNCONTAINED; setting this
value guarantees the following:
1. Display list items produced by the pre-node CULL func will
get placed in the display list before the contents of the node
(including its children and DRAW funcs)
2. Display list items produced by the post-node CULL func will
get placed in the display list after the contents of the node
(including its children and DRAW funcs)
3. No part of the scene graph other than this node (including
its children and DRAW funcs) will be placed in the display list
between the items produced by the pre-node CULL func and the
items produced by the post-node CULL func.
PFN_CULL_SORT_CONTAINED is typically used in applications such
as virtual clip texturing in which the pre-cull function calls
display-listable functions (such as
pfClipTexture::applyVirtualParams) which are intended to affect
the contents of the node and its children, and no other part of
the scene graph. Turning off CULL sorting altogether using
pfChannel::setTravMode is another way to accomplish this
effect, but that is usually overkill and can result in greatly
Page 11
pfNode(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages pfNode(3pf)
decreased performance, as can setting DRAW trav funcs on the
node to accomplish the PFN_CULL_SORT_CONTAINED effect.
getTravMode returns the current value of the given mode for the given
traversal type which.
NOTES
When instanced geometry is flattened, the copy created by pfNode::flatten
shares pfGeoSet attribute arrays with the original when possible. This
means that the newly flattened pfGeoSet may share some arrays (e.g. color
array), but not other arrays (e.g. the vertex array) with the original.
The post-cull callback is a good place to implement custom level-of-
detail mechanisms.
Currently, nodes use spheres as the default bounding volume. This may
change in a future release. libpfutil contains sample code for computing
the bounding box for a subgraph of the scene.
It's an interesting fact that although a node's bounding volume
completely contains the geometry of the nodes that it parents, it may
well not completely contain the bounding volumes of those same nodes. Do
you understand when this situation would occur?
Finding a node by name can be expensive, particularly for path based
searches. These functions are primarily intended to get handles to nodes
which are loaded from disk and should be used sparingly at simulation
time.
In OpenGL Performer releases since 2.0, pfNode::lookup replaces a number
of functions from Performer 1.2, e.g. pfLookupBboard. See the scripts in
/usr/share/Performer/src/tools for help in porting code.
BUGS
If the graph under a node cloned by pfNode::clone contains an object
instanced within the graph, (i.e. a node having two or more parents
within the graph), the new graph will contain multiple copies of the
instanced node rather than duplicating the connectivity of the original
graph.
pfNode::flatten transforms the vertex arrays of non-instanced geometry in
place. If a pfGeoSet belongs to multiple pfGeodes or a vertex array is
shared between pfGeoSets the array is still flattened in place.
It is not possible to get multiple intersection results per segment
without a discriminator callback.
Bounding cylinders do not work when non-orthonormal transformations are
present in the pfDCS and pfSCS nodes of a scene graph.
The path returned by pfGetTravPath is valid only when invoked from a cull
Page 12
pfNode(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages pfNode(3pf)
callback.
SEE ALSO
pfCylinder, pfGroup, pfHit, pfNode, pfBuffer, pfObject, pfChannel,
pfGeoSet, pfBillboard, pfDCS, pfFrame, pfGeode, pfIsectFunc,
pfLightPoint, pfScene, pfSCS, pfSeg, pfGSetIsectSegs, pfSync, pfTraverser
Page 13