Who Am I?

Toney, Alabama, United States
Software Engineer, Systems Analyst, XML/X3D/VRML97 Designer, Consultant, Musician, Composer, Writer

Sunday, March 11, 2007

From Here to There and Back Again, Mr. Proto

Whimsically, Bilbo Baggins wrote a tale of his time away from the shire for most of his life in the shire, but finished it in Rivendale and showed it to Frodo before the younger began his journey to return the ring to fires. Sometimes one has to travel a long ways to finish a story.

Many a tale is told as a road trip, a journey, a walk from here to there where all of the adventures depend on the twists in the trail, the companions and adversaries, and how well one fares with each. This same model of events and situations, call and response, request and acknowledgement is found in all forms of communication and art.

A prosaic term for this used in music is sequencing. Some sequences are like the trip we take to the local grocer or the song we sing in church. There is a plan of stops or notes and if all goes according to plan, the events are predictable. If there are surprises along the way, we make decisions about the next stop or next note. Most of us like trips that aren’t the same every time we travel a road. The same is true of many stories and some adventures in life. Some journeys go straight to their destination, and some journeys and most stories take side trips.

I am not going to philosophize about that. I am going to show you how to author that in 3D using sequencing techniques. In this tutorial, I am going to show you how to set up animation and sound sequences in VRML/X3D that may be planned and provide choices. This tutorial has three parts:

Part 1: The Basic VRML Nodes Used To Create Sequences

Part 2: Rolling on the River and

Part 3: Walking Kamala

The Basics of Ring Givers and Ring Bearers


First, we will learn about basic VRML/X3D animation sequencing and how this is created by sending and receiving events.

In Western tradition of marriage, bride and groom give and receive rings. There are two important concepts:

  • Rings are exchanged.

  • Rings are expected.

    In animation, instead of rings, events are exchanged. Instead of placing a ring on a finger, events are sent by event outs, and received by events in. As with the ring, event ins and event outs have to match by type or just event types. If a ring is given, a ring is expected. If an event is given, an event of the same type is expected.

    Events


    Event types are also called 'data types'. Data types will be numbers and characters of special forms. We have to live with a bit of geekSpeak here. Some examples of event types are:

  • SFInt32: A single field integer. Or simply, 0, 1, 2, 3 and so on with no fractions allowed and no multiple integers such as (0 1 2).

  • SFFloat: A single field floating point number. This allows fractions but only one and conventionally, between 0 and 1, so 0.23, or even just .23.

  • MFFloat: a set or array of floating point numbers, so multiple fractions between 1 and 0.

  • SFVec3F: an XYZ coordinate (a vector)

  • MFVec3F: a set or array of XYZ coordinates (an array of vectors)

  • SFNode: a node within the file by name.

  • MFNode: a set or array of nodes in the file

  • SFTime: a timestamp or value of time automatically generated by the system on request.

  • SFRotation: A single field multiple number value that describes a vector (XYZ coordinate) and a rotation angle in radians. For example, 0 1 0 1.57.

    Let's decode the rotation event. The example says, there is a rotation event of 1.57 radians (90 degrees) about the Y axis Think of the X Y Z values not as positions but as yes/no switches that tell the VRML engine which axis is the axis about which something is to be rotated, or simply, X is NO, Y is YES, Z is NO and the angle of rotation is 90 degrees. So, turn the receiver of the event one quarter of a complete turn.

    Transforms


    Before we talk about grooms that can offer rotation events (rings), let’s look at brides that can accept them. In VRML/X3D, all of the elements of the language are referred to as ‘nodes’. A basic organizing element of a VRML world is the transform node. Just like the bride, a transform node can have children nodes and when asked the right way, can turn the children around.

    Transform {
    rotation 0 1 0 1.57
    children [
    … child nodes
    ]
    }

    In geekSpeak, the concept that nodes have other nodes as children is called ‘containment’ or ‘hierarchy’. The idea in animation is that any event received by the outermost or parent node passes that event to all of its children. So, if the bride turns 90 degrees, so do all of the children. On the other hand, it the child receives an event, it turns 90 degrees relative to where the parent is without turning the parent.

    What? Children turning around without permission from their parents? Merciful heavens! Children follow their parents otherwise. Clear? Good.

    To make this possible, transforms can be the children of other transforms.

    Transform {
    rotation 0 1 0 1.57
    children [
    Transform {
    rotation 0 1 0 1.57
    children [
    … child nodes such as transforms, groups, boxes, spheres, text, etc.
    ] }]}

    However, a transform is not something you can see. It is actually the space that something you can see is inside. So a transform with a transform as a child is a space contained within a space. The geekSpeak term for this is ‘nested finite coordinate system’, or simply FCS. Don’t let this become a burden to you, but remember this:

    A rotation or any event that changes the location, rotation of position of any thing seeable within the transform is figured relative to the parent.

    If you remember anything from high school geometry beyond how hot it was in that room or the bodacious body two seats in front of you, you remember the concept of an ‘origin’, that is the zero point in the graph from which you count upwards or into negative numbers. For now just know that each transform has its own origin and it is relative the origin of the world space, the outermost origin which the system gives you for free, or it is relative to the space is it inside of.

    Know what’s inside your head. Know what your head is inside of.

    That is all you need to know.

    Fields


    A transform is an example of a node that can only receive events. It cannot send them. However, it does not use a received event to set the rotation value. It uses a property that is said to be “set”. This will confuse you if you take it too literally. You will want to know why we are suddenly talking about properties instead of events. Accept it. Don’t fight the author. Oh drat! I suppose I have to explain it anyway.

    When an event is sent or received, it is property value that is set as a result of sending or receiving the event. The event ins and event outs are the interfaces that serve as connection to the node. When an event is received, a property value is changed to the value of the event it receives. These property values are called fields.

    In VRML, there are two kinds of fields:

  • field: a property value set by the author. It is the same for the life of the world or has an initial value that can be changed by a script.
  • exposed field: a property value that can be changed by events.

    In X3D, the new version of VRML, all fields are exposed, but for this tutorial, we will only look at VRML and in VRML, you need to know which fields are exposed and which can only be set by the author. There is a very good book by Jed Hartman and Josie Wernecke, The VRML 2.0 Handbook that I keep by my side at all times when authoring. There are also several sites on the web with that information. I will tell you that and leave it up to you to go Google for the information.

    Or….what the heck… See VRML97. Polite, ain’t I?

    So let’s go over that in short form:

  • Node field values change as a result of receiving events sent by other nodes.
  • Events are values of specific types.
  • Event interfaces are eventIns or eventOuts.
  • Any event sent by an eventOut must match the corresponding type of the eventIn.

    Routes


    Before we leave the basics of our journey, let’s talk about the Map. Most travelers have a good map. A VRML adventurer NEVER leaves home without one even if only in their head. A map is a territory with routes to destination. A VRML map is the same. For an event to travel from node to node, it uses ROUTEs.


    ROUTE AvatarProx.enterTime TO doAct.walkFromBridgeToTemple


    This example of a ROUTE instructs a time eventOut (SFTime) to be sent from a Proximity Sensor object named AvatarProx to a time eventIn (SFTime) in a script object named doAct. In this case, when the user gets near the object with the proximity sensor, it will automatically activate and send the time of the user entering the area described in the sensor to the script. Upon receiving this event, the script will act on it and start the avatar’s walk from its current location on a bridge in the world to a temple in that world.

    Scripts


    There is another way to enable these events to be sent and received. I’ll describe that later. It is a bit like Gandalf perishing in the gorge and coming back with a new and better smelling robe but the same horse. In other words, it is script magic.

    A script is also a node and can receive and send events. Unlike the nodes we’ve looked at so far, where the nodes are defined by the designers of the VRML language, you determine what kinds of events are handled by the script, the fields and the names of both. A script node structure is this:

    DEF nameOfScript Script {

    eventIn eventType eventName
    eventOut eventType eventName
    field fieldType fieldname fieldDefaultValue

    directOutput TRUE # Optional. see below.

    url "javascript:

    function functionName (value, timestamp) {
    someLogic

    }”
    }

    Take particular heed of the quotation marks. Dropping one of these is a common error and your browser won’t necessarily tell you anything more than something about bad syntax. The quotation marks are the languages way of telling the VRML browser that what is in the quote marks is NOT VRML syntax, it is Javascript, so give this to the Javascript handler.

    This will give you misery at times. For example, to comment out a VRML statement, you use the # sign (octothorpe or pound sign depending on which side of the big pond you live). In Javascript, you use the // or double slash. If like me you use an ASCII editor such as Professional File Editor (free and highly recommended because it can find beginning and end curly braces), you’ll screw this up more than once and find yourself screaming at the system because you KNOW your logic is right so why is the system complaining, then you realize you used # where you needed \\, and so on.

    That’s life in the UTF trenches. Don’t look it up. Think: ‘U Da Fool’.

    The eventIns and Outs behave exactly as for any other VRML node. They must be type-compatible with their senders and receivers. For each event, there is a corresponding function or handler that will receive or send the event. The name of the function is exactly the same as the name of the event in or out that is handles. The value passed by the function is of the same type as the event. The timestamp is automatically generated by the browser for the time that the event is received. To the value and the timestamp can be used in the function logically, errrr… for comparing, for setting other values, etc.

    The fields can be of any type including other nodes. This is particularly useful because it enables you to set the property values of these nodes from within the script. Note that fields don’t have handlers. Fields are properties that can have their values set either by default in their declaration or by the event handlers.

    I assume that you are familiar with Javascript. If not, this tutorial is not for you. There are plenty of good resources on the web and at Barnes and Nobles to teach you how to write Javascript. In the example that follows, I explain the purpose of the script statements, but you are advised to get a good reference book. Ok? Ok.

    Earlier I said that there is magic in scripts that obviate (nice word that; the opposite of bloviate almost) the need for ROUTE statements. The phase ‘directOut TRUE’ is that magical spell. Some claim it is ‘black magic’ and makes a VRML file harder to read. I believe the opposite. Its convenience far outweighs its obsfuscation. Don’t look that up either. Just understand that when directOut is set to true, you can send eventOuts declared in the script directly to the nodes referenced in the script.

    In the interface declaration of the Script you will see a statement with this structure:

    field fieldType fieldname USE nameOfNodeInFile

    That USE keyword tells the VRML browser to automatically route any event or property change to the named node via the fieldname alias. So you will see something like this:

    field SFNode turnDownSoundTS USE TurnDownSounds

    In a script you can see:

    turnDownSoundTS.startTime = value;

    where the startTime is a property of the TurnDownSounds node, the value is an SFTime value that was passed to the function enclosing the statement or is the timestamp of the event. Note the dot (.) between the node alias and the startTime property name. That is a standard Javascript or object-property name convention you see in several object-oriented languages. Simply,

    objectName.propertyName.

    To summarize, a script is a node type for getting and setting property values in other nodes including itself. A script has an interface specification for the events and fields it will handle. For each event, there is a corresponding Javascript function or event handler of the same name. Within the script, the Javascript functions can conditionally set the values of the fields of the Script node and other nodes within the file with or without the use of ROUTE statements.

    PROTO


    You had to have wondered if the title of this tutorial contained a typo. The nephew of Bilbo Baggins was Frodo, not Proto. Sue me.

    A proto is the keyword to identify a VRML prototype. What is a prototype?

    XML talks longingly and smugly about ‘extensibility’. However, any webHead who has written a page of it knows that adding or subtracting tags from an XML Schema does not a language extend. No sir, without scripts, there are no semantics. Without reliable field types, there are no semantics. XML is really just a syntax the way curly brackets and square brackets and commas and white space and keywords in VRML are a syntax.

    EYURRP? Keywords, didja say? Aren’t those bad? No Matilda. All things have names if they want to behave in polite society or polite computer code. A keyword is a word reserved by the language for the things its handler, the VRML browser in this case, must….handle. It’s just a name but a name in a namespace meaning it has meaning and you can’t use it because…. Well, never mind.

    All of the fixed names are the names of node types. A Transform is the name for a bit of space. A TimeSensor is a name for an object that provides time stamps instead of foodstamps. A FoodSensor is a dog downstairs or my son but not a reserved node name in VRML. But isn’t VRML a modeling language? What is you really want a FoodSensor, need a FoodSensor, just can’t live without a FoodSensor.

    Well, you prototype one using a keyword, a name, and a bit of bracketing.

    PROTO FoodSensor [
    interfaceSpecification … eventIns, Outs, and fields

    ]{

    ... VRML nodes including other protos and scripts for events and ROUTEs

    }

    You will note that a PROTO looks a lot like a script. A secret: all of the VRML nodes are really just protos with special status as being handled by the VRML browser instead of by your code. Or so they say. I’ve never looked.

    The differences between a script and a proto are that the script can only occur once in a VRML file, and it cannot contain other nodes except as fields. A script is a node itself. A proto is a specification for a node. What does that mean? It means that a script can do stuff when you reference it by name and event interface such as

    ROUTE someTS.startTime TO doAct.turndownsound

    but it cannot be used to create other nodes like itself. A proto cannot ever receive or send events or do anything EXCEPT create nodes like itself which then CAN receive or send events. In other words, a PROTO is a template or prototype for creating new node types. These new node types have the same interface as the PROTO, duplicate the event handlers and other nodes specified in the proto, and can be referenced many times to create as many of these nodes as you need the same way you can with other VRML nodes. To use a proto, somewhere below the proto declaration you will see

    DEF MyDogMurdock FoodSensor{property-value pairs}
    DEF MySonDaniel FoodSensor {property-value pairs}

    And so on. Until all the food is eaten or the langoliers get them first.

    This is a very cool thing and very handy. When you are looking at a VRML world, the creatures you see such as avatars are typically PROTO node instances. In fact, creating protos and sharing them or selling them is one of the most creative-friendly or business-lucrative products you can make other than the worlds themselves. There are whole libraries of protos for sale and for love on the Internet. Go to Google and type in “VRML PROTO” and look at all the nice toys the furry VRMLers before you have left for you to play with. Protos are the key to production work in VRML.

    EXTERNPROTO



    But how do we share protos without copying them into each VRML file that needs them? Glad to see you’re thinking ahead.

    Sharing a proto is done with an EXTERNPROTO. This ‘external proto’ is just that: a named reference to a PROTO in another file. An externproto duplicates the name and the interfaces of the PROTO it needs and refers to. Note I said, needs, not necessarily all of the events and fields of that proto. Why? An externproto is itself, not a complete specification. It is a reference to a proto that does that. By making that reference, the proto can be used in the file that references it as if it were there, but doesn’t necessarily need all of the events and fields, only the ones to be used in the referring file. Otherwise, it is the same with one difference. It needs the URL of the proto it refers to. So an EXTERNPROTO might look like this:

    EXTERNPROTO FoodSensor [
    eventIn SFBool walkToRefrigerator
    eventOut SFTime turnDownTelevision
    eventOut SFTime StartRummaging
    ]
    "daniel.wrl"

    while the complete Daniel prototype has many more events such as telephoneRings, walkMurdock, and so on. He is really a pretty complete model for a teen-ager.

    EXTERNPROTOs play a very important role in VRML besides enabling you to reuse code. They serve as the means to route events AMONG VRML files used in the same world. I will demonstrate that in the example that follows because this is a key concept that is not often taught well if taught at all. When creating VRML, you want to create modular reusable components as with any building or development task for all the same reasons. When assembling these, you may use Inline statements that act like Include statements in other languages. In VRML, inlines are namespace-opaque. That means that you cannot simply route an event to another node in a different file unless it exposes an interface for that task. Inlines cannot do that.

    Externprotos can and do as we’ll see in the next installment of this tutorial.
  • 1 comment:

    Anonymous said...

    It is very interesting for me to read this blog. Thank author for it. I like such topics and anything connected to this matter. I would like to read more on that blog soon.