Next Titel Inhalt Vorwort 1 2 3 4 5 6 7 8 9 10 11 12 Appendix @ CAAD Teachers

Kapitel 10

Inventor II - Programming in C++, Structure of a Program and Nodes


lecture

10.1 An Inventor C++ Program

10.1.1 Structure and Components

A program always describes a scene and then specifies which viewer should be used for displaying the scene. This is true for Inventor and many other graphics programs.

To build the Scenegraph, it has to be specified which node is a child of which other node. This has to happen in the right order, so that material and transformations are described before the shape is drawn.

As we have learned in the previous lecture, there needs to be a function called main, which contains the commands to initialise and build the scene. It is also necessary to reference the root node. With the main and ref function the program structure will look like this:

In order to understand how to treat the Inventor objects and functions a number of files, so called header files, have to be included. This can also be necessary for objects and functions defined in other files, which will be linked with this one when compiling.

It is possible that the same sequence of commands would have to be written several times with different parameters. In this case it might be a good idea to define a new function for the execution of those commands. Functions with mnemonic names can make the code easier to read.

10.1.2 Getting started

These are only the basics, but to understand them means to be in a good position to understand the code of an Inventor C++ program. As you will see, there are many right ways to write the same thing, which is nice because everybody can chose the approach he/she feels the most comfortable with. On the other hand it makes learning difficult, because there are a lot of options to chose from instead of a straight way to go. We propose that you should start with a working program and modifiy it until it does what you intended it to do. This is a valid approach to learn programming, specially for tools, like Inventor, that can do very complicated things. It is allowed to copy code, learn from reading it and then use the code as a basic for your program. But, if you use code from another person, always keep a reference to the original in your file. And, if there is any copyright note in some code do not copy it unless you have the permission to do so.

10.2 Nodes I

5 important nodes are introduced so that you can get started with modelling 3D scenes:

10.2.1 SoSeparator

In the Scenegraph the Separator node is used to isolate effects of nodes in a group. All nodes of the group have to be made its children. You do not have to set any of the variables of a Separator.
	SoSeparator *root = new SoSeparator; 

10.2.2 SoCube and SoSphere

Cubes and Spheres are specialised shape object. The important variables to be set are width, height and depth for the cube. The default value for those dimensions is 2.0.
	SoCube *mycube = new SoCube;
	mycube->width = 1.5;
	mycube->height = 2.7;
	mycube->depth = 2.1;
And for the Sphere the radius can be specified, default = 1.0.
	SoSphere *mysphere = new SoSphere;
	mysphere->radius = 0.9;

10.2.3 SoMaterial

Material at first will be interesting to set the color of the following shapes. For the beginning lets look at the diffuseColor. The default value for the diffuse rgb-color is [0.8 0.8 0.8], the first parameter is for the amount of red, the second for green, the third for blue. Values range from 0 to 1, white is [1 1 1], black is [0 0 0], a not too saturated red is [0.8 0 0].
SoMaterial *myblue = new SoMaterial;
myblue->diffuseColor.setValue(0.0, 0.05, 0.9);
The Material node has fields for other kinds of color, shininess and transparency, everything you want to specify for solid colored materials. You can look up the other fields of SoMaterial in the quick reference.

10.2.5 SoTransform

The Transformation node can specify and combine the translation, rotation and scaling of the following shapes. The default values are set so that no transformation will happen. A translation is defined by three values for X, Y, and Z. The orientation of the coordinate system by default is so that Y points upwards.
	SoTransform *mytrans = new SoTransform;
	mytrans->translation.setValue(1.2, 0, 2.8);

The rotation is defined by a vector which defines the rotation axis and a value for the angle in radius. The following defined a quarter turn around the Y-axis:
	mytrans->rotation.setValue(SbVec3f(0 1 0), 1.57);

10.3 SoShapeKits

Shapekits can be used for any Inventor shape node. With a Shapekit you do not have to create and arrange each node individually. The following example produces the blue cube from example.iv of the previous exercise.
	SoShapeKit *mykit = new SoShapeKit;
	mykit->setPart("shape", new SoCube);
	mykit->set("shape { width  2  height 2  depth  2 }");
	mykit->set("material {diffuseColor 0.0 0.0 1.0}");
	mykit->set("transform {translation 2.5 0.0 0.0}");
In the set() function the form of the string between " and " is actually like the iv-format. But, because it is a string, it is not possible to use variables inside of it.

10.4 Viewers

Viewers allow you to look at the objects of a scene and move around. There are 4 types of viewers: the ExaminerViewer, the WalkViewer, the FlyViewer, and the PlaneViewer. Important functions are common to all viewers, the difference is mostly in the tools for navigation. They all have a "?" button to display the necessary information on how to use them. In the following specifics of navigation of two important viewers are explained. For navigating you have to select the arrow cursor from the buttons on the right.

10.4.1 ExaminerViewer

The examiner viewer treats the scene like an object. It lets you rotate the whole scene, so that you can look at it from all sides. It is also possible to use the zoom to get a closer look at the object.

10.4.2 WalkViewer

The walk viewer lets you move around in the scene. It feels like driving around with a car. This is nice for architectural scenes, but one has to get used to it. Using the zoom can distort the scene.

This is how a walk viewer is coded into main, (for the ExaminerViewer replace SoXtWalkViewer with SoXtExaminerViewer):

	void main(int , char **argv)
	{
		Widget myWindow = SoXt::init(argv[0]);
		SoSeparator *root = new SoSeparator; 
		root->ref();
		...
		...
		SoXtWalkViewer *myViewer = new SoXtWalkViewer(myWindow);
		myViewer->setSceneGraph(root); 				    
		myViewer->setTitle("MY WALK VIEWER");
		myViewer->show();
		   
		SoXt::show(myWindow);
		SoXt::mainLoop();
	}
	

10.5 Types, Functions, Conditions, Header Files

10.5.1 Important Types

intinteger number, often used for counting.
float
floating number, you can use float types for all coordinates and dimensions in Inventor.
char
the character type is used for strings, which are defined as an array of characters or a pointer to a char, like:
		char *word = "theword";
enum
An enumeration declares a set of constant integer variables, the following command sets HORIZONTAL = 0, PERPENDIC = 1, and VERTICAL = 2. Orientation is a new type and can be used to declare a variable.
		enum orientation {HORIZONTAL, PERPENDIC, VERTICAL};
		orientation myorient = HORIZONTAL;
SbVec3f
This is a 3D vector class used to represent points or directions. It has some useful functions associated with which you might get to now later, for now you will use it to define the axis of a rotation.

10.5.2 Important Functions

You will get to know many functions, two are important for building the Scenegraph. They are always used in combination with an object:
addChild
to add the first child to a node or additional children the to the end of the list of children.
		root->addChild(mytrans);
		root->addChild(mymaterial);
		root->addChild(mycube);
insertChild
is used to add a child at a specific position, the first position is 0. This is useful to add transformations or materials before a shape.
		root->addChild(mycube);
		root->insertChild(mytrans, 0);

10.5.3 Important Conditions

if
The if-statement tests a particular condition, if that condition is true an action or set of actions is executed. Form:
		if (expression) {
				statement 1;
				statement 2;
				...
		}
switch-case
to choose among different choices. Switch specifies which variable of type int should be compared, case gives a value and a set of statements ended by break:
		switch(a)
				{
				case 1:
					statement 1.1;
					statement 1.2;
					...
					break;
				case 2:
					statement 2.1;
					statement 2.2;
					...
					break;
				case 3:
					statement 3.1;
					statement 3.2;
					...
					break;
				...
				}
for
can be used to step through a set of statements until a condition becomes false, usually a counter variable of type int is modified until it reaches a limit, i++ is a way to increase i by 1 every time the loop is executed:
		for (int i = 0; i<7 ; i++) {
					statement 1;
					statement 1;
					...
		}

10.5.4 Defining a New Function

To define a new function it is important to know whether it should return a value. In that case a return type has to selected. For your first applications it will be fine to have void functions, this means functions that do not return anything, only execute a number of statements.

The second thing to specify are the arguments and their types, because for the C++ compiler these things have to be known.

The following function will draw a number (num) of cubes each one at a certain distance (dist) from the previous:

	void makecubes(SoSeparator *root, int num, float dist)
	{
		SoTransform *atrans = new SoTransform;
		atrans->translation.setValue(dist, 0.0, 0.0);
		for (int i = 0; i < num ; i++) {
			SoCube *acube = new SoCube;
			root->addChild(atrans);
			root->addChild(acube);
		}
	}
In main you can call the function with: makecubes(root, 5, 3.2);

10.5.5 Including Header Files

At the very beginning of your C++ file you have to list all header files that need to be included.

Including a header file is written like this:

	#include <Inventor/nodes/SoCube.h>
or like this if the include file is in the same directory as your program:
	#include "student.h"
Every viewer, node, field, or kit, that you refer to in your code needs to be declared in a header file. The man-pages can help to find out which header files you have to include.

10.6 Exercise 10 - Modify a Sculpture

The goal is to get used to the commands of a C-based language and to learn to program 3D environments with Inventor. The task is to modify the program that generates a model of Max Bill's Sculpture at the Bahnhofstrasse in Zurich and lets you walk through it. These are the steps for proceeding with this exercise: The online book 'The Inventor Mentor' and the hardcopy version of it are good places to look for explanations and samples of code.

If you think you understand every line of code of the program, which means that you can modify it and know what is going to change in the model, you have completed this exercise and are ready for next weeks exercise.

Hand in:

For a proof of your understanding please hand in a modified c++-program of the Bill Sculpture to '~prog/abgabe/exercise10/yourname10.c++'.

Next Titel Inhalt Vorwort 1 2 3 4 5 6 7 8 9 10 11 12 Appendix @ CAAD Teachers

This website has been archived and is no longer maintained.