Ygdrasil Getting Started Guide (rough draft)

See the XP 1.0 notes for additional, partially correct information.

The 0.1.5 release of Ygdrasil can be found at EVL in ~pape/yg0.1.5.tgz, or in this tar file: yg0.1.5.tgz The contents are as follows:

First important note - Ygdrasil uses the 0.4 version of the Bergen sound system (which is also under development). If you have any sounds in a scene, you must run snerd0.4; with an earlier version of snerd, yg will just hang forever waiting for the server to respond to its query of the duration of a sound file.

Converting an XP scene - the program xptrans will translate an XP scene file into an Ygdrasil scene file (or at least try to). It handles the basic syntax, comments, and most of the basic, known nodes and messages. Messages to the special XP nodes (%user, %navigator, etc) are not currently handled; options for custom nodes may need to be corrected. There is no translator for C++ node classes, as the changes at that level are more involved (although the translation job is usually not very difficult for a human).
Probably the one significant piece of XP that does not exist yet in Ygdrasil is the Grabber node.

A Basic Ygdrasil Scene

The syntax for scene files is described in the XP 1.0 notes.

The main change is that Ygdrasil does in fact run input files through the C pre-processor; comments are delimited by // or /* */; #include, #if, and #define may be used just as in a C program. (It appears that, depending on your exact SGI development environment, C++-style comments might not be accepted. You can change the preprocessor that Ygdrasil uses via the environment variable YG_CPP_COMMAND; e.g. setenv YG_CPP_COMMAND "/usr/bin/cc -E")

In order to interact with a scene, you must include a User node, with appropriate navigator, head, and wand(s) under it. Without a User, you can see the scene, but not navigate or activate any triggers.

Some other significant changes:

Here is an example scene:

    User User0 ()
	    caveNavigator User0Nav (fly(off))
	    caveHead User0Head ()
	    caveTracker User0WandTracker (sensor(1))
		    caveWand User0Wand (when(button3, User0Nav.toggleFly))
	    keyboard User0KB (when(ckey, User0Nav.toggleCollide))
    light sun ()
    light sun2 (position(-.5 -1 1))
    object (file(ground.pfb), floor, position(0 0 -5))
    switch spinnerSwitch ()
	spinner (position(-5 2 7))
		object (file(banana.pfb))
    Environment space0 (volume(box -1000 -1000 -1000 1000 10 1000),
		    skyColor(.5 .7 1))
    Environment space1 (volume(box -1000 10 -1000 1000 1000 1000),
		    skyColor(0 0 0))
    WandTrigger trigger0 (volume(sphere 0 5 5  3), 
		    when (enter, print($user entered)),
		    when (button1, space0.skyColor(1 1 .2)),
		    when (button2, spinnerSwitch.toggle) )

See the Ygdrasil nodes quick-reference for a basic list of all the existing node classes and their messages and events.

C++ coding

The following is a skeleton of the C++ code for a basic Ygdrasil node class. The script makeNode will generate something like this.


#ifndef _simpleNode_h_
#define _simpleNode_h_

#include "ygNode.h"

class simpleNode : public ygNode
         simpleNode(const char* name,bool master=true);
         virtual void reset(void);
         virtual void message(const ygMessage&);
         virtual void app(void);



#include "simpleNode.h"

using namespace std;

extern "C" ygNode* construct_simpleNode(const char* name,bool master) { return new simpleNode(name,master); }

simpleNode::simpleNode(const char* name,bool master) : ygNode(name,master)

void simpleNode::reset(void)

void simpleNode::message(const ygMessage& msg)
        if (msg == "mymessage")
                /* mymessage(msg.floatArg(0)); */

void simpleNode::app(void)

All messages will be automatically parsed into ygMessage objects, which contain the message name and a vector of the arguments, all as ygStrings. For instance, position(1 0 2) becomes an ygMessage with the message name "position" and 3 arguments - "1", "0", "2". The == operator is overloaded for messages to compare message names with strings, as in the msg == "mymessage" above. There are also a number of convenience functions for converting message arguments into various types:

The Makefile in the module-src/ directory can be used to compile a node class into a DSO (e.g. "make simpleNode.so" for the above). The directory containing the DSO should be included in the YG_DSO_PATH environment variable, and then the Ygdrasil executable will automatically load it if it encounters the node type name in a scene file.


If your new class is derived from another node class that is not built-in (that is, from some other new class you've written), the DSO for the parent class must be loaded before the derived class's DSO. Otherwise, the derived class's DSO will have unresolved symbols, and it will fail to load. To tell Ygdrasil about other classes to load before a given class, list them in a ".ygdep" dependencies file. For example, if the class fancySpinner is derived from spinner, then in the same directory that contains fancySpinner.so there should be a text file named fancySpinner.ygdep, with a line that says

If there is more than one dependency, list each one on a separate line. You do not need to list any dependencies of the parent class - those will be found recursively as the parent class is loaded.


The built-in node classes automatically share their state when running networked. Remote users can join an existing world by simply connecting to the server, without needing the scene file for the world, just a scene describing the user.

This will be documented soon.

Environment Variables

The following environment variables are used to control the behavior of Ygdrasil:

Changes from 0.1.4 to 0.1.5

Changes from alpha1 to alpha2

Changes from alpha0 to alpha1

Last modified 20 September 2000.
Dave Pape, pape@evl.uic.edu