|
Syzygy Documentation: Myriad Scene GraphIntegrated Systems Lab04/12/2006 Documentation Table of Contents
BackgroundThis section introduces the Myriad scene graph and explains its C++ API. For the (similar) Python API, please see this [tutorial SceneGraphTutorial.html]. Python's internal reference counting is integrated with Myriad's, so their combined operation is thread-safe (e.g. when a remote peer in a shared scene graph deletes nodes). Several scene graph examples are written in Python.
When reading this section, first understand the basic design of the Myriad distributed scene graph, including how lighting, texturing, and coordinate arrays are inherited to guide where rendering happens, at the "drawable" nodes. Also understand how to [construct #Constructing] a node tree and populate it with built-in objects. That lets you get something running quickly. Using the Myriad Scene Graph in Your ProgramsThe easiest way to use Myriad in your programs is via Syzygy's scene graph application framework (arDistSceneGraphFramework), which is supported in both C++ and Python. You will want direct access to the underlying arGraphicsDatabase, which is provided by the framework's getDatabase() method. It is also possible to use arGraphicsDatabase objects directly in your programs, without an application framework. Myriad's Basic DesignThe arGraphicsDatabase object is the fundamental tool for working with the Myriad scene graph. It receives a stream of messages causing it to alter its internal contents. These messages are either in the form of arStructuredData or byte blocks which can be parsed into arStructuredData. The alter() method receives arStructuredData, while the alterRaw() method receives byte blocks, parses them, and runs the resulting arStructuredData object through alter(). The arGraphicsDatabase object manages a tree of arGraphicsNode objects. The base class arGraphicsNode is subclassed to define the various types of nodes, like visibility nodes, texture nodes, lines nodes, etc. These objects have three important methods, receiveData(), draw(), and dumpData(). Message streams sent to the arGraphicsDatabase via alter()/alterRaw() are either routed to the arGraphicsDatabase itself, like the message that requests a new node be created, or to a specific node, via that node's receiveData() method. For instance, a message might ask that a visibility node turn itself on or off. The draw() method renders graphics via OpenGL, and the dumpData() method serializes the node, creating a message that can be used to replicate that node in another arGraphicsDatabase. In Myriad cluster rendering, graphics state is synchronized across multiple machines by replicating arGraphicsDatabase objects on each machine. An arGraphicsServer object exists embedded in the application on the master machine and an arGraphicsClient object exists embedded in an szgrender on each render box (slave); both arGraphicsServer and arGraphicsClient manage an arGraphicsDatabase. When an arGraphicsClient connects to the arGraphicsServer, the server serializes the state of its arGraphicsDatabase (using the dumpData() methods of its nodes) and sends it across the network to the newly-connected arGraphicsClient, which then uses the alterRaw() method of its arGraphicsDatabase to recreate the remote state. Subsequently, all alter() calls to the arGraphicsDatabase managed by the arGraphicsServer are mirrored over the network to those managed by the connected arGraphicsClients. This message stream can be coordinated with graphics buffer swaps on the render computers to ensure perfect state synchronization at each draw. Node Inheritance and DrawingMany operations, like drawing or intersection with a ray or bounding sphere, require traversing the arGraphicsDatabase's tree. Tree traversal is generally depth-first, with child nodes visited in the order they were added (though the permuteChildren(...) method of arGraphicsDatabase can change this). Tree traversal is made thread-safe with respect to node removal (from another thread as might occur when the scene graph powers a shared world in peer-to-peer mode) via a reference counting mechanism. The traversing process increments the reference count of nodes it uses (decrementing the reference count when it is through with them). The owning arGraphicsDatabase, upon receiving a deletion message, decrements the nodes' reference counts and removes them from its internal tree. It does not delete them. Instead, a node deletes itself once its reference count has fallen to 0.
Many properties related to drawing, like the active texture, material, points set, and normals set, are inherited down the scene graph tree, from parent to child. As a tree traversal occurs, an arGraphicsContext object keeps track, at each visited node, of the ancestor nodes that hold the active properties, and, at an arDrawableNode, the active properties are used to actually draw a mesh. As an example, when the traversal passes an arMaterialNode (going down into the tree) the active material is changed to the arMaterialNode's. Similarly, as the traversal passes the arMaterialNode the other way (going back up the tree after visiting all nodes in the subtree), the active material reverts to its previous value. In this way, the graphical characteristics of a drawable node only depend on its ancestors, not on nodes to the left or the right in the scene graph. This localization is very important for guaranteeing predictable results when node trees are combined. The following is a complete list of the properties used by the arDrawable node in drawing. If you are using the built-in shapes only, the blend, material, and texture properties are the only relevant ones.
Node Types
Constructing a Node TreearGraphicsDatabase is a subclass of arDatabase, as arGraphicsNode is a subclass of arGraphicsNode. A short summary of the kinds of operations that are possible. Node names. The root node has a special name ("root") and ID (0).
string arDatabaseNode::getName() const;
void arDatabaseNode::setName(const string& name);
Node IDs. Cannot set node ID This is done by an arDatabase only in node construction. An arDatabase never repeats node IDs for the nodes it creates.
int arDatabaseNode::getID();
Node info.
string arDatabaseNode::getInfo() const;
void arDatabaseNode::setInfo(const string& info);
Node type.
string arDatabaseNode::getTypeString() const;
Creating new nodes. This must be done via the arDatabase.
arDatabaseNode* arDatabase::getRoot();
arDatabaseNode* arDatabase::newNode(arDatabaseNode* parent,
const string& type,
const string& name = "",
bool refNode = false);
arDatabaseNode* arDatabaseNode::newNode(const string& type,
const string& name = "",
bool refNode = false);
Reference counting. Necessary for thread-safety (if another thread is deleting).
void arDatabaseNode::ref();
void arDatabaseNode::unref();
int arDatabaseNode::getRef();
bool arDatabaseNode::active();
list<arDatabaseNode*> arDatabaseNode::getChildrenRef();
Deleting nodes, cutting and erasing.
bool arDatabase::cutNode(arDatabaseNode* node);
bool arDatabase::cutNode(int ID);
bool arDatabase::eraseNode(arDatabaseNode* node);
bool arDatabase::eraseNode(int ID);
Inserting between existing parent and child (or in front of ALL of a parent's children). Must go through arDatabase to avoid deadlocks.
arDatabaseNode* arDatabase::insertNode(arDatabaseNode* parent,
arDatabaseNode* child,
const string& type,
const string& name = "",
bool refNode = false);
Permuting children.
void arDatabase::permuteChildren(arDatabaseNode* parent,
list<arDatabaseNode*>& children);
void arDatabaseNode::permuteChildren(list<arDatabaseNode*>& children);
Inspecting and traversing the node tree.
arDatabaseNode* arDatabaseNode::getParent() const;
list<arDatabaseNode*> arDatabaseNode::getChildren() const;
void arDatabaseNode::ps(int maxLevel=10000);
Finding nodes via name or ID.
arDatabaseNode* arDatabaseNode::findNode(const string& name,
bool refNode = false);
arDatabaseNode* arDatabaseNode::findNodeByType(const string& type.
bool refNode = false);
arDatabaseNode* arDatabase::getNode(int ID);
Manipulating node level. Imporant only for peer-to-peer reality.
arNodeLevel getNodeLevel();
void setNodeLevel(arNodeLevel nodeLevel);
Helper ClassesarMaterial, with the fields having the same meaning and defaults as in the OpenGL specification.
arVector3 diffuse;
arVector3 ambient;
arVector3 specular;
arVector3 emissive;
float exponent;
float alpha;
arLight, with the fields having the same meaning and defaults as in the OpenGL specification.
int lightID;
arVector4 position;
arVector3 diffuse;
arVector3 ambient;
arVector3 specular;
float constantAttenuation;
float linearAttenuation;
float quadraticAttenuation;
arVector3 spotDirection;
float spotCutoff;
float spotExponent;
arBoundingSphere
arVector3 position;
float radius;
bool visibility;
arRay
arVector3 origin;
arVector3 direction;
Using Built-In Objects
Mention attachMesh. Mention setTransform. arSphereMesh: Sphere of radius 1 centered at (0,0,0).
void arSphereMesh::setSectionSkip(int skip);
arCubeMesh: Cube with side length 1 centered at (0,0,0) and axis-aligned. arCylinderMesh: Cylinder of length 1 pointing along the z axis.
void arCylinderMesh::setAttributes(int numberDivisions,
float bottomRadius,
float topRadius);
void arCylinderMesh::toggleEnds(bool useEnds);
arRectangleMesh: Square with sides of length 1 centered at (0,0,0). Normal in the positive y direction. Explain texture coordinates? arTorusMesh: Torus in the x-y plane.
void arTorusMesh::reset(int numberBigAroundQuads,
int numberSmallAroundQuads,
float bigRadius,
float smallRadius)
Importing files in .obj format. Node Methods in C++
void arDatabaseNode::lock();
void arDatabaseNode::unlock();
arMatrix4 arTransformNode::getTransform();
void arTransformNode::setTransform(const arMatrix4& transform);
string arTextureNode::getFileName();
void arTextureNode::setFileName(const string& fileName, int alpha = -1);
string arBillboardNode::getText();
void arBillboardNode::setText(const string& text);
bool arVisibilityNode::getVisibility();
void arVisibilityNode::setVisibility(bool visibility);
float arBlendNode::getBlend();
void arBlendNode::setBlend(float blendFactor);
arLight arLightNode::getLight();
void arLightNode::setLight(arLight& light);
arMaterial arMaterialNode::getMaterial();
void arMaterialNode::setMaterial(const arMaterial& material);
const float* arNormal3Node::getNormal3(int& number);
void arNormal3Node::setNormal3(int number, float* normal3, int* IDs = NULL);
vector arNormal3Node::getNormal3();
void arNormal3Node::setNormal3(vector& normal3);
void arNormal3Node::setNormal3(vector& normal3,
vector& IDs);
const float* arColor4Node::getColor4(int& number);
void arColor4Node::setColor4(int number, float* color4, int* IDs = NULL);
vector arColor4Node::getColor4();
void arColor4Node::setColor4(vector& color4);
void arColor4Node::setColor4(vector& color4,
vector& IDs);
const float* arTex2Node::getTex2(int& number);
void arTex2Node::setTex2(int number, float* tex2, int* IDs = NULL);
vector arTex2Node::getTex2();
void artex2Node::setTex2(vector& tex2);
void arTex2Node::setTex2(vector& tex2,
vector& IDs);
const int* arIndexNode::getIndices(int& number);
void arIndexNode::setIndices(int number, int* indices, int* IDs = NULL);
vector arIndexNode::getIndices();
void arIndexNode::setIndices(vector& indices);
void arIndexNode::setIndices(vector& indices,
vector& IDs);
Drawable Node SpecificsRelationship between drawable number, the sizes of the various arrays, and the number of primitives drawn.
int arDrawableNode::getType(); string arDrawableNode::getTypeAsString(); int arDrawableNode::getNumber(); void arDrawableNode::setDrawable(arDrawableType type, int number); void arDrawableNode::setDrawableViaString(const string& type, int number); Graphics State Node
string arGraphicsStateNode::getStateName();
bool arGraphicsStateNode::isFloatState();
bool arGraphicsStateNode::isFloatState(const string& stateName);
string arGraphicsStateNode::getStateValueString(int i);
float arGraphicsStateNode::getStateValueFloat();
bool arGraphicsStateNode::setGraphicsStateString(const string& stateName,
const string& value1,
const string& value2 = "false");
bool arGraphicsStateNode::setGraphicsStateFloat(const string& stateName,
float stateValueFloat);
Notes on Thread SafetyThe Myriad scene graph is thread-safe, for instance, with respect to drawing in multiple threads even with simultaneous deletions and other scene graph restructurings occur in still other threads. |
|
[Schedule] [Labs] [Beckman Meeting Rooms] [Equipment] [Projects] [CUBE Projects] [Syzygy] [VSS] [People] [Events] [Publications] |