Cosmo 3D is a scene graph API that brings 3D graphics programming to desktop applications. Cosmo 3D speeds up and facilitates the process of creating complex graphics applications. It allows applications to use a higher-level interface than the lower-level OpenGL language that it is based on. Developers interact with C++ objects that are arranged in an object hierarchy.
With its scene graph architecture and features such as culling, level of detail (LOD), 2D texture mapping, and audio, Cosmo 3D enables you to develop complex graphic applications, for example, professional character animations and gaming applications.
After creating a scene graph using Cosmo 3D objects, developers can use the OpenGL Optimizer API to improve performance. See the manual OpenGL Optimizer Programmer's Guide: An Open API for Large-Model Visualization for more information.
This chapter gives an overview of the base classes of a Cosmo 3D scene graph. Understanding how each class contributes to the scene graph is essential for making optimal use of the API. These are the sections in this chapter:
A scene graph is a directed acyclical graph of nodes that embodies the semantics of what is to be drawn, but not how it is to be drawn. Developers interacting with a scene graph are interested in achieving a result, usually seeing a model on screen and manipulating it. They leave it up to Cosmo 3D to achieve this result in the most efficient way.
A Cosmo 3D scene graph consists of objects that inherit appropriate methods and fields from the Cosmo 3D classes. Conceptually, there are four kinds of classes:
Base classes—csObject, csField, csContainer, and csNode. These classes are never instantiated directly. Instead, applications create subclasses that inherit certain functionality from the base classes. Base classes are discussed in this chapter.
Scene graph construction classes—csGroup, csShape, csGeometry, and csAppearance determine appearance in a general way.
Specific appearance classes—csContext, csDrawTraversal, csEnvironment and some of their subclasses determine how things are drawn, for example, whether lights or fog are applied.
Geometry classes, such as csSphere or csCylinder, are the building blocks of the model itself.
This manual starts by discussing the different kinds of classes. It then briefly lists the steps required to create a simple sample program. The sample program itself is listed in Appendix B, “Cosmo 3D Sample Application.”
This section discusses the following abstract, base classes that provide the functionality that is necessary to implement a scene graph:
The csObject class is the base class for all objects in a scene; where an object is an entity that you can place in the scene graph. A csObject provides reference counting and runtime typing for all its children.
Many kinds of data objects in Cosmo 3D can be placed in a hierarchical scene graph. Using instancing, an object can be referenced multiple times. Scene graphs can become quite complex, which can cause problems if you're not careful. Deleting objects can be a particularly dangerous operation, for example, if you delete an object that another object still references.
Within each csObject is a counter that keeps track of the number of objects referencing a particular instance. Reference counting provides a bookkeeping mechanism that makes object deletion safe: an object should never be deleted if its reference count is greater than zero. In general, you should only unreference an object in case it is referenced by another object.
It is just as important, however, not to unreference an object that has not been referenced. Because the reference count is an unsigned integer, unreferencing an object that has not been referenced decrements the reference count from 0 to a large positive number and it will never be deleted.
Each csObject is created with a reference count of 0. It is important to reference an object when it is created to make sure that someone else does not delete it when they unreference it.
When object A is attached to object B, the reference count of A is incremented. Additionally, if A replaces a previously referenced object C, the reference count of C is decremented.
Example 1-1 demonstrates how reference counts are incremented and decremented.
csAppearance *appearanceA, *appearanceC; csGeoSet *gset; csShape *shape; shape->setGeometry(0, gset); /* Attach appearanceC to gset. Reference count of appearanceC * is incremented. */ shape->setAppearance(appearanceC); /* Attach appearanceA to gset, replacing appearanceC. Reference * count of appearanceC is decremented and that of appearanceA * is incremented. */ shape->setAppearance(appearanceA); |
When the reference count of an existing csObject becomes 0, the object is assumed not to be referenced by any other object and is deleted. An object that has nothing above itself in the scene hierarchy is removed because it is no longer part of the scene graph.
This automatic reference counting is usually all you ever need to use. However, the routines csObject::Ref(), csObject::Unref(), and csObject::GetRefCount() allow you to increment, decrement, and retrieve the reference count of a csObject should you wish to do so.
Each csObject knows what type it is. Applications can find out the class object of an instance by querying the object with getClassType(), as in the following example:
// csContainer *ctr if(ctr->getType() == csMaterial::getClassType()) printf(“It's a csMaterial!\n”); else printf(“It's not a csMaterial!\n”); |
You need to know the runtime type of an object so you can invoke the right code to manipulate an object.
For checking the derivation of a type, use csObject::isOfType().
csContainer objects contain data associated with scene graphs. The data in csContainer objects is grouped into fields (csField). Fields are not accessible directly to applications. Instead, set() and get() methods are provided to set and return field values.
Each field contains either a single value of a simple data type, such as a float, or a group of values, all of simple data types.
As an abstract, base class, csContainer provides functionality common to all objects containing fields, such as generic access to the fields, creating and deleting field connections, and managing reference counts when objects are added and removed as fields.
Fields contain the data of csContainer objects; data generally associated with scene graphs. All publicly-accessible fields in classes derived from csContainer should be derived from csField.
Fields differ from standard C++ data members. Fields are not evaluated until they are queried. Consequently, none of the meta information (for example, the field's name) exists unless you ask for it.
Fields are compact but they still allow applications complete access in two ways:
Indirect access. Methods for field access and modification are part of each class. Most of the time, applications access fields using these get*() and set*() functions.
Generic access. Applications can query any container object abstractly using getFieldInfo() on any object that inherits from csContainer. This is useful for getting information about unknown objects and makes it possible, for example, to create a GUI for an application.
Each field contains either a single value of a simple data type, such as a float, or a group of values, all of simple data types.
Single Item Fields—Single-valued field types, including SFDouble, SFEnum, SFRef, SFString, SFInt, SFFloat, SFVec2f, SFVec3f, SFVec4f, SFBitMask, SFName, SFMatrix4f, SFRotation.
Multiple Item Fields—Multi-valued field types, including MFRef, MFString, MFInt, MFFloatMFMatrix4f, MFVec2f, MFVec3f, MFVec4f, MFRotation.
For more information about single- and multi-item fields, see “Setting the Values in Scene Graph Nodes”.
All Cosmo 3D scene graph components, except leaf objects, such as csGeometry, are derived from csNode. csNode, a subclass of csContainer, maintains a bounding sphere for the geometry and the descendant geometry associated with a csNode-type object, such as csGroup.
csNode is the fundamental object to which csActions are applied.
For more information about leaf objects, see “Leaf Nodes”.
For more information about bounding spheres, see “Bounding Volumes”.
This section discusses several essential elements of a scene graph.These elements are part of most scene graphs and make it possible for the geometry elements of a model to be drawn and to relate to one another.
Figure 1-1 shows a basic scene graph similar to the example program discussed in Appendix B, “Cosmo 3D Sample Application.” Black lines indicate parent-child relationships; gray lines indicate class-field links.
The figure shows the following elements, which are discussed in this section:
“The csGroup Class”—allows you to group csNodes.
“The csTransform Class”—applies a transformation, such as rotation, scaling, to all its children.
“The csShape Class”—encapsulates a geometric shape; providing appearance and geometry fields and a draw() method.
“The csAppearance Class”—contains fields to specify the material properties of a surface, including transparency, color, and texture.
“The csGeometry Class”—encapsulates the geometric data to which a csAppearance can be applied.
The csGroup class allows applications to group a list of csNodes. When the application then applies actions to the csGroup, the actions traverse the scene graph starting at the group-type node. The group-type node passes the action to some or all of its children. The bounding sphere of a csGroup is the bounding sphere containing all the bounding spheres of its children.
In Figure 1-1, a group node is the top of the scene graph, joining two csTransform nodes and a light.
A csTransform is a csGroup that allows applications to apply a transformation to all of its children. A csTransformAction pushes down an action's matrix stack, applies the transform to the top of the stack, visits the children, and then pop the action's matrix stack.
See “Transforming Shapes to New Locations, Sizes, and Orientations” for more information.
Once you define the orientation of a shape, you use csTransform nodes to place and orient the shape in a different coordinate system. World space is the coordinate system of the root node. If all the shapes in a scene graph are transformed into world space, a csCamera object attached to the root node can view all the shapes in the scene graph together in one coordinate system.
World space is rendered when a draw action is applied to the root node of the scene graph; local space is rendered when a draw action is applied to a subsection of the scene graph. The same object rendered in these two spaces may appear different, for example, a shape in world space may appear smaller than in local space because it is farther from the viewer; it might also be rotated and positioned differently.
There are usually many transformation nodes in a scene graph and a shape is often transformed more than once. Figure 1-2 illustrates how a leaf node is first transformed twice, then placed in world space.
csShape nodes, derived from csNode, define a textured geometry by associating a csAppearance, which describes the look of a shape (such as its color), with a csGeometry, which defines the dimensions of the geometry (such as whether the geometry is a cube or sphere).
A csAppearance contains fields to specify the material properties of a surface, including transparency, color, and texture. csAppearance also provides some facilities borrowed from OpenGL, like specifying whether the surface is drawn filled or in wireframe mode, and the alpha and depth functions to use. csAppearance is associated with a csGeometry container by a csShape, which contains fields for one appearance and a list of geometry.
csGeometry encapsulates the geometric data to which a csAppearance can be applied. For example, a csGeometry can define a sphere onto which the texture of an orange can be applied to create a realistic image of an orange. Together, csGeometry and csAppearance combine to form a textured shape. csShape associates the two classes.
The set of nodes discussed in this section determines how things are drawn.
“csContext”—Maintains the OpenGL state, for example,
“The csEnvironment Classes”—Determines how lights and fog are applied to its children.
csContext defines the default, global graphics state of shapes in the scene graph. Shapes inherit some or all of the csContext values according to the values set in a mask. csAppearance values set on shapes override the default csContext values. Similarly, geometry values, defined in csContext, can be overridden by individual shapes.
csContext is multi-threaded. A thread can associate a csContext and a csWindow to facilitate multi-threaded processing. For more information about multi-threading, see Chapter 13, “Multiprocessing.”
For more general information about csContext, see “csContext Overview”.
The csEnvironment class determines how lights and fog are applied to the scene graph.
The lights that affect a csShape during a csDrawAction are the lights attached to all ancestor csEnvironments of the shape, plus all lights applied before invoking the traversal. For more information on lights, see Chapter 8, “Lighting and Fog.”
The actual geometric objects in a Cosmo 3D scene graph are derived as follows:
For more information, see Chapter 2, “Creating Geometries.”
The following procedure summarizes the steps you take to create and render the simple scene graph shown in Figure 1-1. This scene graph is created by the example program discussed in Appendix B, “Cosmo 3D Sample Application.”
Create csAppearance and csGeometry containers to define the appearance and the geometry of a shape.
For more information on setting csAppearance values, see Chapter 3, “Specifying the Appearance of Geometries.” For more information on setting csGeometry values, see Chapter 2, “Creating Geometries.”
Create csShape and csTransform nodes.
For more information on setting csShape values, see Chapter 2, “Creating Geometries.”
Associate the csAppearance and csGeometry containers using the csShape node.
Add the csShape node as a child of a csTransform node.
The csTransform node orients and positions the geometry encapsulated in the csShape node. For more information on setting csTransform values, see Chapter 6, “Placing Shapes in a Scene.”
![]() | Note: A csShape node by itself can be a complete scene graph. Typically, however, scene graphs have many csShape nodes, most of which are connected to other parts of the scene graph with csTransform nodes. |
Add the csTransform node as a child of a csGroup-type node.
For more information about adding nodes to scene graphs, see Chapter 6, “Placing Shapes in a Scene.”
Create a window, csWindow, in which to view the application and interact with it.
Set the current graphical context, csContext.
Draw all of the shapes in world space by applying a csDrawAction to the root of the scene graph.
The root node is the csGroup-type node at the “top” of the scene graph. For more information about draw actions, see Chapter 7, “Traversing the Scene Graph.”