Kapitel
11
Inventor
III - More C++
lecture
Light is important in architecture. An architect would like to design the light
situation as carefully as the solid parts of the building. To do this the
computer simulation can be of great help. In Inventor three kinds of lights are
available:
SoPointLight, SoDirectionalLight, and SoSpotLight.
from "Inventor Mentor" published by Addison Wesley
All lights are derived from SoLight and all have variables for:
- on: 1 = on, 0 = off.
- intensity: Brightness of the light, values range from 0.0 to 1.0, default is 1.0.
- color: Color of the light as an rgb value.
- location: a 3D point, default is (1.0 1.0 1.0).
- direction: a 3D vector, default is (0.0, 0.0, -1.0)
- location: a 3D point, default is (1.0 1.0 1.0).
- direction: a 3D vector, default is (0.0, 0.0, -1.0)
- dropOffRate: rate at which the light intensity decreases, 1.0 = immediate drop off, 0.0
= constant intensity, default is 0.0.
- cutOffAngle: Total angle of light, ousted of it the intensity is 0.0, values in radians
range from 0 to [[pi]], default is [[pi]]/4.
For a PointLight the C++ code
would look like this:
SoPointLight *mylight = new SoPointLight;
mylight->set("location 0 2.2 0");
root->addChild(mylight);
or
SoPointLight *light = new SoPointLight;
light->location.setValue( 0 2.2 0);
root->addChild(mylight);
Text can be used to display additional information in Scene. There are two
kinds of text available in Inventor: 2D-Text (Text2) and 3D-Text (Text3).
Before the text node a font node has to be placed in the Scenegraph.
- name: a font name, (in our environment 'ls /usr/lib/DPS/outline/base' can be
used to list the available fonts).
- size: size in points, default is 10.0.
- string: the text to display.
- spacing: between the lines of text, the default is 1.0.
- justification: alignment relative to the text origin, values are LEFT (default), RIGHT,
or CENTER.
- string: the text to display.
- spacing: between the lines of text, the default is 1.0.
- justification: alignment relative to the text origin, values are LEFT (default), RIGHT,
or CENTER.
- parts: visible parts of the 3D text, values are FRONT (default), SIDES, BACK,
ALL. Turning on all parts of Text can make your application very slow, because
three times more polygons have to be drawn.
The following is a code
example to produce 2D Text:
SoFont *myfont = new SoFont;
myfont->name.setValue("Helvetica-Bold");
myfont->size.setValue(32.0);
root->addChild(myfont);
SoText2 *mytext = new SoText2;
mytext->string.setValue("This is my text");
root->addChild(mytext);
Callback functions are a way to include new features to Inventor. A callback
function is a user written function, that gets called under certain conditions.
An important callback function is the SelectionCallback. It requires a
selection node to be placed in the right place in the Scenegraph and a function
which should be executed. A selection callback is always added to a
SoSelection node.
This are the pieces of code necessary for a selection callback:
void
mySelectionCB(void *, SoPath *selectionPath)
{
SoSelection *selected =
(SoSelection *)selectionPath->getHead();
... // add or modify children of selection
}
void
myDeSelectionCB(void *, SoPath *deselectionPath)
{
SoSelection *selected =
(SoSelection *)deselectionPath->getHead();
... // remove or reset children of selection
}
SoSelection *myselection = new SoSelection;
myselection->policy = SoSelection::SINGLE;
myselection->addSelectionCallback(mySelectionCB);
myselection->addDeselectionCallback(myDeSelectionCB);
root->addChild(myselection);
For
your exercises, a callback function has been prepared. In exercise 11 it will
execute a prepared callback function. In exercise 12 you will have to write the
code, which it should execute by yourself. You will not have to write and
insert the selection node.
Besides of their type variables can have a different scope (global, local), and
different kinds of storage (const, static).
Variables can be defined globally for one file. This is done by declaring them
outside of any functions at the beginning of the file after the include
statements. All the variables listed here, can be accessed and modified from
every function in the file. It is not a good programming style to use a lot of
global variables. It makes code hard to read and it is difficult to track the
value change of a global variable, when the program is not working properly. A
few globals are sometimes inevitable, but it is better to avoid them.
Local variables are the ones defined inside of a function. They are not
accessible by other functions. The same variable name can be used in different
functions without causing conflicts.
Usually variables are not kept in memory when a function has finished
execution, two exceptions are constant and static variables.
Constant variables never change there value. Therefore it is a good advice to
declare variables, which should never change as const. Because it cannot be
changed, a constant variable has to have a value assigned, when it gets
declared. For example: A constant variable can be used to remember the time,
when a function was called for the first time.
Static variables are permanently stored, when re-entering a function they still
have there previous value assigned. For example: Static variables can be used
to count how many times a function has been called. Static variables can be a
good substitute for global ones.
Defining a class is straight forward, it means to register every method
(=function) and field (= variable) of the class. The form is:
class newclass {
// methods
// fields
};
Methods are declared in the class definition by their return type and in
parenthesis the types of the arguments. The constructor method always has the
same name as class and must be defined.
class newclass {
// methods
newclass();
void writefun(int, char*);
// fields
};
the
methods then have to be programmed, the name is always composed from the class
name and the method name with two ':' in-between:
newclass::newclass()
{
// set values
// do something
...
}
void
newclass::writefun(int num, char *string)
{
// do something
// use the arguments
...
}
Field are variables of an object, they declared inside the class-definition in
the same way as variables are declared in functions. Fields are preceded by
their type and if they are pointers with an asterisk (*).
class newclass {
// methods
// fields
int mysize;
SoFont *myfont;
};
In
the functions of this class they can be used as if they were declared inside
the function.
newclass::newclass()
{
// set default values
mysize = 12;
myfont = new SoFont;
// do something
myfont->size.setValue(size);
...
}
Methods and fields can have different degrees of accessibility. Some fields
inside an object should not be modifiable directly, or some methods only
applied by the class itself. For example: A room class could have constraints
for the minimum size, therefore every time the size gets changed, the object
wants to check, if the new value is not too small. This can happen if the
change of size happens by using a method of the room class instead of changing
the value directly.
- public
- a public member is accessible from anywhere.
- private
- a private member can be accessed only be the functions of its class
- protected
- a protected member is like a public member to a subclass and like a private
member to the rest of the program.
The following example defines a class
for adding a string to a scene. The class has two methods, the creator:
mynote::mynote(), and mynote::moveCB():
#include <Inventor/nodes/SoSelection.h>
#include <Inventor/nodes/SoFont.h>
#include <Inventor/nodes/SoText3.h>
class mynote {
public:
mynote(char *, SoSeparator *);
protected:
static void moveCB(void *, SoPath *);
};
mynote::mynote(char *thenote, SoSeparator *root)
{
SoSelection *myself = new SoSelection;
myself->policy = SoSelection::SINGLE;
myself->addSelectionCallback(moveCB);
root->addChild(myself);
SoFont *myfont = new SoFont;
myfont->name.setValue("Helvetica-Bold");
myfont->size.setValue(32.0);
myself->addChild(myfont);
SoText3 *mytext = new SoText3;
mytext->string.setValue(thenote);
myself->addChild(mytext);
}
void
mynote::moveCB(void *, SoPath *selectionpath)
{
SoTransform *mytrans = new SoTransform;
mytrans->translation.setValue(2.0, 2.0, 0.0);
SoSelection *n = (SoSelection *) selectionpath->getHead();
n->insertChild(mytrans, 1);
}
main()
{
...
mynote *anote = new mynote("it's great", root);
...
}
The goal is to get used to the commands of a C++-based language and to gain
insight into object-oriented programming.
You are supposed to design an object (furniture, sculpture), which should be
inserted into a space together with the objects of other students. You will
have to write a function that can create your object and design an icon for the
button, that will invoke the creation of your object.
Start by compiling the unmodified files. Then run 'exercise11'. On the right
side you will discover the following new buttons:
- move mode
- rotate mode
- write iv-file
- insert Rietveld chair
- insert simple three legged chair
Inserting elements is easy. To move
or rotate them you first click on them with the left mouse button and when the
element is lifted use the middle button to do the transformation. Click with
the left button again to release the object.
Each object needs three different files:
- a "student_bitmap.h"-file which contains a bitmap that is going to appear
on the button in the viewer.
- a "student.h"-file that defines what kind of classes and member-functions
that you will use.
- a "student.c++"-file with the actual content of those member-functions.
To get an idea of how the three files work, take a look at the examples:
- three... an easy example.
- rietveld... a not difficult, but quite extensive example.
The template
program is split up into two parts: One that manages objects and one with the
objects themselves. You do not really have to understand the managing part in
order to write an object for it.
1. Startup Photoshop:
- press "new"
- set width and height to be measured in Pixels
- enter "24" for width and height, set mode to "Bitmap", press "OK".
- press "Ctrl" + "+" to enlarge the drawing area and use the drawing tools to
draw your button.
- then save your button as a "Compuserve GIF"-file, if that is not possible
as tiff-file.
- leave Photoshop
2. Startup xv:
- press right mousebutton, a menu will appear
- load your "gif"-file (ev. "tiff"-file), it will be in the
Adobe-Photoshop/Photoshop.MacFiles folder. Don't worry if it looks distorted,
- then press "save":
- from Format: choose the X11-Bitmap-format
- change the directory to your exercise directory
- select "Normal Size"
- name it student_bitmap.h
- and press "ok".
- choose "ok" again to overwrite the existing file
- quit xv
3. Open your new file in a text editor by double-clicking on it:
- delete "_bits", in the third row of the text.
- save it and close the editor.
4. Open exercise11.c++:
- find the function "MyViewer::studentPushCB()"
- delete "/*" and "*/" at the beginning and end of the function.
- save it!
5. If you want to add another one you have to understand the
exercise 11-program very well. Doing the same what you've just done, will only
replace your first button with a new one.
Open the file student.c++ with a text editor:
- The function "student::mySelCB" should not be touched, it tells Inventor
what to do if your object gets selected. The same with the lines marked with
"////", they are responsible for the insertion point of the object, you can
change that point but not the position of the node.
- the 'constructor' is the only function that gets called when a class is
instantiated as an object. This means that you have to start here with creating
new objects and calling other functions
- If you want to add your own functions, like for example:
- void myFunction(int i, SoSelection *top)
- open the "student.h"-file and add the following in the "class student"
- under:
private:
void myFunction(int, SoSelection *);
- in "student.c++" you can then add:
void student::myFunction(int i, SoSelection *top)
{ YOUR COMMANDS }
Please hand in three files, you can use the following commands:
cp student_bitmap.h ~prog/abgabe/exercise11/yourname_bitmap.h
cp student.h ~prog/abgabe/exercise11/yourname.h
cp student.c++ ~prog/abgabe/exercise11/yourname.c++
This website has been archived and is no longer maintained.