Introduction to Open Inventor

Open Inventor is C++ toolkit on the top of OpenGL, used to create graphics and interaction in three-dimensions. Compared to programming using directly OpenGL, it is much easier and C++ allows a programmer to create new classes derived from the toolkit. The productivity becomes much higher. Besides doing graphics (the main purpose of OpenGL), classes for user interaction (viewers, draggers, and manipulators) allow the construction of user interfaces in three-dimensions. Open Inventor is also a file format for exchanging geometry data, including object behavior (engines).

File format

The file format allows one to create a scene without programming. The program ivview can view the contents. The file format has two representations; the ASCII file structure is well-documented, but the binary format is not open. The program ivcat (man ivcat) can convert between the formats. A simplified grammar is file-asc := header body body := node body | empty node := node-name { body | fields } fields := field fields | empty field := field-name field-value

Example: cube

Display Source Grammar
a cube #Inventor V2.0 ascii Separator { Cube { width 1 height 2 depth 3 } } header node-name { node-name { field-name field-value field-name field-value field-name field-value } }

Data Structure

The data structure is basically a tree which is parsed from top to bottom and left to right, but the use of connections, an essential part of engines, force us to use the word graph. The objects in the graph are nodes. During parsing the graph (e.g., for rendering) a state is accumulated. Objects in the graph are nodes with attributes called fields. An important node is the Separator. The Separator pushes the state (i.e. transformation matrix, color, etc.) on a stack. After parsing the subgraph under the Separator, the state is popped, and all state changes done in the subgraph do not affect the subsequent (following) nodes.

Example: Effect of a Separator node

Display Source Graph
Separator Example #Inventor V2.0 ascii Separator { Material { diffuseColor 0 0 1 } Cube {} Separator { Material { diffuseColor 1 0 0 } Transform { translation -1 0 0 } Sphere {} } Transform { translation 1 0 0 } Sphere {} } Separator Example
The parsing of the graph might be like: Set current color to blue. Draw a cube using the actual color (i.e., blue). Push state (i.e., color and transformation matrix) onto the stack. Set color to red. Translate current position in x direction by one. Draw a sphere (in red). Pop stack. Translate in x direction by one. Draw sphere (in blue), with state saved on the stack.

Classes

The amount of classes which come with Inventor is rather large, so that we recommend use of an object-oriented development environment. Two families of classes are distinguished by their prefix. All classes for the scene graph starts with So (e.g., SoCube, for "Scene Object"). Basic classes start with Sb (e.g. SbColor). Fields have the prefix SoSF and are usually based on Basic types. SoMF stands for "multiple fields" which can contain a list of objects.

Hello World. - First example

Let's present the obligatory "Hello World!" example. Besides creating the scene graph with the text it is necessary to initialize a viewer.

Hello World in a Viewer
// Each class has its own include file #include <Inventor/Xt/SoXt.h> #include <Inventor/Xt/viewers/SoXtExaminerViewer.h> #include <Inventor/nodes/SoSeparator.h> #include <Inventor/nodes/SoText3.h> // View in 3D "Hello World" void main(int argc, char **argv) { Widget myWindow = SoXt::init(argv[0]); // Create window for viewer if(myWindow == NULL) exit(1); SoSeparator *root = new SoSeparator; // Create root node root->ref(); // reference root node so that the graph will not be deleted SoText3 *myText3 = new SoText3; // Create 3D Text myText3->string.setValue("Hello World."); root->addChild(myText3); // add 3D text node to the graph SoXtExaminerViewer *myViewer = new SoXtExaminerViewer(myWindow); myViewer->setSceneGraph(root); // pass graph to viewer myViewer->setTitle("Hello World! - an Inventor Example"); myViewer->show(); SoXt::show(myWindow); // show window of the viewer SoXt::mainLoop(); // Enter main event loop }
For compiling an Inventor program it is necessary to link the inventor libraries. Usually a makefile which you setup create initially will do the job. Please look at the Makefile for our Hello World example. Use the command smake instead of make to start the compilation (to use the SGI make); GNU make doesn't recognize the extensions of an SGI Makefile.

Literature

The book "The Inventor Mentor" gives a good start. It is online as an insight book on SGI machines. Also, several copies are available in the main library and the library lounges. All source code examples are available on workstation with complete Open Inventor distribution in /usr/share/src/Inventor/examples/Mentor/C++ and /usr/share/src/Inventor/examples/Toolmaker. In this workshop, we try not to write another "Mentor", but emphasize parts which allow an introduction within three hours. The amount of classes in Open Inventor is huge and sometimes you get lost even though you have some experience. As a compact guide through the Inventor nodes (objects) and their fields (attributes), you can use the Open Inventor Nodes Quick Reference. The section "Tips and Tricks" explains some tools and their setup.