Chapter Objectives
After reading this chapter, you'll be able to do the following:
Explain the basic structure of an Inventor program
Describe the conventions used by Inventor
This chapter provides an overview of the 5 percent of Inventor that is part of any program. It includes a short program that draws a red cone in a window. This program is gradually augmented to show the use of some important Inventor objects: engines, manipulators, and components. Inventor naming conventions and basic data types are also described.
This chapter begins with a set of sample programs that illustrate the key aspects of Inventor. Example 2-1 creates a red cone and then renders it in a window (“A Red Cone”). This example uses an Inventor Xt window, which is part of the Inventor Component Library. This library provides utilities for window management and event processing and also contains a set of Inventor components (viewers and editors).
The code shown in Example 2-1 constructs a simple scene graph composed of a camera node, a light node, a material node, and a cone node. Later chapters go into specifics on creating nodes, setting values in fields, structuring the database, and applying actions. The purpose of this chapter is simply to convey a feel for the tools Inventor offers and to help you get started writing an Inventor program.
The first example program illustrates the basic steps in writing an Inventor program.
Example 2-1 gives the code to create the cone shown in “A Red Cone”.
#include <Inventor/Xt/SoXt.h> #include <Inventor/Xt/SoXtRenderArea.h> #include <Inventor/nodes/SoCone.h> #include <Inventor/nodes/SoDirectionalLight.h> #include <Inventor/nodes/SoMaterial.h> #include <Inventor/nodes/SoPerspectiveCamera.h> #include <Inventor/nodes/SoSeparator.h> main(int , char **argv) { // Initialize Inventor. This returns a main window to use. // If unsuccessful, exit. Widget myWindow = SoXt::init(argv[0]); // pass the app name if (myWindow == NULL) exit(1); // Make a scene containing a red cone SoSeparator *root = new SoSeparator; SoPerspectiveCamera *myCamera = new SoPerspectiveCamera; SoMaterial *myMaterial = new SoMaterial; root->ref(); root->addChild(myCamera); root->addChild(new SoDirectionalLight); myMaterial->diffuseColor.setValue(1.0, 0.0, 0.0); // Red root->addChild(myMaterial); root->addChild(new SoCone); // Create a renderArea in which to see our scene graph. // The render area will appear within the main window. SoXtRenderArea *myRenderArea = new SoXtRenderArea(myWindow); // Make myCamera see everything. myCamera->viewAll(root, myRenderArea->getViewportRegion()); // Put our scene in myRenderArea, change the title myRenderArea->setSceneGraph(root); myRenderArea->setTitle("Hello Cone"); myRenderArea->show(); SoXt::show(myWindow); // Display main window SoXt::mainLoop(); // Main Inventor event loop } |
Example 2-2 illustrates how to use engines to make the cone spin. An engine is attached to the angle field of an SoRotationXYZ node in the scene graph. The engine changes the angle value in the rotationXYZ node in response to changes in the real-time clock, which in turn causes the cone to rotate. After each change, the scene is automatically rendered again by the render area. Successive rotations give the desired effect of a spinning cone.
#include <Inventor/Xt/SoXt.h> #include <Inventor/Xt/SoXtRenderArea.h> #include <Inventor/engines/SoElapsedTime.h> #include <Inventor/nodes/SoCone.h> #include <Inventor/nodes/SoDirectionalLight.h> #include <Inventor/nodes/SoMaterial.h> #include <Inventor/nodes/SoPerspectiveCamera.h> #include <Inventor/nodes/SoRotationXYZ.h> #include <Inventor/nodes/SoSeparator.h> main(int , char **argv) { // Initialize Inventor and Xt Widget myWindow = SoXt::init(argv[0]); if (myWindow == NULL) exit(1); SoSeparator *root = new SoSeparator; root->ref(); SoPerspectiveCamera *myCamera = new SoPerspectiveCamera; root->addChild(myCamera); root->addChild(new SoDirectionalLight); // This transformation is modified to rotate the cone SoRotationXYZ *myRotXYZ = new SoRotationXYZ; root->addChild(myRotXYZ); SoMaterial *myMaterial = new SoMaterial; myMaterial->diffuseColor.setValue(1.0, 0.0, 0.0); // Red root->addChild(myMaterial); root->addChild(new SoCone); // An engine rotates the object. The output of myCounter // is the time in seconds since the program started. // Connect this output to the angle field of myRotXYZ myRotXYZ->axis = SoRotationXYZ::X; // rotate about X axis SoElapsedTime *myCounter = new SoElapsedTime; myRotXYZ->angle.connectFrom(&myCounter->timeOut); SoXtRenderArea *myRenderArea = new SoXtRenderArea(myWindow); myCamera->viewAll(root, myRenderArea->getViewportRegion()); myRenderArea->setSceneGraph(root); myRenderArea->setTitle("Engine Spin"); myRenderArea->show(); SoXt::show(myWindow); SoXt::mainLoop(); } |
The next two examples show additional methods for editing a node in the scene graph. Example 2-3 adds a manipulator (a trackball) to the first example (see “Cone with Trackball Manipulator”). The trackball itself appears as three rings around the cone. When the left mouse button is pressed on the trackball, it highlights itself in a different color to show it is active. While it is active, the mouse can be used to rotate the trackball and the object (here, the cone) inside it. In this example, a trackball is constructed instead of the SoRotationXYZ node in Example 2-2. Each time the user rotates the trackball, its values change and the cone rotates as well. Because the render area has a sensor attached to the scene graph, the scene is automatically rendered again after each edit, and the cone appears to move.
#include <Inventor/Xt/SoXt.h> #include <Inventor/Xt/SoXtRenderArea.h> #include <Inventor/manips/SoTrackballManip.h> #include <Inventor/nodes/SoCone.h> #include <Inventor/nodes/SoDirectionalLight.h> #include <Inventor/nodes/SoMaterial.h> #include <Inventor/nodes/SoPerspectiveCamera.h> #include <Inventor/nodes/SoSeparator.h> main(int , char **argv) { // Initialize Inventor and Xt Widget myWindow = SoXt::init(argv[0]); if (myWindow == NULL) exit(1); SoSeparator *root = new SoSeparator; root->ref(); SoPerspectiveCamera *myCamera = new SoPerspectiveCamera; root->addChild(myCamera); // child 0 root->addChild(new SoDirectionalLight); // child 1 root->addChild(new SoTrackballManip); // child 2 SoMaterial *myMaterial = new SoMaterial; myMaterial->diffuseColor.setValue(1.0, 0.0, 0.0); root->addChild(myMaterial); root->addChild(new SoCone); SoXtRenderArea *myRenderArea = new SoXtRenderArea(myWindow); myCamera->viewAll(root, myRenderArea->getViewportRegion()); myRenderArea->setSceneGraph(root); myRenderArea->setTitle("Trackball"); myRenderArea->show(); SoXt::show(myWindow); SoXt::mainLoop(); } |
Example 2-4 replaces the render area in the first example with the examiner viewer, a component. This viewer, shown in ,“Cone with Examiner Viewer” modifies the camera node, which lets you view the cone from different positions. It provides a user interface that allows use of the mouse to modify camera placement in the scene. (Note that this example looks similar to the trackball in Example 2-3. Here, however, the camera is moving, not the cone itself.) This program does not need to set up a camera and call viewAll() because the viewer does this automatically.
#include <Inventor/Xt/SoXt.h> #include <Inventor/Xt/viewers/SoXtExaminerViewer.h> #include <Inventor/nodes/SoCone.h> #include <Inventor/nodes/SoDirectionalLight.h> #include <Inventor/nodes/SoMaterial.h> #include <Inventor/nodes/SoPerspectiveCamera.h> #include <Inventor/nodes/SoSeparator.h> main(int , char **argv) { Widget myWindow = SoXt::init(argv[0]); if (myWindow == NULL) exit(1); SoSeparator *root = new SoSeparator; root->ref(); SoMaterial *myMaterial = new SoMaterial; myMaterial->diffuseColor.setValue(1.0, 0.0, 0.0); root->addChild(myMaterial); root->addChild(new SoCone); // Set up viewer: SoXtExaminerViewer *myViewer = new SoXtExaminerViewer(myWindow); myViewer->setSceneGraph(root); myViewer->setTitle("Examiner Viewer"); myViewer->show(); SoXt::show(myWindow); SoXt::mainLoop(); } |
Basic types in Inventor begin with the letters Sb (for scene basic; see the next section, “Scene Basic Types”). For example:
SbColor
SbViewVolume
All other classes in Inventor are prefixed with the letters So (for scene object). For example:
SoCone
SoPerspectiveCamera
SoMaterial
SoTransform
Methods and variables begin with a lowercase letter. Each word within a class, method, or variable name begins with an uppercase letter. For example:
getNormal()
setSceneGraph()
myCube
Enumerated type values are in UPPERCASE. For example:
FILLED
PER_PART
This section discusses Inventor's Sb classes, a set of basic types that are used in many Inventor objects. Inventor includes useful methods for converting between different types and performing specific 3D operations on them.
Inventor defines the following types:
Each Sb class has useful operators associated with it. For example, you can negate a variable of type SbVec3f, multiply it by a matrix, or normalize it to unit length. The following code creates a unit-length vector, based on the specified direction:
SbVec3f v(1.0, 2.0, 3.0); // declares and initializes the vector v.normalize(); // normalizes the vector to unit length |
Similarly, SbMatrix has useful methods including multVecMatrix(), which multiplies a row vector by the matrix and returns the result, and rotate(), which sets the matrix to rotate by a given amount. See the Open Inventor C++ Reference Manual for a complete description of the available methods for each Sb class.
Chapter 3, “Nodes and Groups,” contains a complete discussion of fields, which are the structures that store parameters for nodes. A field contains a value of a certain type. Fields are always contained within Inventor nodes. Many fields contain a corresponding Sb type. For example:
A field of type SoSFVec3f contains an SbVec3f
A field of type SoSFRotation contains an SbRotation
A field of type SoSFName contains an SbName
Inventor uses a right-handed coordinate system for 3D data, with +z coming out of the screen. All angles are specified in radians. Objects are described in their own local coordinate space, known as object coordinate space. After all transformations have been applied to the objects in the scene graph, they are said to be in world coordinate space. This world coordinate space includes the camera and lights.
Inventor contains include files for every class. You need to include the appropriate file for each class used in your program. For example, SoSphere and SoTransform nodes require you to include the files SoSphere.h and SoTransform.h.Most include files are found in a subdirectory—for example, nodes/SoSphere.h and sensors/SoNodeSensor.h.
In addition, you need to include the SoXt.h file if you are writing an interactive program that uses the Inventor Component Library.
If you are programming using the C application programming interface, use the Inventor_c directory instead of the Inventor directory.