Computer Graphics Workshop '96 Lecture Notes


Today's topics

As we saw in the second problem set, engines are objects which accept connections from fields as inputs, perform some calculation, and drive the results to their outputs, to which other fields can be connected. We will briefly discuss some more of the details concerning engines in case you would like to make use of them for your final projects; for a better treatment, please see the Inventor Mentor.

Field to field connections

We have seen, again in the second problem set, that fields can be directly connected to one another, as well as hooked up to engines. There are several different types of fields, and Inventor provides some built-in converters which allow fields of one type to be hooked up to fields of another type. The following conversions are supported (from the Inventor Mentor, p. 335-6):

  • Any field type to String
  • String to any field type
  • Between any two of Bool, Float, Long, Short, ULong, UShort
  • Between Color and Vec3f
  • Between Float and Time
  • Between Matrix and Rotation
  • Between Name and Enum
  • Between Rotation and Vec4f (quaternion)
  • From an MF field to its SF version, and from an SF field to its MF version

We have already used one of these conversions; recall that all the inputs and outputs to the Compose and Decompose engines in the second problem set were MF fields, but that we were hooking up single-value, or SF, fields to them.

Reference counting and engines

Engines are derived from SoBase, which means that every engine has an associated reference count. The mechanism for maintaining this reference count is different from that of nodes, however. Whenever an output of an engine is connected to a field, that engine's reference count is incremented; whenever this connection is broken, the engine's reference count is decremented. As with nodes, engines are deleted when their reference counts are decremented to zero. For safety, you should ref engines you want to keep around.

Engines and animation

There are three primary types of engines which can be used to perform animations; SoElapsedTime, SoOneShot, and SoTimeCounter. These engines can be combined with others to create complex functions which can control the animation of certain scene elements. The primary advantages of using engines instead of, for example, sensors are twofold:

  • Engines can be read from and written to .iv files along with the rest of the scene graph
  • Engines allow convenient abstraction of certain types of motions (like the rotating of blades on a helicopter)

Sensors allow more general functions to be performed than engines do, but engines have the advantage that they automatically update their values; this allows simple animation tasks to be delegated to engines while the rest of the application works on more complicated tasks. for more information on engines, see Chapter 13 of the Inventor Mentor, and see the examples from this chapter in /mit/thingworld/Ivy/Mentor/.


A camera is a special type of node which controls how the rendering of a scene graph appears in a window. The cameras in Inventor act in a similar fashion to real-world cameras; they have several parameters which can be adjusted to alter how the resulting picture appears. We will examine some of these parameters as well as the two types of cameras to understand how they can be used to our advantage in application design.

Types of cameras

There are two types of cameras available in Inventor: the perspective camera (SoPerspectiveCamera) and the orthographic camera (SoOrthographicCamera). When you view a scene in an examiner viewer, you can switch between the two types of cameras by clicking on the box-shaped icon near the bottom of the icon list.

A perspective camera views the scene in the same fashion as the human eye; that is, objects farther away from the camera appear smaller. This type of viewing style is known as a perspective projection. An orthographic camera has no perspective; it uses a parallel projection so that objects far away from the camera look the same size as those near the camera. Each type of camera has associated fields whose values can be changed to alter the parameters of the view. An orthographic camera has a field, height, which specifies the height of the view volume; this, combined with the aspect ratio of the camera, specifies how much of the scene fits within the camera view. A perspective camera has a heightAngle field which performs a similar function. Both types of cameras have several fields inherited from the parent class, SoCamera, such as the position, orientation, and aspectRatio of the camera.

Cameras and viewers

When you create an examiner viewer and set its scene graph, the first thing it does is check the scene graph to see whether it contains a camera. If it does, it uses that camera as the one which will render the scene; if not, it automatically adds one to the scene. All cameras only render objects which follow them in the scene graph; for this reason, the camera is usually the first node added to the scene graph. You can get the camera used by a viewer by using the getCamera method. This returns an SoCamera; you can use the isOfType method of the camera to check whether it is a perspective or orthographic camera:
(define viewer (new-SoXtExaminerViewer))

;;; ...Additional code for showing viewer,
;;;    and setting up scene graph...
;;; This is a simple example:
(define root (new-SoSeparator))
(-> root 'ref)
(define draw-style (new-SoDrawStyle))
(-> (-> draw-style 'style) 'setValue SoDrawStyle::LINES)
(-> root 'addChild draw-style)
(-> root 'addChild (new-SoCube))
(-> viewer 'setSceneGraph root)

;;; Extract the camera from the viewer.
(define camera (-> viewer 'getCamera))
(define other-camera '())
(if (= 1 (-> camera 'isOfType
    (set! other-camera (SoPerspectiveCamera-cast camera))
    (set! other-camera (SoOrthographicCamera-cast camera)))
We can also set the camera type of the viewer manually. Note, as described in the manual page, that the change does not take effect until the next time the viewer's scene graph is set:
(-> viewer 'setCameraType
(-> viewer 'setSceneGraph root)

Up until now, we have ignored the issue of how the scenes we view in the viewer are lit. Inventor provides several types of lights which are designed to emulate various types of real-world lights; however, when designing an interactive game, keep in mind that fewer and simpler lights in your scene will cause it to render faster.

Types of lights

There are three primary types of lights in Inventor; point lights (SoPointLight), spot lights (SoSpotLight), and directional lights (SoDirectionalLight). In all cases, the light itself is invisible; only its effects on other geometry in the scene are visible. A point light emits light in all directions from its center. A spot light has fields which control how quickly the intensity of the light falls off from the center (dropOffRate) and the angle from the ceter after which no light is visible (cutOffAngle). A directional light simulates a light source very far away and sends parallel light rays into the scene; all polygonal faces pointing in a given direction are illuminated uniformly over their surfaces.

Directional lights cause the fastest rendering of shapes, because they do not require shading over the surface of a polygon. Point lights are the next fastest, and spot lights are the slowest. You will probably find it best to use only directional lights, if needed, in your scenes.

Let's look at the difference between these three types of lights:

;;; Example of point, spot, and directional lights.

;;; Three viewers, one per light

(define v1 (new-SoXtExaminerViewer))
(-> v1 'show)
(-> v1 'setHeadlight 0)

(define v2 (new-SoXtExaminerViewer))
(-> v2 'show)
(-> v2 'setHeadlight 0)

(define v3 (new-SoXtExaminerViewer))
(-> v3 'show)
(-> v3 'setHeadlight 0)

;;; Three scenegraph roots, one per type of light.

(define point-root (new-SoSeparator))
(-> point-root 'ref)
(define spot-root (new-SoSeparator))
(-> spot-root 'ref)
(define dir-root (new-SoSeparator))
(-> dir-root 'ref)

;;; Group node for holding point light
;;; and associated transform.

(define point-light-group (new-SoTransformSeparator))
(-> point-root 'addChild point-light-group)
(define light-xform (new-SoTransform))
(-> (-> light-xform 'translation) 'setValue 0.5 -0.5 -0.5)
(-> point-light-group 'addChild light-xform)
(define light (new-SoPointLight))
(-> point-light-group 'addChild light)
(-> (-> light 'intensity) 'setValue 1.0)
(define sphere (new-SoSphere))
(-> point-light-group 'addChild sphere)
(-> (-> sphere 'radius) 'setValue 0.1)

;;; Group node for holding spot light
;;; and associated transform.

(define spot-light-group (new-SoTransformSeparator))
(-> spot-root 'addChild spot-light-group)
(define light-xform (new-SoTransform))
(-> (-> light-xform 'rotation) 'setValue
    (new-SbVec3f -0.356368511915207
		 -0.932199954986572) 1.46062397956848)
(-> (-> light-xform 'translation) 'setValue 1.6 0.0 2.0)
(-> spot-light-group 'addChild light-xform)
(define light (new-SoSpotLight))
(-> spot-light-group 'addChild light)
(-> (-> light 'intensity) 'setValue 1.0)
(-> (-> light 'dropOffRate) 'setValue 0.1)

;;; Group node for holding directional light
;;; and associated transform.

(define dir-light-group (new-SoTransformSeparator))
(-> dir-root 'addChild dir-light-group)
(define light-xform (new-SoTransform))
(-> (-> light-xform 'translation) 'setValue 0.5 -0.5 -0.5)
(-> dir-light-group 'addChild light-xform)
(define light (new-SoDirectionalLight))
(-> dir-light-group 'addChild light)
(-> (-> light 'intensity) 'setValue 1.0)
(-> (-> light 'direction) 'setValue -1 -1.3 -3.0)

;;; Group node for holding the three cubes.
;;; Shared among the three scene graphs.

(define cube-group (new-SoGroup))

;; Complexity node improves the shading of the cubes
;; at the expense of rendering speed.

(define complexity (new-SoComplexity))
(-> cube-group 'addChild complexity)
(-> (-> complexity 'value) 'setValue 0.7)

(define mat (new-SoMaterial))
(-> cube-group 'addChild mat)
(-> (-> mat 'diffuseColor) 'setValue 0.2 0.2 0.9)
(define xform0 (new-SoTransform))
(-> cube-group 'addChild xform0)
(-> (-> xform0 'rotation) 'setValue
    (new-SbVec3f 0.551838874816895
		 -0.213665723800659) 0.859030544757843)
(define cube1 (new-SoCube))
(-> cube-group 'addChild cube1)
(-> (-> cube1 'width) 'setValue 0.25)
(define xform1 (new-SoTransform))
(-> cube-group 'addChild xform1)
(-> (-> xform1 'translation) 'setValue 1.125 0 -1.125)
(define cube2 (new-SoCube))
(-> cube-group 'addChild cube2)
(-> (-> cube2 'depth) 'setValue 0.25)
(define xform2 (new-SoTransform))
(-> cube-group 'addChild xform2)
(-> (-> xform2 'translation) 'setValue 0 -1.125 1.125)
(define cube3 (new-SoCube))
(-> cube-group 'addChild cube3)
(-> (-> cube3 'height) 'setValue 0.25)

(-> point-root 'addChild cube-group)
(-> spot-root 'addChild cube-group)
(-> dir-root 'addChild cube-group)

(-> v1 'setSceneGraph point-root)
(-> v2 'setSceneGraph spot-root)
(-> v3 'setSceneGraph dir-root)
Lights and viewers

Another of the conveniences of the examiner viewer is that it provides a light to illuminate the scene; this light is a directional light fixed to the position and orientation of the camera, and is therefore called a headlight. The effects of adding additional lights to the scene can be diminished by the presence of the headlight. To manually turn off the headlight, you can use the setHeadlight method:
(-> viewer 'setHeadlight 0)  ;; turns off headlight
(-> viewer 'setHeadlight 1)  ;; turns on headlight
Next lecture

Next Monday Bruce Blumberg, a Ph.D student here at the Media Lab, will give a talk about the ALIVE system, of which he is the primary designer and implementor. ALIVE is a very complicated Inventor-based application, and is a good example of what Inventor can be used for aside from games. On Wednesday Sumit Basu, a Course VI M.Eng student working on his thesis at the Media Lab, will give a talk about his work on deforming and matching a generic model of the human head to video sequences of people. This is another situation where Inventor is the tool rather than the basis of the application; it is a completely different type of application than we have seen yet, and will prove to be a fascinating talk.

Back to the CGW '96 home page

$Id: index.html,v 1.4 1996/01/18 22:58:49 kbrussel Exp $