The Seamless3d Modelling Language

Most of the effort so far has focused on developing a WYSIWYG editor for creating VRML/X3D and POV-Ray content but it is inevitable that a specialized 3d viewer that can take advantage of seamless3d's powerful built in compiler will emerge.

Why Seamless3d is designed to be more script friendly than VRML/X3D

Although seamless3d is influenced by VRML97, Seamless3d is designed to be a more script friendly and a more powerful modelling language than VRML/X3D by making scripts integrated into the design and by not having all events deferred.

In Example 1, we have VRML97 code for a spinning box using 2 ROUTEs and an OrienationInterpolator.

Example 1:

#VRML V2.0 utf8

DEF transform Transform{
    children Shape{
        appearance Appearance{
                    material Material{}
        }
        geometry Box{}
    }
}
DEF orientationInterpolator OrientationInterpolator{
    key [0 .333333 .666666 1]
    keyValue [0 1 0 0 0 1 0 2.094395 0 1 0 4.18879 0 1 0 0]
}
DEF timeSensor TimeSensor{
    cycleInterval 4
    loop TRUE
}
ROUTE timeSensor.fraction_changed TO orientationInterpolator.set_fraction
ROUTE orientationInterpolator.value_changed TO transform.rotation


In Example 2, ROUTEs are replaced with script but a ROUTE is also added from the TimeSensor to the Script node because there is no other way to call a script from a Sensor node in VRML/X3D.

Example 2:

#VRML V2.0 utf8

DEF transform Transform{
    children Shape{
        appearance Appearance{
            material Material{}
        }
        geometry Box{}
    }
}
DEF orientationInterpolator OrientationInterpolator{
    key [0 .333333 .666666 1]
    keyValue [0 1 0 0 0 1 0 2.094395 0 1 0 4.18879 0 1 0 0]
}
DEF timeSensor TimeSensor{
    cycleInterval 4
    loop TRUE
}
DEF script Script{
    directOutput TRUE
    field SFNode transform USE transform
    field SFNode orientationInterpolator USE orientationInterpolator
    eventIn SFFloat onFrame
    url "javascript:
    function onFrame(v){
        orientationInterpolator.set_fraction = v;
        transform.rotation = orientationInterpolator.value_changed;
    }
    "
}
ROUTE timeSensor.fraction_changed TO script.onFrame


Example 2 is not as clean as example 1 because it is only one ROUTE less and the Script node added adds 12 lines!
Although the actual function contains only 2 lines of script, the extra lines around the function are needed because:
  1. All script functions must be contained in a Script node (but unlimited functions can be contained in a single Script node).
  2. VRML/X3D requires that in order to reference a node external to the Script node, a SFNode field be added to the Script node with it USEing the external node.
  3. An eventIn field must be added to the Script node with the same name as the function so that a ROUTE can call the function by sending values to the eventIn field.
  4. The directOutput field must be set to TRUE to allow for nodes to be referenced.
  5. VRML/X3D is a ROUTE oriented design.

In Example 3, script is utilised more neatly by replacing the OrientationInterpolator node with a single line of script:

Example 3

#VRML V2.0 utf8

DEF transform Transform{
    children Shape{
        appearance Appearance{
            material Material{}
        }
        geometry Box{}
    }
}
DEF timeSensor TimeSensor{
    cycleInterval 4
    loop TRUE
}
DEF script Script{
    directOutput TRUE
    field SFNode transform USE transform
    eventIn SFFloat onFrame
    url "javascript:
    function onFrame(v){
        transform.rotation = new SFRotation(0, 1, 0, Math.PI * 2 * v);
    }
    "
}
ROUTE timeSensor.fraction_changed TO script.onFrame


This is significalty cleaner than the previous example but this still has more lines of code than the first example.

Some advise not to reference nodes from a script node and instead use the approach shown in example 4 because of problems that can arise when events are deferred for VRML/X3D.

Example 4

#VRML V2.0 utf8

DEF transform Transform{
    children Shape{
        appearance Appearance{
            material Material{}
        }
        geometry Box{}
    }
}
DEF timeSensor TimeSensor{
    cycleInterval 4
    loop TRUE
}
DEF script Script{
    eventOut SFRotation spin_changed
    eventIn SFFloat onFrame
    url "javascript:
    function onFrame(v){
        spin_changed = new SFRotation(0, 1, 0, Math.PI * 2 * v);
    }
    "
}
ROUTE timeSensor.fraction_changed TO script.onFrame
ROUTE script.spin_changed TO transform.rotation



This may simplify some of the lines in the script node and the directOutput field no longer has to be specified but because of the extra ROUTE, it is not any cleaner and feels more like spaghetti logic than example 3.

Although in the last 2 examples the OrientationInterpolator is replaced with a single line of script, it is debatable if the last 2 examples look any more elegant than the first example.
I think this is because ROUTEs feel like they are part of the language the way they are more integrated into the design (a ROUTE oriented design). This is why it often feels good if scripts can be avoided for VRML/X3D but scripts offer greater creative freedom so typically a combination of ROUTEs and scripts are used but this can be messy.

Often one hopes one can avoid using script for some minor task and so ROUTEs are first applied and then later while debugging, scripts may be tried if they look like they may offer a solution and then later again one may come up with another idea that might utilize ROUTEs better but alternating back and forth between what feels like 2 different languages can be time consuming.

When scripts are required for VRML/X3D I prefer to do as much as I can using scripts and use ROUTEs only when there is no alterative way offered (such as for capturing events from Sensor nodes).

The next example which uses Seamless3d code offers a solution as clean as using ROUTEs (free of script) using script (free of ROUTEs).

Example 5

#SMLS V2.123 utf8

Seamless{
    effect ColorEffect{}
    skeleton DEF part Part{}
    build BoxBuild{
        part USE part
    }
}
Anim{
    play TRUE
    pause FALSE
    loop TRUE
    period 4
    void onFrame(float v){
        part.rotation = Rotation(0, 1, 0, PI * 2 * v);
    }
}


With this script friendly design, scripts can accomplish the same trivial tasks that can be done using ROUTEs just as easily. The following VRML/X3D ROUTE:

ROUTE nodeA.field TO nodeB.field

translates to the following line of seamless script:

nodeB.feild = nodeA.feild

and scripting options not available to ROUTEs can be so much more easily taken advantage of:

nodeB.field = nodeA.field * .5

Firing Events Immediatly as Opposed to Defering Events

In Seamless3d events fire immediately by default the same way they do for other modern procedural oriented languages. This keeps the language both simple and flexible and avoids exposing the beginner to a non intuitive scripting environment. For example most would intuitively expect the following code to display 2 on the screen:


Deferred Event Example:

#VRML V2.0 utf8

Shape{
    appearance Appearance{
        material Material{}
    }
    geometry DEF text Text{}
}
PROTO MyNode[
    exposedField SFInt32 myField 0
]{
    Group{}
}

DEF myNode MyNode{}

Script{
    directOutput TRUE
    field SFNode myNode USE myNode
    field SFNode text USE text
    field MFString str []
    url "javascript:
    function initialize(){
        myNode.myField = 1;
        myNode.myField = myNode.myField + 1;

        str[0] = myNode.myField;
        text.string = str;
    }
    "
}



But if the events are deferred for VRML/X3D, 0 will be displayed. The Xj3D browser gives an answer of 0 which is consistent with this but four of the most popular VRML browsers, Cosmo, Contact, Cortona and Octaga will display the intuitive answer of 2 which suggests they fire events immediately the same as Seamless3d. Are these browsers not conforming to the VRML standard? It does not seem clear to me that VRML must defer events because the VRML specs state under
4.12.5 Scripts with direct outputs:

When setting a value in another node, implementations are free to either immediately set the value or to defer setting the value until the Script is finished.

This to me seems to be saying it is ok to either defer or not defer events for VRML (not to be confused with X3D), if so the answer can be either 0 or 2 allowing for inconsistent behaviour from different browsers.

Order of instructions

It is said by some that ROUTEs have the advantage of it not mattering what order they are placed in your code because the same behaviour will always result but if the user expects their instructions to follow through in the order they specify as most would intuitively expect, the user will experience frustration.

Avoiding self modifying code

It is said by some that ROUTEs offer the advantage of being able to be displayed as a map to show all of the event ins and event outs and that ROUTEs can be added and removed on the fly.
But if ROUTEs can be added or deleted at run time you are not guaranteed of seeing all your ROUTEs mapped in your source code.
Self modifying code is a common request by beginner programmers and it can have it's uses but because self modifying code can make code very difficult to read, debug and document, most programmers use more practical means.

Avoiding browser bloat

By avoiding the extra overhead required for ROUTEs and a deferred event mechanism the browser is freed from a lot of unnecessary baggage.

Compatibility with other procedral languages

Seamless script offers a standard way to process logic that does not get in the way of the novice advancing on to more advanced tasks.

Using a more standard approach for processing logic makes it much easier to convert scripts from and to other procedral languages.

Compatibility with VRML/X3D

When seamless scripts are exported to VRML/X3D the necessary ROUTEs are created but if one wants to write strict legal code for VRML/X3D it must be realized not all of the powerful scripting capabilities from the Seamless3d modelling language apply, largely due to VRML/X3D being a ROUTE oriented language. Therefore when targeting VRML/X3D, scripts have to be written for the language but seamless can still make scripting easier when targeting VRML/X3D because there is no need to set up a USE to reference a node and there is no need to add a Script node nor is there any need to explicitly add ROUTEs and one can take advantage of using operators for SFRotation and SFVec3f types. For more information on how seamless utilises operators better than JavaScript see VRML JavasScript Conversion to Seamless3d C++


Why Seamless3d is not yet another incompatible 3d modelling language

It is fair to say Seamless3d is not a new 3d modelling language but rather it is a C++ library for creating and displaying 3d content and that this library is influenced by VRML and is designed to be able to interpret most VRML content. However to allow content for this library to be viewed on-line by a Seamless3d player (currently the only Seamless3d player is the Seamless3d editor), a specialized on-line script compiler is required to ensure scripts do not pose any more security issues than would arise from any other web friendly scripting language. C++ is highly suitable for writing complex applications and because it is a versitile language by design it is also highly suitable for writing the most trivial of scripts but seamless3d format does not have to be strictly C++ code for it to run in the player, it just has to be be designed so that it relates 100% to the C++ standard so that the content is guaranteed of being able to be compiled by any standard C++ compiler after it has been passed through a converter. This gives more than enough elbow room in order to keep the standard both novice and expert friendly. I feel it is very important to keep the modelling language compatible with C++ because:

  1. C++ enjoys an enormous amount of support and is the most popular language used for writing 3d applications.
  2. C++ is an already well established ISO non proprietary standard.
  3. Scripts for on-line content can be interchanged with offline content.
  4. C++ offers a great level of creative freedom.
  5. Through custom built libraries C++ comes closest to satisfying everyone's needs.
  6. Scripts can be single stepped through and examined frozen in time using standard C++ debugging aids.
  7. Standard C++ compilers can be used to verify script behavior.
  8. Very fast Scripts can be written for simulating physics in real time.
  9. It does not hold the novice back from advancing.
  10. C++ is not a trade mark of any organization and is free of lawsuit threats if one finds the need to innovate on the standard.
Same as C++, the Seamless3d modelling language is not intended to be owned by any individual including my self (thyme) or become a trademark of any organisation.

[3d Modelling Software] [Tutorials] [Forum] [Features] [Download] [Gallery] [FAQ] [Worlds] [Avatars] [Links] [Thyme]


Copyright © 2000-2009 Graham Perrett thyme@seamless3d.com