class ssgBase
- The Universal Abstract Base Class.class ssgBase { void ref () ; void deRef () ; int getRef () ; int isA ( int ty ) ; int isAKindOf ( int ty ) ; int getType (void) ; virtual char *getTypeName(void) ; ssgBase *getUserData () ; void setUserData ( ssgBase *user_data ) ; void setName ( char *nm ) ; char *getName () ; const char *getPrintableName () ; virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) ; virtual int load ( FILE *fd ) ; virtual int save ( FILE *fd = stderr ) ; ssgBase *clone ( int clone_flags ) ; } ;
ssgBranch::addKid()
, we
increment its reference count and each time we remove a node from
the graph with ssgBranch::removeKid()
, we decrement the count -
and if it's zero, we'll delete the node to recover memory.
Sometimes, you need a node to stay in memory even though it may be
be disconnected from the scene graph. You can achieve that by
calling ssgBase::ref()
to increment the reference count.
If you later find you don't need that node anymore then you may
ssgBase::deRef()
it. If you ssgBase::deRef()
a node to zero, SSG won't automatically delete it - you still need to use
delete
to do that. Since such deletions are recursive,
you may delete an entire sub-branch with a single call.
Instead of using ssgBase::deRef()
directly, you should use
ssgDeRefDelete()
which automatically deletes the node if
the reference count drops to zero.
You can read the current ref count for a node
using ssgBase::getRef()
.
ssgBase::setName(s)
sets the name,
ssgBase::getName()
returns it.
ssgBase::getUserData()
and ssgBase::setUserData(data)
.
Notice that user data is of class ssgBase - which means that user data can be named, ref-counted - and can in turn have user data of it's own. This allows user data to be formed into linked lists when multiple user data items need to be attached to a single node.
int ssgTypeBase () ; int ssgTypeEntity () ; int ssgTypeLeaf () ; int ssgTypeVTable () ; int ssgTypeVtxTable () ; int ssgTypeDisplayList() ; int ssgTypeBranch () ; int ssgTypeBaseTransform (); int ssgTypeTransform () ; int ssgTypeTexTrans () ; int ssgTypeSelector () ; int ssgTypeTimedSelector () ; int ssgTypeRangeSelector () ; int ssgTypeRoot () ; int ssgTypeCutout () ;Now, you can use the
ssgBase::isA(type)
or ssgBase::isAKindOf
to test the type of the node. For example, if you want to test
whether a node is a Leaf node or a Branch node, you can do this:
if ( mynode -> isAKindOf ( ssgTypeLeaf() ) ) printf ( "Leaf node\n" ) ; else if ( mynode -> isAKindOf ( ssgTypeBranch() ) ) printf ( "Branch node\n" ) ; else printf ( "Something else\n" ) ;Notice that if you ran that code on (say) an ssgSelector, then it'll print "Branch node" since the Selector class is derived from the Branch class. If you wanted to tell if a node was *exactly* a Branch node - and not from a derived class, then you could use:
if ( mynode -> isA ( ssgTypeBranch() ) ) printf ( "Branch node\n" ) ;Finally, you can actually read the type of a node - either as a token (using
ssgBase::getType()
) or as an ASCII string
(using ssgBase::getTypeName()
). The latter is very useful
for debug routines:
printf ( "ERROR - something wrong with my '%s' node.\n", mynode -> getTypeName () ) ;
ssgBase::print(fd, indent, how_much)
does that for you - it prints out the node itself - and anything
connected beneath it in the scene graph. fd
is the
file descriptor to print to (defaults to stderr) and
indent
is a string that will prefix all output lines
- and is used internally within SSG to make printout of tree
structures more legible by indenting them.
The values for the parameter how_much
may be 0,1,2,3 or 4
and determine how much is printed, with 0 meaning little
and 4 meaning much.
For how_much = 0, basic information of the branches is printed
For 1, additionally there is: basic leaf info, state pointers
For 2, additionally there is: states, user data, number of parents,
bSphere
For 3, additionally there is: Reference count
For 4, additionally there is: contents of vertex-, normal-, colour-,
texCoord- and index-arrays
Experience tells that for how_much = 0
you get very little
out put, with 1, 2 and 3 a manageable amount and with 4 a huge amount,
up to 100 MB for a medium sized model.
It would be unwise
to attempt to parse the output of ssgBase::print
into another
program since it is only intended for human consumption and the
format may change dramatically between revisions of SSG.
ssgBase *clone(int clone_flags)
which new's a
new object of that class as a copy of the calling object.
The 'clone_flags' is a set of tokens that you 'OR' together to specify how 'deep' you want the cloning to go. By default (with clone_flags==0), only the object itself is cloned and the clone will simply point to the same child structures as the original object. However, if you OR in 'SSG_CLONE_RECURSIVE', then all ssgEntities beneath this one will also be cloned. ORing in SSG_CLONE_GEOMETRY will cause all the per-vertex data at the leaf nodes to also be cloned. SSG_CLONE_STATE causes ssgState objects to be cloned also, SSG_CLONE_STATE_RECURSIVE also causes states pointed to by other states to be copied, SSG_CLONE_USERDATA causes user data attached to the original node to be referenced (NOT copied) by the clone - otherwise, user data for the clone is set to NULL. Finally, SSG_CLONE_TEXTURE causes texture maps to be replicated also.
Most copy operations will typically use either zero, SSG_CLONE_RECURSIVE or (SSG_CLONE_RECURSIVE | SSG_CLONE_GEOMETRY)
<= previous = | Return to SSG Index | = next => |
Steve J. Baker. <sjbaker1@airmail.net> |