320 lines
13 KiB
HTML
320 lines
13 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
|
<HTML>
|
|
<HEAD>
|
|
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
|
<TITLE>A Simple Scene Graph API for OpenGL.</TITLE>
|
|
</HEAD>
|
|
<BODY text="#B5A642" link="#8FFF8F" vlink="#18A515" alink="#20336B"
|
|
bgcolor="#005000" background="../marble.png">
|
|
|
|
<H2><code>class ssgBranch</code> - A basic branch node.</H2>
|
|
The basic ssgBranch node simply handles a node in the tree,
|
|
with zero or more child nodes which can be any kind of ssgEntity
|
|
except ssgRoot.
|
|
<p>
|
|
There are a rich set of functions for adding, deleting and
|
|
replacing child nodes:
|
|
<pre>
|
|
|
|
class ssgBranch : public ssgEntity
|
|
{
|
|
int getNumKids (void) ;
|
|
ssgEntity *getKid ( int n ) ;
|
|
ssgEntity *getNextKid (void) ;
|
|
int searchForKid ( ssgEntity *entity ) ;
|
|
void addKid ( ssgEntity *entity ) ;
|
|
void removeKid ( int n ) ;
|
|
void removeKid ( ssgEntity *entity ) ;
|
|
void removeAllKids (void) ;
|
|
void replaceKid ( ssgEntity *old_entity, ssgEntity *new_entity ) ;
|
|
} ;
|
|
|
|
</pre>
|
|
Most of these are pretty self-explanatory.
|
|
<code>ssgBranch::getNumKids()</code> returns the number of child nodes
|
|
beneath this branch.
|
|
<code>ssgBranch::getKid(n)</code> returns the address of the n'th child ssgEntity.
|
|
<code>ssgBranch::getNextKid()</code> returns the address of the child entity following
|
|
the last one returned by getKid or getNextKid - returning NULL when all child nodes
|
|
have been exhausted.
|
|
<code>ssgBranch::searchForKid(entity)</code> searches for the specified entity
|
|
in the list of child nodes and returns it's index (ie the inverse of getKid).
|
|
<code>ssgBranch::addKid(entity)</code> adds the specified entity to the list of
|
|
child nodes - the new node is added at the end of the list and will therefore
|
|
have the highest numbered index.
|
|
<code>ssgBranch::removeKid(n)</code> removes the n'th child node and renumbers
|
|
any higher numbered children so there are never any gaps in the number range.
|
|
<code>ssgBranch::removeKid(entity)</code> same as removeKid(searchForKid(entity)).
|
|
<code>ssgBranch::removeAllKids()</code> remove ALL child entities.
|
|
<code>ssgBranch::replaceKid(old, new)</code> replaces <code>old</code> with <code>new</code>.
|
|
If the entity removed by any of these commands has a ref count of
|
|
zero, it will be deleted.
|
|
|
|
<H2><code>class ssgInvisible</code> - Invisible parts of a Scene Graph.</H2>
|
|
It's sometimes useful to have sections of the scene graph that are never
|
|
rendered to the screen. These are frequently used for collision detection
|
|
and other non-graphical operations.
|
|
|
|
<H2><code>class ssgRoot</code> - The Root of the Scene Graph,</H2>
|
|
The node at the root of the scene graph is special. At present,
|
|
it resembles an ssgBranch externally.
|
|
<pre>
|
|
|
|
class ssgRoot : public ssgBranch
|
|
{
|
|
} ;
|
|
|
|
</pre>
|
|
|
|
<H2><code>class ssgTweenController</code> - A morph controller,</H2>
|
|
This is essentially identical to an ssgBranch - but adds API to
|
|
set the current 'bank' settings of all ssgTween leaf nodes beneath it.
|
|
<p>
|
|
An ssgTween is a leaf node that can hold multiple geometric
|
|
representations that it smoothly interpolates between.
|
|
<pre>
|
|
|
|
ssgTweenController::selectBank ( float b ) ;
|
|
float ssgTweenController::getCurrBank () ;
|
|
|
|
</pre>
|
|
This allows you to set which of the banks of it's daughter ssgTweens
|
|
will be rendered. That's a "float" quantity - so if you selectBank(2.4)
|
|
then the ssgTweens will render their vertices in a position (colour, etc)
|
|
that's 40% of the way between the bank 2 and bank 3.
|
|
<p>
|
|
You can also set the behaviour when the selected bank number is larger
|
|
than the number of banks in the model. This tends to happen when you
|
|
simply add some amount of to the bank selector each frame in order
|
|
to keep the animation running forever:
|
|
<pre>
|
|
|
|
ssgTweenController::setMode ( int mode ) ;
|
|
|
|
</pre>
|
|
'mode' can either be SSGTWEEN_STOP_AT_END or SSGTWEEN_REPEAT.
|
|
The default is STOP_AT_END - where anytime the bank selector
|
|
is larger than the actual number of banks in the ssgTween node,
|
|
it is clamped to the largest possible number. If you choose
|
|
REPEAT, then the bank number will be taken modulo the number of
|
|
banks.
|
|
<H2><code>class ssgSelector</code> - A switch point,</H2>
|
|
Most ssgBranch nodes represent a collection of objects that
|
|
are all present in the scene at the same time. ssgSelector
|
|
nodes (and derived classes) typically represent a single
|
|
object that can be represented in more than one way.
|
|
<p>
|
|
A selector contains up to 32 daughter objects and a
|
|
32 bit unsigned integer mask. Where there is a one bit
|
|
in the mask, that child object will be drawn, where
|
|
there is a zero, it will not.
|
|
<p>
|
|
<code>ssgSelector::select(mask)</code> sets the mask,
|
|
<code>ssgSelector::getSelect()</code> returns the current
|
|
state of the mask, <code>ssgSelector::selectStep(n)</code>
|
|
sets the n'th mask bit and zeroes out all the others - effectively
|
|
causing only the n'th child object to be displayed.
|
|
<p>
|
|
It is quite common to have an ssgSelector with just one
|
|
child object that can be enabled with select(1) and disabled
|
|
with select(0).
|
|
|
|
<H2><code>class ssgTimedSelector</code> - An animation node,</H2>
|
|
This is a selector in which the selection is made as a function
|
|
of the amount of time elapsed.
|
|
<p>
|
|
SSG will draw each of the child objects in turn for some amount
|
|
of time before going onto the next node in the sequence. You
|
|
set the time for each child using:
|
|
<pre>
|
|
|
|
ssgTimedSelector::setDuration ( float time, int which_child ) ;
|
|
|
|
</pre>
|
|
...or you can set the same time for each of the child nodes using:
|
|
<pre>
|
|
|
|
ssgTimedSelector::setDuration ( float time ) ;
|
|
|
|
</pre>
|
|
(At present, times are measured in SSG update cycles - ultimately,
|
|
there will be an option to set the times in seconds - but until
|
|
I have a reasonably accurate portable timer library, I can't
|
|
easily implement this).
|
|
<p>
|
|
The animation doesn't have to start at the first child node and
|
|
end at the last. It is sometimes useful to be able to replay
|
|
just a subset of them.
|
|
<pre>
|
|
|
|
ssgTimedSelector::setLimits ( int start_child, int end_child ) ;
|
|
|
|
</pre>
|
|
You can also choose between a number of animation algorithms:
|
|
<pre>
|
|
|
|
ssgTimedSelector::setMode ( ssgAnimDirection mode ) ;
|
|
|
|
Where mode is one of:
|
|
|
|
SSG_ANIM_ONESHOT, SSG_ANIM_SHUTTLE, SSG_ANIM_SWING
|
|
|
|
</pre>
|
|
<ul>
|
|
<li>In SSG_ANIM_ONESHOT mode, the animation starts at the first child
|
|
you specified with setLimits and ends at the last child you
|
|
specified. Once the last child has been displayed, the animation
|
|
will automatically go into STOP mode and continue to display
|
|
that last object until the application intervenes.
|
|
<li>In SSG_ANIM_SHUTTLE mode, the animation goes from the start
|
|
child to the end child - but unlike SSG_ANIM_ONESHOT, when
|
|
the animation has finished displaying the last child object,
|
|
it resets to the start child and does it all over again.
|
|
SSG_ANIM_SHUTTLE animations don't stop running unless the
|
|
application stops them.
|
|
<li>In SSG_ANIM_SWING mode, the animation goes from the start
|
|
child to the end child - but when the end is reached, the
|
|
animation reverses direction and heads back to the start
|
|
again. The animation oscillates like a swing until the
|
|
application stops it.
|
|
</ul>
|
|
<p>
|
|
When all this preparation is done, the application must
|
|
control the animation:
|
|
<pre>
|
|
|
|
ssgTimedSelector::control ( ssgAnimEnum cntrl ) ;
|
|
|
|
Where 'cntrl' is one of:
|
|
|
|
SSG_ANIM_START, SSG_ANIM_STOP,
|
|
SSG_ANIM_PAUSE, SSG_ANIM_RESUME
|
|
|
|
</pre>
|
|
These controls work just like you'd expect. Start, Stop,
|
|
Pause, Resume. SSG_ANIM_START resets the animation to
|
|
the 'start' child and lets it rip. SSG_ANIM_STOP causes
|
|
it to stop wherever it is and continue to display that
|
|
child node indefinitely. SSG_ANIM_PAUSE pauses the
|
|
animation wherever it is right now and SSG_ANIM_RESUME
|
|
allows it to continue from whatever point it was paused.
|
|
<p>
|
|
When the animation is in SSG_ANIM_STOP mode, you can
|
|
use this node just like a normal ssgSelector node
|
|
using the ssgSelector API.
|
|
<p>
|
|
If you need to know which child object is currently being
|
|
displayed, you cannot call ssgSelector::getSelect() because
|
|
SSG computes the animation step only if the node is actually
|
|
on-screen. Instead call ssgTimedSelector::getStep() which
|
|
returns the currently selected child node.
|
|
<H2><code>class ssgRangeSelector</code> - A level of detail node,</H2>
|
|
This is a selector in which the selection is made automatically
|
|
based on the range to the object. This is principally used to
|
|
allow you to save time by drawing simpler versions of objects
|
|
at long ranges and more complex ones close up.
|
|
<p>
|
|
Since an <code>ssgRangeSelector</code> is a kind of
|
|
<code>ssgSelector</code>, you can find
|
|
out which version of the object was most recently drawn using
|
|
<code>getSelect()</code>. However, if the object was not drawn recently, that
|
|
may not be a very useful thing to know. Mostly, it's useful in
|
|
the post-cull callback.
|
|
<p>
|
|
You set the ranges at which each daughter object will be drawn
|
|
by passing an array of lengths to
|
|
<code>ssgRangeSelector::setRanges(float *ranges,int nranges)</code>.
|
|
The first parameter is an array of ranges and the second is the
|
|
number of elements in that array. Note that element N of the
|
|
array is the range beyond which child object N will be drawn.
|
|
The array should contain one more range than there are child
|
|
objects - and beyond the last range, nothing will be drawn.
|
|
setRanges takes a copy of your array so you can delete it after
|
|
the call. If nranges is less than the number required, the
|
|
remaining ranges will be set to infinity. You can query the
|
|
current range array with <code>float getRange(int n)</code> which
|
|
returns the n'th range in the array.
|
|
<p>
|
|
In some cases, you'd like to build several complete versions
|
|
of an object such that just one of those versions will be
|
|
drawn - and that is the default behaviour. In other cases,
|
|
you'd like some basic object to be rendered at long range
|
|
and for additional parts to be added to it at shorter ranges.
|
|
This is called 'additive' mode and it is set using
|
|
<code>setAdditive(int additive)</code>
|
|
and queried with <code>isAdditive()</code>.
|
|
<H2><code>class ssgBaseTransform</code> - Nodes with transformations.</H2>
|
|
It is common to wish to move objects around in the scene, scale and rotate
|
|
them, move their texture maps, etc. All of these operations entail
|
|
manipulating a matrix associated with the branch node and the
|
|
ssgBaseTransform contains the functionality to store and manipulate
|
|
that matrix. Applications use one of the derived classes of ssgBaseTransform
|
|
to actually do something with that matrix.
|
|
<pre>
|
|
|
|
class ssgBaseTransform : ssgBranch
|
|
{
|
|
void getTransform ( sgMat4 xform ) ;
|
|
virtual void setTransform ( sgVec3 xyz ) ;
|
|
virtual void setTransform ( sgCoord *xform ) ;
|
|
virtual void setTransform ( sgCoord *xform, float sx, float sy, float sz ) ;
|
|
virtual void setTransform ( sgMat4 xform ) ;
|
|
} ;
|
|
|
|
</pre>
|
|
You can set up the transformation matrix using <code>ssgBaseTransform::setTransform()</code>
|
|
which has versions that allow you to pass either a full-blown
|
|
4x4 matrix, a simple translation, an 'sgCoord' (which is an xyz translation
|
|
and a hpr rotation) or an sgCoord and scale factors in each of X, Y and Z
|
|
directions.
|
|
<p>
|
|
<code>ssgBaseTransform::getTransform(matrix)</code> copies the current
|
|
transform into the matrix that you provide.
|
|
<H2><code>class ssgTransform</code> - Nodes with spatial transformations.</H2>
|
|
An ssgTransform is derived from ssgBaseTransform and uses the base classes'
|
|
transform to transform all the spatial vertices and normals of it's
|
|
child nodes. This is done by applying the current transform to the
|
|
GL_MODELVIEW stack each frame.
|
|
<H2><code>class ssgTexTrans</code> - Nodes with moving texture</H2>
|
|
ssgTexTrans nodes are just like ssgTransform nodes except that the
|
|
resulting matrix is applied to the GL_TEXTURE stack rather than
|
|
the modelview stack. Hence, altering the transform moves the texture
|
|
map(s) on the descendent leaf nodes.
|
|
<H2><code>class ssgCutout</code> - turn-to-face-the-viewer nodes.</H2>
|
|
Cutout nodes will normally contain only leaf nodes that are
|
|
modelled with polygons in the X/Z plane. The ssgCutout will rotate
|
|
those polygons such that they turn to continually face the viewer.
|
|
<p>
|
|
There are actually two distinct forms of ssgCutout - depending on
|
|
what value is passed as a parameter to the constructor function.
|
|
ssgCutout(TRUE) produces an object that rotates around it's
|
|
origin such as to keep the X/Z plane parallel to the screen and
|
|
ssgCutout(FALSE) produces one that tries to stay parallel to the
|
|
screen - but which is only allowed to rotate about the Z axis.
|
|
The latter form is useful for objects with cylindrical symmetry
|
|
and the former for those with spherical symmetry.
|
|
|
|
<hr>
|
|
<table width="100%">
|
|
<tr>
|
|
<td width="33%" align="left"><a href="ssgLeaf.html"><= previous =</a></td>
|
|
<td width="34%" align="center"><a href="index.html">Return to SSG Index</a></td>
|
|
<td width="33%" align="right"><a href="state.html">= next =></a></td>
|
|
</tr>
|
|
</table>
|
|
<hr>
|
|
<table>
|
|
<tr>
|
|
<td>
|
|
<a href="http://validator.w3.org/check/referer"><img border="0" src="../valid-html40.png" alt="Valid HTML 4.0!" height="31" width="88"></a>
|
|
<td>
|
|
<ADDRESS>
|
|
<A HREF="http://www.sjbaker.org">
|
|
Steve J. Baker.</A>
|
|
<<A HREF="mailto:sjbaker1@airmail.net">sjbaker1@airmail.net</A>>
|
|
</ADDRESS>
|
|
</table>
|
|
</BODY>
|
|
</HTML>
|
|
|