Studierstube scripting mentor

File Format

Studierstube uses the Open Inventor file format for the input files that define an application's content and behavior. OIV files follow a structured ASCII-based syntax, allowing the author to define an application's scene graph. Inventor files generally have the extension .iv .

File Header

All Inventor files are required to have the same first line

#Inventor V2.0 ascii

that identifies them as containing data in the Open Inventor file format.

Comments and blank lines

Extra whitespace characters like blanks, tabs or newlines are ignored. It is possible and very advisable to use plenty of whitespace and comments to structure your IV-files, improving their readability for humans, and making it easier to find parts of your scene.

Comments start with the # character. All content after that character until the end of the line is ignored by the parser (except for the very first line in the file stating the file format and version).

Defining Nodes & Fields

A node is represented in the file by its class name (for built-in OIV nodes, the So prefix of the class name can be omitted), an opening brace ({), the fields of the node and their values (if any), and a closing brace (}). For example:

Cube {
    width  0.1
    depth  0.1
    height 0.1
}

Defines a cube that measures 10 cm in each dimension.

The individual values of a vector-type field (Vec3f, Rotation,...) are seperated by whitespace, multiple values of a MF-field are enclosed in square brackets ([ ]) and seperated by commas. Strings must be enclosed in quotation marks if they contain a whitespace character. Examples:

Transform {
    translation 0 0 1                   # Single Vector value (0,0,1)
}


Material {
    diffuseColor [1 0 0, 0 1 0, 0 0 1]  # 3 Color values: red, green and blue
}


Text3 {
    string "This is a String."          # Single String value
}

Note that all fields that are not specified explicitly are always set to their default value. This means that all fields of a node will always be used, even if not listed in the input file. If you want to use just a subset of a node's fields, and suppress the influence of other fields, you can set the ingore flag by appending a tilde (~) character. To change only the transparency, but not the base color and other properties of the current material, you would use for example:

Material {
    transparency  0.5 # Make all subsequent geometry semi-transparent
    diffuseColor  ~   # ignore these fields
    specularColor ~
    ambientColor  ~
    emissiveColor ~
    shininess     ~
}

Group Nodes

Group nodes are nodes that can contain other nodes, called children. A group node is defined by specifying the node type, an open brace, the node's fields (if any), the node's children, and a closing brace. This results in a nested syntax for trees of nodes:

Group {            # Group node (no fields)
    Group {        # 1st child
        Cube {}
        Sphere {}
    }
    Group {        # 2nd child
        Sphere {}
        Cube {}
    }
}

Group nodes are useful for creating sub-scenegraphs that can be referenced and re-used in other locations, and for controlling traversal (e.g. rendering) behaviour. The basic group node is called Group, and has no side effects besides grouping its children together. The different other group nodes and their effects on traversal are explained in section 2.

Node Kits

Node Kits are nodes that encapsulate a scene graph, acting as a template for possibly complex arrangements of nodes that can be reused easily. Node kits can only be implemented in C++ (see section "Extending Open Inventor"), and from a scripting perspective they look like nodes with SFNode fields. Internally, these special fields, called parts, are leaf nodes of the encapsulated scenegraph. The main difference between a part and a SFNode field is that parts are part of the scene graph structure and will be traversed, whereas SFNode fields are just fields of a node and will not be traversed by any action (including rendering).

In the file format, node kits are written like normal nodes, and parts are written like SFNode fields - the part name followed by the node definition. For example:

ShapeKit {
    transform Translation { translation 0 1 0 }
    shape Sphere {}
    # both parts are part of the scenegraph and will be traversed.
    # This will render a Sphere at position 0 1 0
}

While the node kits built into Open Inventor are rarely used, a lot of Studierstube classes are node kits. In the documentation, this will be indicated by putting the type of the part in brackets.

Naming & referencing nodes and fields

A single node can be used multiple times in the scene graph - this is very useful if the same objects should be rendered multiple times in different locations, or you want to reuse other things like textures or transformations without having to redefine them. This does not only save typing work and makes your code more readable, but it also saves memory - the node is only stored once and just referenced from other parent nodes. An natural consequence of this is that any change done to the node will affect all its occurences in the scene graph.

To make a node referencable, the node has to be given a unique name. The name is assigned to the node by putting the DEF keyword, followed by chosen name, in front of the definition of the node. Names must start with an uppercase or lowercase letter or an underscore, followed by digits (0..9), uppercase or lowercase letters and underscores. For example

DEF _MyCube1 Cube {                        # define a cube named _MyCube1
    width 0.1 
    depth 0.1 
    height 0.1
}

Defines a cube and assigns it the valid name _MyCube1.

To reference an already existing node in the scenegraph, you use the USE keyword, followed by the name:

DEF _MyCube1 Cube {                        # define a cube named _MyCube1
    width 0.1 
    depth 0.1 
    height 0.1
}
 
DEF mat1 Material { diffuseColor 1 0 0 }  # define the Material mat1
Transform { translation 0.5 0 0 }         # translate position
 
USE _MyCube1                              # reference the Cube defined above

Will render the cube a second time, in a different color and at a different location.

Similar to whole nodes, also single fields can be referenced in other nodes. This creates a field connection between the referenced field and the target field, updating the target field whenever the referenced field changes. Field references are composed of the DEF name of the containing node, a dot and the name of the field to be referenced. References are assigned to a field by using the = sign, after a possible default value, followed by the USE keyworkd and the field reference. For example:

DEF trans1 Transform {
    translation 0 0 1 
}
Cube {}
DEF trans2 Transform {
    translation 0 0 0 = USE trans1.translation # trans1's translation value is connected here
}
Sphere {}

In this example, it is sufficient to change trans1.translation to update both translation values.

Note that field connections introduce a second graph-structure, which is orthogonal to the scene graph, into your application: the dependency graph. The dependency graph models the dependency of fields from other fields in the scene graph. If a field changes, the dependency graph forwards the field change to all connected fields, which are also updated.