University of California, Berkeley EECS Dept, CS Division |
||
Jordan Smith |
SLIDE: Scene Language for Interactive Dynamic Environments |
Prof. Carlo H. Séquin |
Home | Goals | Publications | People | Gallery | Assignments | Distributions |
The file diamonds.slf contains the description of a 2D dynamic scene made up almost entirely of diamonds. The diagrams below show two frames from the diamonds' animation. The diamonds are all blue. The static bounding boxes appear in white, and the dynamic bounding boxes appear in red. The upper left hand corner contains a static group of two diamonds. The upper right hand corner contains another static instance of the group of two diamonds with another diamond surrounding them which is statically rotated and is scaling in a pulsating manner. The bottom left hand corner contains a morphing diamond which has a dynamic point. The bottom right hand corner contains the same morphing diamond rotated 90 degrees. The left hand diagram shows the dynamic objects at their minimal extent, and the right hand diagram shows them at their maximal extent.
The objectives of Preprocess
are: to initialize any
dynamic TCL values, mark any objects which have any dynamic fields as
dynamic, and to mark all the bounding boxes in the object
and group
nodes of the scene graph as invalid. In the
Preprocess
phase of execution, the
CSLIDEWorld
object calls the Preprocess
method flatly on each object of all types (
CSLIDESurfaces
, CSLIDEPoints
,
CSLIDEFaces
, CSLIDETransforms
,
CSLIDEInstances
, CSLIDEObjects
and
CSLIDEGroups
and CSLIDECameras
and
CSLIDELights
, CSLIDEViewports
, and
CSLIDERenders
) exactly once. The
CSLIDEWorld
's dynamics list is not used or modified while
preprocessing.
The objects initialize any dynamic values by executing the TCL
statement which is stored as a string. DynVector
,
DynPoint
, and DynFloat
type variables
execute any TCL commands associated with them when their respective
Update
method is invoked.
An object can tell if its fields are dynamic by calling their
GetDynamic()
boolean method. This method returns true if
any of the data values are controlled by a TCL statement. The dynamic
objects are colored red in the diagram below.
Bounding boxes are invalidated in this flat pass over the data
structure to optimize the traversal of the scene graph in the
PreprocessGraph
phase of execution. The bounding box
valid flag can be used to check whether a node has already been
processed in the depth first traversal of the scene graph DAG which is
executed by the PreprocessGraph
function.
The diagram below shows the state of the scene graph DAG, of the
diamonds.slf
example, after Preprocess
has
been executed. The red nodes in the graph correspond to objects which
have been marked dynamic because one or more of their fields are
dynamic. Note that CSLIDEInstances
consider their
CSLIDETransforms
as fields, but CSLIDEGroups
do not consider their CSLIDEInstances
as fields.
CSLIDEInstances
are considered as arcs in the scene graph
instead. The CSLIDEWorld
's list of dynamic object is
empty. ( Note: There is a spurious arrow head pointing from the
camera to the dynamics list. And the rotation transform, "R," in the
iPulsate instance is not dynamic, but the scale, "S," is dynamic. )
CSLIDEWorld::Preprocess()
: flatly for each (
CSLIDESurfaces
, CSLIDEPoints
,
CSLIDEFaces
, CSLIDETransforms
,
CSLIDEInstances
, CSLIDEObjects
and
CSLIDEGroups
and CSLIDECameras
and
CSLIDELights
, CSLIDEViewports
, and
CSLIDERenders
) call the Preprocess
method:
For a cleaner view of the graph view the postscript version: preprocess.ps.
The objectives of the PreprocessGraph
phase of
execution are: to initialize the bounding boxes of the nodes of the
scene graph and mark any object
or group
nodes whose bounding boxes could change dynamic as having a dynamic
bounding box. In the PreprocessGraph
phase of execution,
the CSLIDEWorld
object calls the
PreprocessGraph
method on each of its
CSLIDERender
objects. Each CSLIDERender
object initiates a depth first traversal of its scene graph by
recursively calling the PreprocessGraph
method of its
root node. At the end of the PreprocessGraph
traversal
of the scene graphs, the CSLIDEWorld
object flatly runs
through all of the its objects and places any objects with dynamic
fields or dynamic bounds on its dynamics list.
Bounding boxes are calculated for every CSLIDEObject
and CSLIDEGroup
in the scene graph hierarchy. These
bounding boxes are created recursively, so a CSLIDEGroup
creates its bounding box by first having its children create their
bounding boxes and then transforming their bounding boxes to create
the local bounding box. It should only be necessary to calculate a
bounding box exactly one time in this depth first traversal. This is
acheived by marking the bound valid flag true after the bounding box
is created, and by only calculating bounding boxes for nodes who's
bounding boxes are invalid. The green arrows in the diagram below
demonstrate how the depth first traversal avoids doing redundant
work.
A node of the scene graph hierarchy should be marked as having a dynamic bounding box if one of its children has a dynamic bounding box or if one of instances is dynamic and the node pointed to by that instance actually has a bounding box. All real geometry nodes have bounding boxes. Cameras and lights do not contain any real geometry, so they do not have a boundary. Following from this fact, any subtree of the graph which only contains camera or light leaves has no boundary. The nodes with dynamic bounding boxes are colored purple in the diagram below. It is possible for a group to have dynamic fields, but not have a dynamic bounding box. For example, it could have a dynamic surface properties which do not alter its geometric extent.
After PreprocessGraph
is done
CSLIDEWorld::CreatDynamicsList()
is called. In this
procedure, the CSLIDEWorld
runs through its
CSLIDESurfaces
, CSLIDEPoints
,
CSLIDEFaces
, CSLIDETransforms
,
CSLIDEInstances
, CSLIDEObjects
and
CSLIDEGroups
and CSLIDECameras
and
CSLIDELights
, CSLIDEViewports
, and
CSLIDERenders
in this order. It adds any object which is
dynamic or has a dynamic bounding box to the dynamics list,
maintaining the order in which they are checked. Objects will be
updated in the order which they appear in the dynamics list. An
example of why this order might be important is transforms and instances.
If transforms are updated before instances, then instances can
premultiply their transforms into a single matrix which can then be
used in the graph update.
In the diagram below, notice that the dynamic transforms appear
before the instances which reference them. Also notice that the
static rotation from the iPulsate
instance does not
appear in the dynamics list.
CSLIDEWorld::PreprocessGraph()
: for each
CSLIDERender
object call the PreprocessGraph
method:
PreprocessGraph
on all children
For a cleaner view of the graph view the postscript version: preprocessgraph.ps.
The objectives of Update
are: to update any dynamic
TCL values and mark all the bounding boxes invalid for the objects on
the dynamics list. The CSLIDEWorld
object is awaken by a
timer event which invokes its Update
method. The
CSLIDEWorld
object only touches the objects on the
dynamics list which is illustrated by the green arrows traversing the
dynamics list in the diagram below. After the flat
Update
is executed CSLIDEWorld
object then
calls the recursive UpdateGraph
method.
CSLIDEWorld::Update()
: flatly for each object in
the dynamics list call the Update
method:
For a cleaner view of the graph view the postscript version: update.ps.
The objective of the UpdateGraph
phase of execution
is to update the bounding boxes of the dynamic nodes of the scene
graph. In the UpdateGraph
phase of execution, the
CSLIDEWorld
object calls the UpdateGraph
method on each of its CSLIDERender
objects. Each
CSLIDERender
object initiates a depth first traversal of
its scene graph by recursively calling the UpdateGraph
method of its root node. At the end of the UpdateGraph
traversal of the scene graphs, the world geometry data base is
consistent and ready to be rendered. The CSLIDEWorld
sends redisplay events to all of the SLIDE windows, so that they will
update their renderings of the world.
The green arrows in the diagram below demonstrate how the depth first traversal avoids doing redundant work. Redunandant works includes recomputing bounding boxes of static nodes as well as recomputing bounding boxes of dynamic nodes more than once.
CSLIDEWorld::UpdateGraph()
: for each
CSLIDERender
object call the UpdateGraph
method:
UpdateGraph
on all children
For a cleaner view of the graph view the postscript version: updategraph.ps.
Each CWindow
will call its rendering pass when it
receives a redisplay event. The diagram below shows what the
rendering pass looks like for the full SLIDE rendering pipeline.
For a cleaner view of the graph view the postscript version: render.ps.
This page was originally built by Jordan Smith.
Last modified: Saturday, 08-May-1999 17:03:10 PDT