Advanced javascript in VRML

Introduction

This tutorial page assumes a good understanding of vrmlscript in particular directOutput and array access methods.

Dynamically adding objects to a world

This example uses a Script node to add an object to the world on loading.

#VRML V2.0 utf8
# When scene loads (initialize function) add the yellow sphere

# We store the new object in this Group node
DEF AddedObject Group {
 children [
 ]
}
DEF Generate Script {
 field SFNode addedObject USE AddedObject
 field MFNode tempNode []
 field SFString str ""
 directOutput TRUE
 url "javascript:
  function initialize () {
   // Create new object as a string
   str+='Transform { ';
   str+=' translation -2 0 0 ';
   str+=' children [ ';
   str+='  Shape { ';
   str+='   appearance Appearance { ';
   str+='    material DEF Yellow Material { ';
   str+='     diffuseColor 1 1 0 ';
   str+='    }';
   str+='   }';
   str+='   geometry Sphere { ';
   str+='    radius 0.5 ';
   str+='   }';
   str+='  }';
   str+=' ]';
   str+='}';
   // convert string to VRML and store in temporary
   // node.
   tempNode=Browser.createVrmlFromString(str);

   // add the object to the scene
   addedObject.addChildren=tempNode;

  }
 "
}

Dynamically adding objects and ROUTEs to a world

This example uses a Script node to add an object to the world and also add a ROUTE from an existing TimeSensor to the new geometry's transparency.

#VRML V2.0 utf8
# When the box is clicked on the 'Generate' Script
# creates a new yellow sphere which is linked to the existing 'Timer'

DEF Scene Group {
 children [
  DEF Sensor TouchSensor {}
  Shape {
   appearance Appearance {
    material Material {
     diffuseColor .1 .44 .22
     shininess .1
     specularColor .15 .15 .02
     ambientIntensity 0
     emissiveColor .04 .18 .09
    }
   }
   geometry Box {
    size 1 1 1
   }
  }
 ]
}

# existing TimeSensor we wish to utilize
# The new Object will have a ROUTE from this TimeSensor added
DEF Timer TimeSensor {
 cycleInterval 1
 startTime -1
 loop TRUE
}
DEF AddedObject Group {
 children [
 ]
}
DEF Generate Script {
 eventIn SFTime touchTime
 field SFNode addedObject USE AddedObject
 field MFNode tempNode []
 field SFString str ""
 field SFNode timer USE Timer
 directOutput TRUE
 url "javascript:
  function touchTime (val,ts) {
   // Create new object as a string
   str+='Transform { ';
   str+=' translation -2 0 0 ';
   str+=' children [ ';
   str+='  Shape { ';
   str+='   appearance Appearance { ';
   str+='    material DEF Yellow Material { ';
   str+='     diffuseColor 1 1 0 ';
   str+='    }';
   str+='   }';
   str+='   geometry Sphere { ';
   str+='    radius 0.5 ';
   str+='   }';
   str+='  }';
   str+=' ]';
   str+='}';
   // convert string to VRML and store in temporary
   // node.
   tempNode=Browser.createVrmlFromString(str);

   // add the object to the scene
   addedObject.addChildren=tempNode;

   // Now add the ROUTE from the Timer to the Yellow Material

   // tempNode[0].children[0].appearance.material is the pointer to the
   // yellow material's DEFed name

   // that is 1st node, then 1st child of node, then appearance,
   // then material
   Browser.addRoute(timer, 'fraction_changed', tempNode[0].children[0].appearance.material, 'transparency');
  }
 "
}
# ROUTE touchTime to Script
ROUTE Sensor.touchTime TO Generate.touchTime

# ROUTE touchTime to TimeSensor
ROUTE Sensor.touchTime TO Timer.startTime

Examples

The 1st example in completed form Dynamically adding objects to a World
The 2nd example in completed form Dynamically adding objects and ROUTEs to a World

Notes

The usage of MFNode/SFNode in Browser.addRoute may appear odd but is actually necessary. Some worlds may already contain a DEFed node with the same name. Also it prevents problems which would occur with using just the DEFed names of nodes.

Usage of the print statement within the Script node is one way of figureing out the values for the tempNode values. For example print (tempNode[0].children[0]); would print Shape.