Computer Graphics Workshop '97 Lecture Notes

1/6/97

Today's topics
Administrivia

The Computer Graphics Workshop will be taught Mondays, Wednesdays, and Fridays during IAP, except for the holiday of 1/20. That week the class will meet on Tuesday.

We will occasionally have laboratory sessions to help clarify the material and to assist with problem sets. These sessions will meet in the SGI cluster in 4-035. Dates and times of the labs will be announced in class.

Purpose of the course

The early weeks of the course will be devoted primarily to learning how to write programs using Open Inventor. Early on, we will have frequent problem sets which will assist you in becoming familiar with the capabilities of the toolkit. Because we believe that you learn best by actually implementing something, we strongly recommend that you form groups for, and participate in, the creation of a final project.

The final project

This year the final project will be to implement a simple game using Open Inventor. The feasibility of this project has been demonstrated; however, it will almost definitely not be possible to implement Doom or Quake. We have a suggested list of games which should be implementable within the IAP timeframe: We suggest you begin thinking about which game you would like to help write and who you would like to work with. We hope to present all the material necessary for the construction of this game within the first two weeks, so that you have plenty of time to work your project.

The development environment

The development environment we will use on Athena is a version of Scheme (SCM) which has an Open Inventor binding. This allows you to write Scheme programs which use the Open Inventor 3D graphics toolkit.

Note that currently Open Inventor is only available on Athena SGIs. Therefore, you will have to find an Indy in order to be able to work with Inventor.

To get started, add the following line to the end of your ~/.environment file:

add iap-cgw   # Current location of IvySCM
Add the following lines to the end of your ~/.cshrc.mine file:
if ($hosttype == sgi) then
  limit coredumpsize 0    # Don't let anything dump core
  setenv SCHEME_INIT_PATH /afs/athena.mit.edu/course/other/iap-cgw/lib/scm/
  setenv SCHEME_LIBRARY_PATH /afs/athena.mit.edu/course/other/iap-cgw/lib/slib/
  setenv LD_LIBRARY_PATH /afs/athena.mit.edu/course/other/iap-cgw/lib
endif
Note: you will need to log out and log back in for the above changes to take effect.

Although you can run the class's Scheme interpreter, ivyscm, directly from an Athena prompt, we strongly recommend you run it from within emacs. To set up ivyscm within emacs, add the following lines to the end of your ~/.emacs file (or create one if you don't have one):

(setq load-path (cons "/afs/athena.mit.edu/course/other/iap-cgw/elisp" load-path)) ; Use scheme-mode for files with .scm suffix (setq auto-mode-alist (append '(("\\.scm$" . scheme-mode) ) auto-mode-alist)) ; Autoload run-scheme from file cmuscheme.el (setq scheme-mode-hook '((lambda () (autoload 'run-scheme "cmuscheme" "Run an inferior Scheme" t)))) (autoload 'run-scheme "cmuscheme" "Run an inferior Scheme process." t) (setq scheme-program-name "ivyscm")
Now typing M-x run-scheme from within emacs will bring up a buffer in which ivyscm is running. After several seconds, the Scheme system will print a banner message, and then bring up a prompt:
> (display "Hello, world\n")
Hello, world
>
While you can work by typing directly into the interpreter's buffer, it is much more convenient to work in a separate buffer. If you save your current buffer with the suffix .scm, you can evaluate the current Scheme expression (the one which the cursor is on) by typing C-c C-e. You can load in an entire Scheme file into the interpreter by typing C-c C-l and specifying the file name. You can get help by typing M-x describe-mode inside the Scheme window or a scheme-mode buffer. The most useful commands are as follows:

Inside the *scheme* buffer:

key binding --- ------- C-c C-l scheme-load-file C-c C-c comint-interrupt-subjob
(C-c C-c interrupts what the Scheme interpreter is doing. If it was in the middle of reading input or performing a computation, it will print "ERROR: user interrupt" and go back to the idle state. However, if you interrupt the interpreter while it is idle, the interpreter will quit, the emacs interface will display "Process scheme interrupt", and you will have to type M-x run-scheme again to restart Scheme.)

Inside a scheme-mode buffer (i.e, filename ending in .scm):

key binding --- ------- C-c C-l scheme-load-file C-c C-r scheme-send-region C-c C-e scheme-send-definition C-c C-z switch-to-scheme
Warning: Do not try to use the scheme-compile-definition or scheme-compile-file commands to evaluate Scheme expressions or load Scheme files. All of the commands you need are listed above. Experimentation is not recommended.

Example code, as well as documentation, resides in /mit/iap-cgw (after you type "add iap-cgw"); see especially /mit/iap-cgw/src. Most of the examples from the Inventor Mentor have been converted to Scheme and are located in the Mentor subdirectory. Several convenience functions for this course are given in /mit/iap-cgw/lib/scm/CGWInit.scm; we will describe (and likely add to) them as the course proceeds.

To exit Scheme, you can exit emacs or kill the Scheme buffer. If you're running ivyscm on the command line, type (exit).

Paradigms of Open Inventor

Open Inventor is a high-level toolkit, unlike many existing 2D and 3D graphics libraries. The data structures and flow of control in programs will seem very abstract at first, but as you gain experience with the toolkit you will understand more about how and why things happen.

Open Inventor is an object-oriented 3D graphics toolkit. Each "object" on the screen is represented as an "object" in memory (in the 6.001 sense of the word -- remember the "object-oriented" adventure game?). Each object is stored in the scene database, SoDB, which stores such information as the name of each part in the current scene.

The fundamental data structure in Open Inventor is called the scene graph. A scene graph is a directed acyclic graph; you can think of it, for the most part, as a tree. Most of the operations in Open Inventor involve applying actions to these scene graphs. Actions traverse this tree from left to right, and from the top down.

For example, when an application renders a scene, it does so by applying a render action to the scene graph. When a program wants to find a certain node in the scene graph, it does so by applying a search action to the scene graph.

The scene graph paradigm has been shown to be a successful one, and has been adopted in many current and forthcoming 3D graphics standards. Familiarity with Open Inventor will allow you to more easily learn similar toolkits and prepare you for the next generation of 3D programming environments.

Creation of a simple scene graph

As a first example, we will create a viewer (a window for viewing Open Inventor scenes) and add some objects to the scene. The first problem set will involve creating a simple scene graph like this one and modifying some of its parameters.

The scene graph we will create will look like this:

                                    SoSeparator
                                         |
       -------------------------------------------------------------------
       |         |         |           |          |           |          |
  SoMaterial  SoCone  SoTransform  SoSphere  SoMaterial  SoTransform  SoCube
First, let's start up the Scheme interpreter, and create and show our window:
(define my-viewer (new-SoXtExaminerViewer))
(-> my-viewer 'show)
Now let's create the root node of our scene graph.
(define root (new-SoSeparator))
(-> root 'ref)
Note that we increment the reference count of the root node. We will discuss the reasons for this as we proceed through the course; for now, just remember to always ref your root node.

Now let's add a material node, which allows us to change the material properties of objects which follow it in the scene graph:

(define my-mat (new-SoMaterial))
(-> root 'addChild my-mat)
And a shape node (in our example, a cone):
(define my-cone (new-SoCone))
(-> root 'addChild my-cone)
Nothing has yet appeared in our window. In order to view our scene, we must tell the viewer which scene graph to render.
(-> my-viewer 'setSceneGraph root)
Voila! A cone appears. Note that you can translate (middle mouse button), spin (left mouse button), and scale (left and middle mouse buttons) the cone. This is standard functionality that Open Inventor provides for viewing scenes.

Now let's try changing the color of our cone to be red.

(-> (-> my-mat 'diffuseColor) 'setValue 0.9 0.0 0.0)
The values in the above expression indicate red, green, and blue values, from left to right, and they range from values of 0.0 to 1.0. They are additive, so that high values for red and green make yellow.

We will next add a transform node to the scene graph, in preparation for placing a sphere next to the cone.

(define my-transform (new-SoTransform))
(-> root 'addChild my-transform)
We will now add a sphere to our scene graph.
(define my-sphere (new-SoSphere))
(-> root 'addChild my-sphere)
Hmm. The sphere appears in the same place as our cone. Since we want to have the sphere next to the cone, we must change its translation:
(-> (-> my-transform 'translation) 'setValue 2.0 0.0 0.0)
Note that the sphere is the same color as the cone. It inherits the material properties defined by the material node we added before it.

Finally, let's add a blue cube to our scene. This second material node will override the presence of the first one for all objects which follow it in the scene graph.

(define my-mat-2 (new-SoMaterial))
(-> root 'addChild my-mat-2)
(-> (-> my-mat-2 'diffuseColor) 'setValue 0.0 0.0 0.9)
(define my-transform-2 (new-SoTransform))
(-> root 'addChild my-transform-2)
(define my-cube (new-SoCube))
(-> root 'addChild my-cube)
Note that the cube appears this time in the place where the sphere is, not where the cone is. Therefore we want to move the cube relative to the center of the sphere:
(-> (-> my-transform-2 'translation) 'setValue 2.1 0.0 0.0)
The default orientation of the coordinate axes in Inventor (before any interaction with the viewer is done) is positive x to the right, positive y up, and positive z out of the screen. This is a right-handed coordinate system.

Using just these basic tools, you should now be able to approach the first problem set , which is to design a simple scene composed of these objects.

Next lecture

Next time we will introduce more of the tools for manipulating scene graphs, explain the workings of nodes and fields, and show how to understand the manual pages from the perspective of Scheme programming.


Back to the CGW '97 home page

$Id: index.html,v 1.21 1997/01/06 18:29:59 kbrussel Exp $