Chapter 2. An Inventor Sampler

Chapter Objectives

After reading this chapter, you'll be able to do the following:

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.

“Hello, Cone”

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.

A Red Cone

The first example program illustrates the basic steps in writing an Inventor program.

  1. Create a window where the scene will be rendered. This example uses SoXtRenderArea, the Inventor Xt window.

  2. Build the scene graph by creating property and shape nodes and combining them into groups.

Example 2-1 gives the code to create the cone shown in “A Red Cone”.

Example 2-1. Basic “Hello, Cone” Program


#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
}

Using Engines to Make the Cone Spin

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.

Example 2-2. “Hello, Cone” Using Engines


#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();
}

Adding a Trackball Manipulator

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.

Example 2-3. “Hello, Cone” with a Trackball Manipulator


#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();
}

Adding the Examiner Viewer

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.

Example 2-4. “Hello, Cone” Using the Examiner Viewer


#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();
}

Naming Conventions

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

Scene Basic Types

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:

SbBool 

Boolean value (TRUE or FALSE)

SbBoxnx 

2D or 3D box that has planes parallel to the major axes and is specified by two points on a diagonal (includes SbBox3f, SbBox2f, SbBox2s); n is the number of values in the type (2 or 3), and x is the value type (f for float, s for short)

SbColor 

RGB (red/green/blue) color value with conversion routines to other color spaces

SbCylinder 

cylinder

SbLine 

directed 3D line

SbMatrix 

4×4 matrix

SbName 

character string stored in a special table for fast and easy comparison, typically for identifiers

SbPList 

list of generic (void *) pointers

SbPlane 

oriented 3D plane

SbRotation 

representation of a 3D rotation about an arbitrary axis

SbSphere 

sphere

SbString 

“smart” character strings that have many convenience methods for easy string manipulation

SbTime 

representation of time—in seconds; seconds and microseconds; or using the timeval structure

SbVecnx 

2D or 3D vector, used to represent points or directions (includes SbVec2f, SbVec3f, SbVec2s); n is the number of values in the type (2, 3, or 4), and x is the value type (f for float; s for short)

SbViewportRegion 


active viewport region within a display window

SbViewVolume 


view volume (for example, see SoCamera's getViewVolume() method in the Open Inventor C++ Reference Manual)

Methods

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.

Types versus Fields

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

Coordinate Systems in Inventor

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.

Include Files

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.