Extensible 3D (X3D) encodings
Part 1: Extensible Markup Language (XML) encoding
Annex C
(informative)
Examples
This annex provides a variety of X3D examples using the XML encoding. Table C.1 contains a table of contents that lists the topics in this clause:
Table C.1 — Topics in this annex
This example contains a simple scene defining a view of a red sphere and a blue box, lit by a directional light as shown in Figure C.1:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd"> <X3D version='3.0' profile='Interchange'> <head> <meta name='filename' content='RedSphereBlueBox.x3d'/> </head> <Scene> <Transform> <NavigationInfo headlight='false' avatarSize='0.25 1.6 0.75' type='"EXAMINE"'/> <DirectionalLight/> <Transform translation='3.0 0.0 1.0'> <Shape> <Sphere radius='2.3'/> <Appearance> <Material diffuseColor='1.0 0.0 0.0'/> </Appearance> </Shape> </Transform> <Transform translation='-2.4 0.2 1.0' rotation='0.0 0.707 0.707 0.9'> <Shape> <Box/> <Appearance> <Material diffuseColor='0.0 0.0 1.0'/> </Appearance> </Shape> </Transform> </Transform> </Scene> </X3D>
Click here to view this example in a 3D scene window.
Reading the following file results in three spheres being drawn. The first sphere defines a unit sphere at the origin. The second sphere, named "Joe", defines a smaller sphere translated along the +x axis, the third sphere is a reference to the second sphere and is translated along the -x axis. If any changes occur to the second sphere (e.g. radius changes), the third sphere will change to the picture shown in Figure C.2:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd"> <X3D version='3.0' profile='Interchange'> <head> <meta name='filename' content='Instancing.x3d'/> </head> <Scene> <Transform> <Shape> <Sphere/> </Shape> <Transform translation='2.0 0.0 0.0'> <Shape DEF='Joe'> <Sphere radius='0.2'/> </Shape> </Transform> <Transform translation='-2.0 0.0 0.0'> <Shape USE='Joe'/> </Transform> </Transform> </Scene> </X3D>
Click here to view this example in a 3D scene window.
(Note that the spheres are unlit because no appearance was specified.)
A simple table with variable colours for the legs and top might be prototyped as shown in Figure C.3:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd"> <X3D version='3.0' profile='Immersive'> <head> <meta name='filename' content='Prototype.x3d'/> </head> <Scene> <ProtoDeclare name='TwoColorTable'> <ProtoInterface> <field name='legColor' type='SFColor' value='.8 .4 .7' accessType='initializeOnly'/> <field name='topColor' type='SFColor' value='.6 .6 .1' accessType='initializeOnly'/> </ProtoInterface> <ProtoBody> <Transform> <Transform translation='0.0 0.6 0.0'> <!-- table top --> <Shape> <Appearance> <Material DEF='TableTopMaterial'> <IS> <connect nodeField='diffuseColor' protoField='topColor'/> </IS> </Material> </Appearance> <Box size='1.2 0.2 1.2'/> </Shape> </Transform> <Transform translation='-0.5 0.0 -0.5'> <!-- first table leg --> <Shape DEF='Leg'> <Appearance> <Material DEF='LegMaterial' diffuseColor='1.0 0.0 0.0'> <IS> <connect nodeField='diffuseColor' protoField='legColor'/> </IS> </Material> </Appearance> <Cylinder height='1.0' radius='0.1'/> </Shape> </Transform> <Transform translation='0.5 0.0 -0.5'> <!-- another table leg --> <Shape USE='Leg'/> </Transform> <Transform translation='-0.5 0.0 0.5'> <Shape USE='Leg'/> <!-- another table leg --> </Transform> <Transform translation='0.5 0.0 0.5'> <Shape USE='Leg'/> <!--another table leg --> </Transform> <!-- End of root Transform's children --> </Transform> <!-- End of root Transform --> </ProtoBody> </ProtoDeclare> <!-- End of prototype --> <!-- The prototype is now defined. Although it contains a number of nodes, only the legColor and topColor fields are public. Instead of using the default legColor and topColor, this instance of the table has red legs and a green top: --> <ProtoInstance name='TwoColorTable'> <fieldValue name='legColor' value='1 0 0'/> <fieldValue name='topColor' value='0 1 0'/> </ProtoInstance> <NavigationInfo type='"EXAMINE"'/> <!--Use the Examine viewer--> </Scene> </X3D>
Click here to view this example in a 3D scene window.
This Script node decides whether or not to open a bank vault given openVault and combinationEntered messages. To do this, it remembers whether or not the correct combination has been entered. The Script node combined with a Sphere, a TouchSensor and a Sound node to show how is works. When the pointing device is over the sphere, the combinationEntered inputOnly field of the Script is sent. Then, when the Sphere is touched (typically when the mouse button is pressed) the Script is sent the openVault inputOnly field. This generates the vaultUnlocked outputOnly field which starts a ‘click’ sound. Here is the example:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd"> <X3D version='3.0' profile='Immersive'> <head> <meta name='filename' content='Scripting.x3d'/> </head> <Scene> <Script DEF='OpenVault'> <field name='openVault' type='SFTime' accessType='inputOnly'/> <field name='combinationEntered' type='SFBool' accessType='inputOnly'/> <field name='vaultUnlocked' type='SFTime' accessType='outputOnly'/> <field name='unlocked' type='SFBool' value='false' accessType='initializeOnly' /> <![CDATA[ ecmascript: function combinationEntered (value) { unlocked = value; } function openVault(value) { if (unlocked) vaultUnlocked = value; } ]]> </Script> <Shape> <Appearance> <Material diffuseColor='1 0 0'/> </Appearance> <Sphere/> </Shape> <Sound maxBack='1000' maxFront='1000' minBack='1000' minFront='1000'> <AudioClip DEF='Click' stopTime='1' description='clicking sound' url='"click.wav"'/> </Sound> <TouchSensor DEF='TS'/> <ROUTE fromNode='TS' fromField='isOver' toNode='OpenVault' toField='combinationEntered'/> <ROUTE fromNode='TS' fromField='touchTime' toNode='OpenVault' toField='openVault'/> <ROUTE fromNode='OpenVault' fromField='vaultUnlocked' toNode='Click' toField='startTime'/> </Scene> </X3D>
Note that the openVault inputOnly field and the vaultUnlocked outputOnly field are of type SFTime, which allows them to be wired directly to a TouchSensor or TimeSensor.
Click here to view this example in a 3D scene window.
The following IndexedFaceSet (contained in a Shape node) uses all four of the geometric property nodes to specify vertex coordinates, colours per vertex, normals per vertex, and texture coordinates per vertex (note that the material sets the overall transparency):
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd"> <X3D version='3.0' profile='Interchange'> <head> <meta name='filename' content='GeometricProperties.x3d'/> </head> <Scene> <Shape> <IndexedFaceSet coordIndex='0, 1, 3, -1, 0, 2, 3, -1'> <Coordinate point='0 0 0, 1 0 0, 1 0 -1, 0.5 1 0'/> <Color color='0.2 0.7 0.8, 0.5 0 0, 0.1 0.8 0.1, 0 0 0.7'/> <Normal vector='0 0 1, 0 0 1, 0 0 1, 0 0 1'/> <TextureCoordinate point='0 0, 1 0, 1 0.4, 1 1'/> </IndexedFaceSet> <Appearance> <Material transparency='0.5'/> <PixelTexture image='2 2 1 0xFF 0x80 0x80 0xFF'/> </Appearance> </Shape> </Scene> </X3D>
Click here to view this example in a 3D scene window.
X3D has the capability to define new nodes. The following is an
example of a new node RefractiveMaterial. This node behaves as a Material node
with an added field, indexOfRefraction. The list of URLs for the
EXTERNPROTO are searched in order. If the browser recognizes the URN,
urn:inet:foo.com:types:RefractiveMaterial
, it may treat it
as a native type (or load the implementation). Otherwise, the URL,
http://www.myCompany.com/vrmlNodes/RefractiveMaterial.x3d
,
is used as a backup to ensure that the node is supported on any browsers. See
below for the PROTO implementation that treats RefractiveMaterial as a Material
(and ignores the refractiveIndex field).
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd"> <X3D version='3.0' profile='Immersive'> <head> <meta name='filename' content='PrototypesPlus.x3d'/> </head> <Scene> <!--external protype definition --> <ExternProtoDeclare name='RefractiveMaterial' url='"urn:inet:foo.com:types:RefractiveMaterial" "http://www.myCompany.com/vrmlNodes/RefractiveMaterial.x3d" "RefractiveMaterial.x3d"'> <field name='ambientIntensity' type='SFFloat' accessType='inputOutput'/> <field name='diffuseColor' type='SFColor' accessType='inputOutput'/> <field name='specularColor' type='SFColor' accessType='inputOutput'/> <field name='emissiveColor' type='SFColor' accessType='inputOutput'/> <field name='shininess' type='SFFloat' accessType='inputOutput'/> <field name='transparency' type='SFFloat' accessType='inputOutput'/> <field name='indexOfRefraction' type='SFFloat' accessType='inputOutput'/> </ExternProtoDeclare> <Shape> <Sphere/> <Appearance> <ProtoInstance name='RefractiveMaterial' containerField='material'> <fieldValue name='ambientIntensity' value='0.2'/> <fieldValue name='diffuseColor' value='1 0 0'/> <fieldValue name='indexOfRefraction' value='0.3'/> </ProtoInstance> </Appearance> </Shape> </Scene> </X3D>
The URL
http://www.myCompany.com/vrmlNodes/RefractiveMaterial.x3d
contains the following:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd"> <X3D version='3.0' profile='Immersive'> <head> <meta name='filename' content='RefractiveMaterial.x3d'/> </head> <Scene><!--external protype definition--> <ProtoDeclare name='RefractiveMaterial'> <field name='ambientIntensity' type='SFFloat' value='0' accessType='inputOutput'/> <field name='diffuseColor' type='SFColor' value='0.5 0.5 0.5' accessType='inputOutput'/> <field name='specularColor' type='SFColor' value='0 0 0' accessType='inputOutput'/> <field name='emissiveColor' type='SFColor' value='0 0 0' accessType='inputOutput'/> <field name='shininess' type='SFFloat' value='0' accessType='inputOutput'/> <field name='transparency' type='SFFloat' value='0' accessType='inputOutput'/> <field name='indexOfRefraction' type='SFFloat' value='0.1' accessType='inputOutput'/> </ProtoInterface> <ProtoBody> <Material> <IS> <connect nodeField='ambientIntensity' protoField='ambientIntensity'/> <connect nodeField='diffuseColor' protoField='diffuseColor'/> <connect nodeField='specularColor' protoField='specularColor'/> <connect nodeField='emissiveColor' protoField='emissiveColor'/> <connect nodeField='transparency' protoField='transparency'/> </IS> </Material> </ProtoBody> </ProtoDeclare> </Scene> </X3D>
Note that the name of the new node type, RefractiveMaterial, is not used by the browser to decide if the node is native or not; the URL/URN names determine the node's implementation.
Click here to view this example in a 3D scene window.
The target parameter can be used by the anchor node to send a request to load a URL into another frame:
<Anchor url='"http://somehost/somefile.html"' parameter='[ 'target=name_of_frame' ]'> <Shape> <Cylinder /> </Shape> </Anchor>
An Anchor may be used to bind the viewer to a particular viewpoint in a virtual world by specifying a URL ending with #viewpointName, where viewpointName is the DEF name of a viewpoint defined in the world. For example:
<Anchor url='"http://www.school.edu/vrml/someScene.x3d#OverView"'> <Shape> <Box /> </Shape> </Anchor>
specifies an anchor that puts the viewer in the someScene world bound to the viewpoint named OverView when the box is chosen (note that OverView is the DEF name of the viewpoint, not the value of the viewpoint's description field).
If no world is specified, the current scene is implied. For example:
<Anchor url='"#Doorway"'> <Shape> <Sphere /> </Shape> </Anchor>
binds the user's view to the viewpoint with the DEF name Doorway in the current scene.
A directional light source illuminates only the objects in its enclosing grouping node. The light illuminates everything within this coordinate system including the objects that precede it in the scene graph as shown below:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd"> <X3D version='3.0' profile='Interactive'> <head> <meta name='filename' content='DirectionalLight.x3d'/> </head> <Scene> <Group> <Transform DEF='UnlitShapeOne' translation='-3.0 0.0 0.0'> <Shape> <Box/> <Appearance DEF='App'> <Material diffuseColor='0.8 0.4 0.2'/> </Appearance> </Shape> </Transform> <Group DEF='LitParent'> <Transform DEF='LitShapeOne' translation='0.0 2.0 0.0'> <Shape> <Sphere/> <Appearance USE='App'/> </Shape> </Transform> <DirectionalLight/> <Transform DEF='LitShapeTwo' translation='0.0 -2.0 0.0'> <Shape> <Cylinder/> <Appearance USE='App'/> </Shape> </Transform> </Group> <Transform DEF='UnlitShapeTwo' translation='3.0 0.0 0.0'> <Shape> <Cone/> <Appearance USE='App'/> </Shape> </Transform> </Group> </Scene> </X3D>
Click here to view this example in a 3D scene window.
This simple example defines a PointSet composed of 3 points. The first point is red (1 0 0), the second point is green (0 1 0), and the third point is blue (0 0 1). The second PointSet instances the Coordinate node defined in the first PointSet, but defines different colours:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd"> <X3D version='3.0' profile='Interactive'> <head> <meta name='filename'content='PointSet.x3d'/> </head> <Scene> <Shape> <PointSet> <Color color=' 1.0 0.0 0.0'/> <Coordinate DEF='mypts' point='0.0 0.0 0.0, 2.0 2.0 2.0, 3.0 3.0 3.0'/> </PointSet> </Shape> <Transform translation='2.0 0.0 0.0'> <Shape> <PointSet> <Color color=' 0.5 0.5 0.0'/> <Coordinate USE='mypts'/> </PointSet> </Shape> </Transform> </Scene> </X3D>
Click here to view this example in a 3D scene window.
The LOD node is typically used for switching between different versions of geometry at specified distances from the viewer. However, if the range field is left at its default value, the browser selects the most appropriate child from the list given. It can make this selection based on performance or perceived importance of the object. Children should be listed with most detailed version first just as for the normal case. This "performance LOD" feature can be combined with the normal LOD function to give the browser a selection of children from which to choose at each distance.
In this example, the scene consists of a small reference sphere and an LOD node which has two ranges and three children. The browser is free to choose from three Shape choices representing either a detailed or a less-detailed version of the object when the viewer is closer than 10 metres (as measured in the coordinate space of the LOD). The browser should display the less detailed version of the object (box) if the viewer is between 10 and 50 metres, the sphere when closer than 10 metres and should display nothing, the empty Shape last child, if the viewer is farther than 50 metres. Browsers should try to honor the hints given by authors, and authors should try to give browsers as much freedom as they can to choose levels of detail based on performance.
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd"> <X3D version='3.0' profile='Interactive'> <head> <meta name='filename' content='LevelOfDetail.x3d'/> </head> <Scene> <Viewpoint position='0 0 25' description='Start' centerOfRotation='0 0 0'/> <LOD range='10.0, 50.0'> <Shape> <Sphere/> </Shape> <Shape> <Box/> </Shape> <Shape/> </LOD> </Scene> </X3D>
For best results, ranges should be specified only where necessary and LOD nodes should be nested with and without ranges.
Click here to view this example in a 3D scene window.
This example interpolates from red to green to blue in a 10 second cycle:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd"> <X3D version='3.0' profile='Interactive'> <head> <meta name='filename' content='ColorInterpolator.x3d'/> </head> <Scene> <ColorInterpolator DEF='myColor' keyValue='1 0 0, 0 1 0, 0 0 1, 1 0 0' key='0.0 0.333 0.666 1.0'/> <TimeSensor DEF='myClock' cycleInterval='10.0' loop='true'/> <Shape> <Sphere/> <Appearance> <Material DEF='myMaterial'/> </Appearance> </Shape> <ROUTE fromNode='myClock' fromField='fraction_changed' toNode='myColor' toField='set_fraction'/> <ROUTE fromNode='myColor' fromField='value_changed' toNode='myMaterial' toField='diffuseColor'/> </Scene> </X3D>
Click here to view this example in a 3D scene window.
The TimeSensor is very flexible. The following are some of the many ways in which it can be used:
The first example animates a box when the user clicks on it:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd"> <X3D version='3.0' profile='Interactive'> <head> <meta name='filename' content='ClickToAnimate.x3d'/> </head> <Scene> <Transform DEF='XForm'> <Shape> <Box/> <Appearance> <Material diffuseColor='1.0 0.0 0.0'/> </Appearance> </Shape> <TouchSensor DEF='Clicker' description='click to animate'/> <TimeSensor DEF='TimeSource' cycleInterval='2.0'/> <OrientationInterpolator DEF='Animation' keyValue='0.0 1.0 0.0 0.0, 0.0 1.0 0.0 2.1, 0.0 1.0 0.0 4.2, 0.0 1.0 0.0 0.0' key='0.0 0.33 0.66 1.0'/> </Transform> <ROUTE fromNode='Clicker' fromField='touchTime' toNode='TimeSource' toField='startTime'/> <ROUTE fromNode='TimeSource' fromField='fraction_changed' toNode='Animation' toField='set_fraction'/> <ROUTE fromNode='Animation' fromField='value_changed' toNode='XForm' toField='rotation'/> </Scene> </X3D>
Click here to view this example in a 3D scene window.
The second example plays chimes once an hour:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd"> <X3D version='3.0' profile='Immersive'> <head> <meta name='filename' content='AlarmClock.x3d'/> </head> <Scene> <Group> <TimeSensor DEF='Hour' cycleInterval='5.0' loop='true'/> <Sound> <AudioClip DEF='Sounder' stopTime='0.0' description='chime' url='"click.wav"'/> </Sound> </Group> <ROUTE fromNode='Hour' fromField='cycleTime' toNode='Sounder' toField='startTime'/> </Scene> </X3D>
Click here to view this example in a 3D scene window.
Shuttles and pendulums are great building blocks for composing interesting animations. This shuttle translates its children back and forth along the X axis, from -1 to 1 (by default). The distance field can be used to change this default. The pendulum rotates its children about the Z axis, from 0 to π radians and back again (by default). The maxAngle field can be used to change this default.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd"> <X3D version='3.0' profile='Immersive'> <head> <meta name='filename' content='ShuttlesAndPendulums.x3d'/> </head> <Scene> <ProtoDeclare name='Shuttle'> <ProtoInterface> <field name='rate' type='SFTime' value='1' accessType='initializeOnly'/> <field name='distance' type='SFFloat' value='1' accessType='initializeOnly'/> <field name='children' type='MFNode' accessType='initializeOnly'/> <field name='startTime' type='SFTime' value='0' accessType='inputOutput'/> <field name='stopTime' type='SFTime' value='0' accessType='inputOutput'/> <field name='loop' type='SFBool' value='true' accessType='initializeOnly'/> </ProtoInterface> <ProtoBody> <Transform DEF='F'> <IS> <connect nodeField='children' protoField='children'/> </IS> </Transform> <TimeSensor DEF='T'> <IS> <connect nodeField='cycleInterval' protoField='rate'/> <connect nodeField='startTime' protoField='startTime'/> <connect nodeField='stopTime' protoField='stopTime'/> <connect nodeField='loop' protoField='loop'/> </IS> </TimeSensor> <Script DEF='S'> <field name='distance' type='SFFloat' accessType='initializeOnly'/> <field name='position' type='MFVec3f' accessType='outputOnly'/> <IS> <connect nodeField='distance' protoField='distance'/> </IS> <![CDATA[ ecmascript: function initialize () { // constructor:setup interpolator pos1 = new SFVec3f(-distance, 0, 0); pos2 = new SFVec3f(distance, 0, 0); position = new MFVec3f(pos1, pos2, pos1); } ]]> </Script> <PositionInterpolator DEF='I' key='0, 0.5, 1' keyValue='-1 0 0, 1 0 0, -1 0 0'/> <ROUTE fromNode='T' fromField='fraction_changed' toNode='I' toField='set_fraction'/> <ROUTE fromNode='I' fromField='value_changed' toNode='F' toField='translation'/> <ROUTE fromNode='S' fromField='position' toNode='I' toField='keyValue' /> </ProtoBody> </ProtoDeclare> <ProtoDeclare name='Pendulum'> <ProtoInterface> <field name='rate' type='SFTime' value='1' accessType='initializeOnly'/> <field name='maxAngle' type='SFFloat' value='3.14159' accessType='initializeOnly'/> <field name='children' type='MFNode' accessType='initializeOnly'/> <field name='startTime' type='SFTime' value='0' accessType='inputOutput' /> <field name='stopTime' type='SFTime' value='0' accessType='inputOutput' /> <field name='loop' type='SFBool' value='true' accessType='initializeOnly'/> </ProtoInterface> <ProtoBody> <Transform DEF='FF'> <IS> <connect nodeField='children' protoField='children'/> </IS> </Transform> <TimeSensor DEF='TT'> <IS> <connect nodeField='cycleInterval' protoField='rate'/> <connect nodeField='startTime' protoField='startTime'/> <connect nodeField='stopTime' protoField='stopTime'/> <connect nodeField='loop' protoField='loop'/> </IS> </TimeSensor> <Script DEF='SS'> <field name='maxAngle' type='SFFloat' accessType='initializeOnly'/> <field name='rotation' type='MFRotation' accessType='outputOnly'/> <IS> <connect nodeField='maxAngle' protoField='maxAngle'/> </IS> <![CDATA[ ecmascript: function initialize() { // constructor: setup interpolator rot1 = new SFRotation(0, 0, 1, 0); rot2 = new SFRotation(0, 0, 1, maxAngle/2); rot3 = new SFRotation(0, 0, 1, maxAngle); rotation = new MFRotation(rot1, rot2, rot3, rot2, rot1); } ]]> </Script> <OrientationInterpolator DEF='II' key='0, 0.25, 0.5, 0.75, 1' keyValue='0 0 1 0, 0 0 1 1.57, 0 0 1 3.14, 0 0 1 1.57, 0 0 1 0'/> <ROUTE fromNode='TT' fromField='fraction_changed' toNode='II' toField='set_fraction' /> <ROUTE fromNode='II' fromField='value_changed' toNode='FF' toField='set_rotation' /> <ROUTE fromNode='SS' fromField='rotation' toNode='II' toField='set_keyValue' /> </ProtoBody> </ProtoDeclare> <Transform translation='-3 0 0'> <ProtoInstance name='Pendulum'> <fieldValue name='rate' value='3'/> <fieldValue name='maxAngle' value='6.28'/> <fieldValue name='children'> <Shape> <Cylinder height='5'/> <Appearance> <Material diffuseColor='0.8 0.1 0'/> </Appearance> </Shape> </fieldValue> </ProtoInstance> </Transform> <Transform> <ProtoInstance name='Shuttle'> <fieldValue name='rate' value='2'/> <fieldValue name='children'> <Shape> <Sphere/> <Appearance> <Material diffuseColor='0.1 0.8 0'/> </Appearance> </Shape> </fieldValue> </ProtoInstance> </Transform> </Scene> </X3D>
Click here to view this example in a 3D scene window.
These nodes can be used to do a continuous animation when loop is true. When loop is false they can perform a single cycle under control of the startTime and stopTime fields. The rate field controls the speed of the animation. The children field holds the children to be animated.
This example is a simple implementation of a robot. This robot has very simple body parts: a cube for his head, a sphere for his body and cylinders for arms (he hovers so he has no feet!). He is something of a sentry--he walks forward and walks back across a path. He does this whenever the viewer is near. This makes use of C.1, Shuttles and pendulums.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd"> <X3D version='3.0' profile='Immersive'> <head> <meta name='filename' content='Robot.x3d'/> </head> <Scene> <ExternProtoDeclare name='Shuttle' url='"ShuttlesAndPendulums.x3d#Shuttle"'> <field name='rate' type='SFTime' accessType='initializeOnly'/> <field name='distance' type='SFFloat' accessType='initializeOnly'/> <field name='children' type='MFNode' accessType='initializeOnly'/> <field name='startTime' type='SFTime' accessType='inputOutput'/> <field name='stopTime' type='SFTime' accessType='inputOutput'/> <field name='loop' type='SFBool' accessType='initializeOnly'/> </ExternProtoDeclare> <ExternProtoDeclare name='Pendulum' url='"ShuttlesAndPendulums.x3d#Pendulum"'> <field name='rate' type='SFTime' accessType='initializeOnly'/> <field name='maxAngle' type='SFFloat' accessType='initializeOnly'/> <field name='children' type='MFNode' accessType='initializeOnly'/> <field name='startTime' type='SFTime' accessType='inputOutput'/> <field name='stopTime' type='SFTime' accessType='inputOutput'/> <field name='loop' type='SFBool' accessType='initializeOnly'/> </ExternProtoDeclare> <NavigationInfo speed='20' type='"WALK ANY"'/> <Viewpoint position='0 0 150' description='Watch Robot'/> <ProximitySensor DEF='Near' size='200 200 200'/> <ProtoInstance DEF='WALK' name='Shuttle'> <fieldValue name='stopTime' value='1'/> <fieldValue name='rate' value='10'/> <fieldValue name='distance' value='20'/> <fieldValue name='children'> <Transform rotation='0 1 0 1.57'> <Shape> <Appearance DEF='A'> <Material diffuseColor='0 0.5 0.7'/> </Appearance> <!--head--> <Box/> </Shape> <Transform scale='1 5 1' translation='0 -5 0'> <Shape> <Appearance USE='A'/> <!-- body --> <Sphere/> </Shape> </Transform> <Transform rotation='0 1 0 1.57' translation='1.5 0 0'> <ProtoInstance DEF='Arm' name='Pendulum'> <fieldValue name='stopTime' value='1'/> <fieldValue name='rate' value='1'/> <fieldValue name='maxAngle' value='0.52'/> <fieldValue name='children'> <Transform translation='0 -3 0'> <Shape> <Appearance USE='A'/> <Cylinder height='4' radius='0.5'/> </Shape> </Transform> </fieldValue> </ProtoInstance> </Transform> <Transform rotation='0 -1 0 1.57' translation='-1.5 0 0'> <ProtoInstance USE='Arm' name='Pendulum'/> </Transform> </Transform> </fieldValue> </ProtoInstance> <ROUTE fromField='enterTime' fromNode='Near' toNode='WALK' toField='startTime'/> <ROUTE fromField='enterTime' fromNode='Near' toNode='Arm' toField='startTime'/> <ROUTE fromField='exitTime' fromNode='Near' toNode='WALK' toField='stopTime'/> <ROUTE fromField='exitTime' fromNode='Near' toNode='Arm' toField='stopTime'/> </Scene> </X3D>
Click here to view this example in a 3D scene window.
Move closer to the robot to start the animation.
This example of a helicopter demonstrates how to do simple animation triggered by a TouchSensor. It uses an EXTERNPROTO to include a Rotor node from the Internet which does the actual animation.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd"> <X3D version='3.0' profile='Immersive'> <head> <meta name='filename' content='Chopper.x3d'/> </head> <Scene> <ExternProtoDeclare name='Rotor' url='"Rotor.x3d#Rotor"'> <field name='rate' type='SFTime' accessType='initializeOnly'/> <field name='children' type='MFNode' accessType='initializeOnly'/> <field name='startTime' type='SFTime' accessType='inputOutput'/> <field name='stopTime' type='SFTime' accessType='inputOutput'/> </ExternProtoDeclare> <ProtoDeclare name='Chopper'> <ProtoInterface> <field name='rotorSpeed' type='SFTime' value='1' accessType='initializeOnly'/> </ProtoInterface> <ProtoBody> <Group> <TouchSensor DEF='Touch' description='touch to toggle rotor rotation'/> <Inline url='"ChopperBody.x3d"'/> <ProtoInstance DEF='Top' name='Rotor'> <fieldValue name='stopTime' value='1'/> <fieldValue name='children'> <Inline url='"ChopperRotor.x3d"' load='true'/> </fieldValue> <IS> <connect nodeField='rate' protoField='rotorSpeed'/> </IS> </ProtoInstance> </Group> <Script DEF='RotorScript'> <field name='startOrStopEngine' type='SFTime' accessType='inputOnly'/> <field name='startEngine' type='SFTime' accessType='outputOnly'/> <field name='stopEngine' type='SFTime' accessType='outputOnly'/> <field name='engineStarted' type='SFBool' value='false' accessType='initializeOnly'/> <![CDATA[ ecmascript: function startOrStopEngine(value) { // start or stop engine: if (!engineStarted) { startEngine = value; engineStarted = true; } else { stopEngine = value; engineStarted = false; } } ]]> </Script> <ROUTE fromNode='Touch' fromField='touchTime' toNode='RotorScript' toField='startOrStopEngine' /> <ROUTE fromNode='RotorScript' fromField='startEngine' toNode='Top' toField='startTime' /> <ROUTE fromNode='RotorScript' fromField='stopEngine' toNode='Top' toField='stopTime'/> </ProtoBody> </ProtoDeclare> <Viewpoint description='Example16' position='0 0 5'/> <NavigationInfo type='"EXAMINE ANY"'/> <Group> <ProtoInstance DEF='MikesChopper' name='Chopper'/> </Group> </Scene> </X3D>
Click here to view this example in a 3D scene window.
X3D provides control of the viewer's camera through use of a script. This is useful for things such as guided tours, merry-go-round rides, and transportation devices such as buses and elevators. These next two examples show a couple of ways to use this feature.
This example is a simple guided tour through the world. Upon entry, a guide orb hovers in front of the viewer. Click on this and a tour through the world begins. The orb follows the user around on his tour. A ProximitySensor ensures that the tour is started only if the user is close to the initial starting point. Note that this is done without scripts thanks to the touchTime output of the TouchSensor.
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd"> <X3D version='3.0' profile='Interactive'> <head> <meta name='filename' content='GuidedTour.x3d'/> </head> <Scene> <Group> <Transform translation='0.0 -1.0 0.0'> <Shape> <Box size='30.0 0.2 30.0'/> <Appearance> <Material/> </Appearance> </Shape> </Transform> <Transform translation='-1.0 0.0 0.0'> <Shape> <Cone/> <Appearance> <Material diffuseColor='0.5 0.8 0.0'/> </Appearance> </Shape> </Transform> <Transform translation='1.0 0.0 0.0'> <Shape> <Cylinder/> <Appearance> <Material diffuseColor='0.0 0.2 0.7'/> </Appearance> </Shape> </Transform> <Transform DEF='GuideTransform'> <Viewpoint DEF='TourGuide' jump='false' description='Tour Guide'/> <ProximitySensor DEF='ProxSensor' size='50.0 50.0 50.0'/> <TouchSensor DEF='StartTour' description='Touch to start tour'/> <Transform translation='0.6 0.4 8.0'> <Shape> <Sphere radius='0.2'/> <Appearance> <Material diffuseColor='1.0 0.6 0.0'/> </Appearance> </Shape> </Transform> </Transform> </Group> <PositionInterpolator DEF='GuidePI' keyValue='0.0 0.0 0.0, 0.0 0.0 -5.0, 2.0 0.0 -5.0, 2.0 6.0 -15.0, -4.0 6.0 -15.0, -4.0 0.0 -5.0, 0.0 0.0 -5.0, 0.0 0.0 0.0' key='0.0 0.2 0.3 0.5 0.6 0.8 0.9 1.0'/> <OrientationInterpolator DEF='GuideRI' keyValue='0.0 1.0 0.0 0.0, 0.0 1.0 0.0 0.0, 0.0 1.0 0.0 1.2, 0.0 1.0 0.0 3.0, 0.0 1.0 0.0 3.5, 0.0 1.0 0.0 5.0, 0.0 1.0 0.0 0.0, 0.0 1.0 0.0 0.0' key='0.0 0.2 0.3 0.5 0.6 0.8 0.9 1.0'/> <TimeSensor DEF='TS' cycleInterval='30.0'/> <ROUTE fromNode='ProxSensor' fromField='isActive' toNode='StartTour' toField='enabled'/> <ROUTE fromNode='StartTour' fromField='touchTime' toNode='TS' toField='startTime'/> <ROUTE fromNode='TS' fromField='isActive' toNode='TourGuide' toField='set_bind'/> <ROUTE fromNode='TS' fromField='fraction_changed' toNode='GuidePI' toField='set_fraction'/> <ROUTE fromNode='TS' fromField='fraction_changed' toNode='GuideRI' toField='set_fraction'/> <ROUTE fromNode='GuidePI' fromField='value_changed' toNode='GuideTransform' toField='translation'/> <ROUTE fromNode='GuideRI' fromField='value_changed' toNode='GuideTransform' toField='rotation'/> </Scene> </X3D>
Click here to view this example in a 3D scene window.
This is another example of animating the camera by depicting an elevator to ease access to a multi-storey building. For this example, a 2 storey building is shown and it is assumed that the elevator is already at the ground floor. To go up, the user just steps onto the elevator platform. A ProximitySensor fires and starts the elevator up automatically. Additional features such as call buttons for outside the elevator, elevator doors, and floor selector buttons could be added to make the elevator easier to use.
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd"> <X3D version='3.0' profile='Interactive'> <head> <meta name='filename' content='Elevator.x3d'/> </head> <Scene> <Transform translation='0.0 0.0 -3.5'> <Shape> <Cone/> <Appearance> <Material diffuseColor='0.0 1.0 0.0'/> </Appearance> </Shape> </Transform> <Transform translation='0.0 4.0 -3.5'> <Shape> <Cone/> <Appearance> <Material diffuseColor='1.0 0.0 0.0'/> </Appearance> </Shape> </Transform> <Transform translation='0.0 8.0 -3.5'> <Shape> <Cone/> <Appearance> <Material diffuseColor='0.0 0.0 1.0'/> </Appearance> </Shape> </Transform> <Group> <Transform DEF='ETransform'> <Viewpoint DEF='EViewpoint' description='Elevator Viewpoint' centerOfRotation='0 0 0' jump='false'/> <ProximitySensor DEF='EProximity' size='2.0 5.0 5.0'/> <Transform translation='0.0 -1.0 0.0'> <Shape> <Box size='2.0 0.2 5.0'/> <Appearance> <Material/> </Appearance> </Shape> </Transform> </Transform> </Group> <PositionInterpolator DEF='ElevatorPI' keyValue=' 0.0 0.0 0.0, 0.0 8.0 0.0' key=' 0.0 1.0'/> <TimeSensor DEF='TS' cycleInterval='10.0'/> <ROUTE fromNode='EProximity' fromField='enterTime' toNode='TS' toField='startTime'/> <ROUTE fromNode='TS' fromField='isActive' toNode='EViewpoint' toField='set_bind'/> <ROUTE fromNode='TS' fromField='fraction_changed' toNode='ElevatorPI' toField='set_fraction'/> <ROUTE fromNode='ElevatorPI' fromField='value_changed' toNode='ETransform' toField='translation'/> </Scene> </X3D>
Click here to view this example in a 3D scene window.
This example illustrates the execution model example described in 4.10.3, Execution model in Part 1 of ISO/IEC 19775.
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "http://www.web3d.org/specifications/x3d-3.0.dtd"> <X3D version='3.0' profile='Immersive'> <head> <meta name='filename' content='ExecutionModel.x3d'/> </head> <Scene> <TouchSensor DEF='TS'/> <Script DEF='Script1'> <field name='touchTime' type='SFTime' accessType='inputOnly'/> <field name='toScript2' type='SFBool' accessType='outputOnly'/> <field name='toScript3' type='SFBool' accessType='outputOnly'/> <field name='string' type='SFString' accessType='outputOnly'/> <![CDATA[ ecmascript: function touchTime() { toScript2 = true; } function eventsProcessed() { string = 'Script1.eventsProcessed'; toScript3 = true; } ]]> </Script> <Script DEF='Script2'> <field name='fromScript1' type='SFBool' accessType='inputOnly'/> <field name='toScript4' type='SFBool' accessType='outputOnly'/> <field name='string' type='SFString' accessType='outputOnly'/> <![CDATA[ ecmascript: function fromScript1() { } function eventsProcessed() { string = 'Script2.eventsProcessed'; toScript4 = true; } ]]> </Script> <Script DEF='Script3'> <field name='fromScript1' type='SFBool' accessType='inputOnly'/> <field name='toScript5' type='SFBool' accessType='outputOnly'/> <field name='toScript6' type='SFBool' accessType='outputOnly'/> <field name='string' type='SFString' accessType='outputOnly'/> <![CDATA[ ecmascript: function fromScript1() { toScript5 = true; } function eventsProcessed() { string = 'Script3.eventsProcessed'; toScript6 = true; } ]]> </Script> <Script DEF='Script4'> <field name='fromScript2' type='SFBool' accessType='inputOnly'/> <![CDATA[ ecmascript: function fromScript2() { } ]]> </Script> <Script DEF='Script5'> <field name='fromScript3' type='SFBool' accessType='inputOnly'/> <![CDATA[ ecmascript: function fromScript3() { } ]]> </Script> <Script DEF='Script6'> <field name='fromScript3' type='SFBool' accessType='inputOnly'/> <field name='toScript7' type='SFBool' accessType='outputOnly'/> <field name='string' type='SFString' accessType='outputOnly'/> <![CDATA[ ecmascript: function fromScript3() { toScript7 = true; } function eventsProcessed() { string = 'Script6.eventsProcessed'; } ]]> </Script> <Script DEF='Script7'> <field name='fromScript6' type='SFBool' accessType='inputOnly'/> <![CDATA[ ecmascript: function fromScript6 () { } ]]> </Script><!--Display the results--> <Script DEF='Collector'> <field name='string' type='MFString' accessType='outputOnly'/> <field name='fromString' type='SFString' accessType='inputOnly'/> <![CDATA[ ecmascript: function initialize() { string[0] = 'Event Sequence:'; } function fromString(s) { i = string.length; string[i] = ''+i+') '+s+' occurred'; } ]]> </Script> <Transform translation='0 2 0'> <Shape> <Appearance> <Material diffuseColor='0 0.6 0'/> </Appearance> <Sphere/> </Shape> </Transform> <Shape> <Text DEF='Result'/> </Shape> <Viewpoint position='7 -1 18'/> <ROUTE fromNode='TS' fromField='touchTime' toNode='Script1' toField='touchTime'/> <ROUTE fromNode='Script1' fromField='toScript2' toNode='Script2' toField='fromScript1'/> <ROUTE fromNode='Script1' fromField='toScript3' toNode='Script3' toField='fromScript1'/> <ROUTE fromNode='Script2' fromField='toScript4' toNode='Script4' toField='fromScript2'/> <ROUTE fromNode='Script3' fromField='toScript5' toNode='Script5' toField='fromScript3'/> <ROUTE fromNode='Script3' fromField='toScript6' toNode='Script6' toField='fromScript3'/> <ROUTE fromNode='Script6' fromField='toScript7' toNode='Script7' toField='fromScript6'/> <ROUTE fromNode='Script1' fromField='string' toNode='Collector' toField='fromString'/> <ROUTE fromNode='Script2' fromField='string' toNode='Collector' toField='fromString'/> <ROUTE fromNode='Script3' fromField='string' toNode='Collector' toField='fromString'/> <ROUTE fromField='string' fromNode='Script6' toNode='Collector' toField='fromString'/> <ROUTE fromNode='Collector' fromField='string' toNode='Result' toField='string'/> </Scene> </X3D>
Click here to view this example in a 3D scene window.
Clicking on the green sphere should display a text string for each eventsProcessed event. The two possible correct displays for this example are:
Event Sequence: 1) Script1.eventsProcessed occurred 2) Script2.eventsProcessed occurred 3) Script3.eventsProcessed occurred 4) Script6.eventsProcessed occurred
or
Event Sequence: 1) Script2.eventsProcessed occurred 2) Script1.eventsProcessed occurred 3) Script3.eventsProcessed occurred 4) Script6.eventsProcessed occurred