Tutorial

This is a small tutorial on how to create an XML3D scene. It explains XML3D based on specification version 0.4, but also takes implementation specific issues into account. As XML3D is a web technology, a prerequisite for this tutorial is a basic understanding of fundamental web technologies such as HTML, CSS, DOM scripting and XML. If you are new to the subject we recommend visiting websites such as W3Schools first, before continuing with this tutorial.

Contents

Creating a Canvas

Example 1.1

Example 1.1

Though XML3D is meant as an extension to HTML5, currently only the XML encoding of HTML5 is supported by the implementations. Thus you have to be sure, that your browser interprets your content XML / XHTML encoded. This is straightforward for local files: Be sure that the extension is .xhtml. For files from a server you have to configure the server such that your XML3D files are sent using the MIME-Type application/xhtml+xml. Additionally you should start your XHTML file like this:

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" >
<html xmlns="http://www.w3.org/1999/xhtml">
...
</html>

Start an <xml3d> element wherever you want your 3D content to be shown:

<xml3d id="MyXml3d" style="width: 150px; height: 100px; border: 1px solid gray" xmlns="http://www.xml3d.org/2009/xml3d">
</xml3d>

This code will produce a rectangular rendering area (as seen in Example 1.1 ). It is important to declare the new namespace that is going to start, thus the implementations know that this is going to be interpreted as XML3D content. The <xml3d> can be styled just as any other box element in HTML. You can use CSS properties to set borders, margins, background etc. By default, the background is transparent and thus the 3D content is mixed with the underlying content. You can easily change this behavior using the CSS background properties.

Adding a Mesh

Example 2.1

Example 2.1

Use the <mesh> element to add geometry to the scene. The type attribute specifies, what kind of mesh is specified. Currently only triangle meshes are supported by the implementations, but this is planned to be changed in future versions.  The child elements of <mesh> are value elements, describing the data of the actual mesh. For triangles, the data is structured similarly to the Vertex Array structure of OpenGL. Here is an example for a simple one-triangle-mesh:

<xml3d id="MyXml3d" style="width: 150px; height: 100px; border: 1px solid gray"
 xmlns="http://www.xml3d.org/2009/xml3d">
  <mesh type="triangles">
    <int name="index">0 1 2</int>
    <float3 name="position">-1 -1 -5  1 -1 -5  0 1 -5</float3>
    <float3 name="normal">
      0 0 1
      0 0 1
      0 0 1
    </float3>
  </mesh>
</xml3d>
Example 2.2

Example 2.2

This mesh contains 3 value elements. Two <float3> elements for vertex positions and vertex normals and one <int> (integer) element describing the index of the mesh. Each index refers to all vertex value arrays (in this case position and normal), whereas 3 consecutive  indexes describe one triangle of the mesh. Make sure that the number of integer values of the index is a multiple of three! Note that the numbers in the value elements are separated by white-spaces only. No comma etc. The type and amount of white spaces hereby doesn’t matter.

Here is another example of an rectangular mesh, that also defines texture coordinates:

<xml3d id="MyXml3d" style="width: 150px; height: 100px; border: 1px solid gray"
 xmlns="http://www.xml3d.org/2009/xml3d">
  <mesh type="triangles">
    <int name="index">0 1 2  1 2 3</int>
    <float3 name="position">-1 -1 -5 1 -1 -5 -1 1 -5 1 1 -5</float3>
    <float3 name="normal">0 0 1  0 0 1  0 0 1 0 0 1</float3>
    <float2 name="texcoord">0.0 0.0 1.0 0.0 0.0 1.0 1.0 1.0</float2>
  </mesh>
</xml3d>

For a triangle mesh, index and position are both required. All other vertex attributes are optional, although most shaders will require normals and some others texcoords.

Definition Areas, Groups and Transformations

Example 3.1

Example 3.1

More complex scenes usually consists of multiple meshes that are placed in correct relation with transformations. In XML3D, this can be achieved by using the elements <group> and <transform>.

Before discussing these elements, however, we first have to mention the <defs> element.  Some of you might know the <defs> element from SVG. In XML3D it is basically the same thing — certain elements in xml3d such as <transform> are declared as resources that can be used once or multiple times by being referred from other elements. These elements belong into the <defs> section. The following code snipped shows a transformation that is declared inside a <defs> section:

<xml3d id="MyXml3d" style="width: 150px; height: 100px; border: 1px solid gray"
 xmlns="http://www.xml3d.org/2009/xml3d">
 <defs>
   <transform id="ex3_1_boxXfm" scale="1.5 0.5 1.0"  rotation="0 0 1 0.3" translation="-0.5 0 0"/>
 </defs>
 ...
</xml3d>

A transformation is declared by separately specifying scale, rotation, translation and other operations. To apply transformations on the geometry, we first have to put this geometry inside a group:

<xml3d id="MyXml3d" style="width: 150px; height: 100px; border: 1px solid gray"
 xmlns="http://www.xml3d.org/2009/xml3d">
  <defs>
    <transform id="ex3_1_boxXfm" scale="1.5 0.5 1.0"  rotation="0 0 1 0.3" translation="-0.5 0 0"/>
  </defs>

  <group style="-moz-transform: url(#ex3_1_boxXfm); transform: url(#ex3_1_boxXfm);" >
    <mesh type="triangles">
      <int name="index">0 1 2  1 2 3</int>
      <float3 name="position">-1 -1 -5 1 -1 -5 -1 1 -5 1 1 -5</float3>
      <float2 name="texcoord">0.0 0.0 1.0 0.0 0.0 1.0 1.0 1.0</float2>
    </mesh>
  </group>
</xml3d>

The transformation is assigned to the group node using the transform style property (or -moz-transform in RTfox). The transformation is applied to all meshes inside the group. Note that a group can contain another group with another transformation assigned to it. In this case the accumulated transformations of both groups are applied on the geometry. This way a transformation hierarchy can be build.

It’s possible to specify a transformation directly according to the CSS 3D Transforms specification. Currently,  however, using <transform>  is preferred because not all implementations have the CSS 3D Transforms implemented yet.

Shader

Example 4.1

Example 4.1

A shader can be specified using the <shader> element. Just like the <mesh> element, the <shader> can have arbitrary parameters. It also references to a script node via the script attribute. This script node contains the shader code to be used. XML3D comes with a set of fixed function standard shaders that have a predefined set of parameters. These shaders are referenced using a URN. Current implementations support only these fixed function shaders. In later version we will allow shader scripts using the AnySL system internally.

A shader can be assigned to a group using the shader property. Then all children will be rendered using that shader, unless the shader property gets overwritten by child groups. Here is an example how a Phong shader is specified and assigned to a group:

<xml3d id="MyXml3d" style="width: 150px; height: 100px; border: 1px solid gray"
 xmlns="http://www.xml3d.org/2009/xml3d">
  <defs>
    <shader id="ex4_1_redShader" script="urn:xml3d:shader:phong">
      <float3 name="diffuseColor">1.0 0.5 0.5</float3>
      <float name="ambientIntensity">1.0</float>
    </shader>
  </defs>
  <group style="shader: url(#ex4_1_redShader)">
    <mesh type="triangles">
      <int name="index">0 1 2  1 2 3</int>
      <float3 name="position">-1 -1 -5 1 -1 -5 -1 1 -5 1 1 -5</float3>
      <float2 name="texcoord">0.0 0.0 1.0 0.0 0.0 1.0 1.0 1.0</float2>
    </mesh>
  </group>
</xml3d>

Textures

Example 4.2

Example 4.2

Textures are just another shader parameter. Instead of a <float> or <float3> parameter just use a <texture> parameter. The texture element configures the access to the actual image (the so called sampler method). The actual image is defined as child of the texture element. These could be arbitrary HTML5 elements that are usable as texture. Currently only the <img> element is supported:

<xml3d id="MyXml3d" style="width: 150px; height: 100px; border: 1px solid gray"
 xmlns="http://www.xml3d.org/2009/xml3d">
  <defs>
    <shader id="ex4_2_texShader" script="urn:xml3d:shader:phong">
      <float3 name="diffuseColor">1.0 1.0 1.0</float3>
      <float name="ambientIntensity">1.0</float>
      <texture name="diffuseTexture" wrapS="repeat" wrapT="repeat">
        <img src="textures/Winter.jpg"/>
      </texture>
    </shader>
  </defs>
  <group style="shader: url(#ex4_2_texShader)" >
    <mesh type="triangles">
      <int name="index">0 1 2  1 2 3</int>
      <float3 name="position">-1 -1 -5 1 -1 -5 -1 1 -5 1 1 -5</float3>
      <float2 name="texcoord">0.0 0.0 1.0 0.0 0.0 1.0 1.0 1.0</float2>
    </mesh>
  </group>
</xml3d>

Lights

Example 5.1

Example 5.1

The <lightshader> element is utilized to define light shader instances describing light sources. Currently, the following standard light shader types are available:

  • PointLight – urn:xml3d:lightshader:point
  • SpotLight – urn:xml3d:lightshader:spot
  • DirectionalLight – urn:xml3d:lightshader:directional

Each light shader type has its own specific set of parameters which can be set within the corresponding definition. Such a definition can then be referenced by the <light> element.
The following examples show the definition of different light shader types with their corresponding possible parameters:

Example PointLight

 <lightshader id="myPointLight" script="urn:xml3d:lightshader:point">
   <float3 name="intensity">0.9 0.4 0.4</float3>
   <float3 name="attenuation">0 0 1</float3>
   <bool   name="castShadow">true</bool>
 </lightshader>

Example SpotLight

 <lightshader id="mySpotLight" script="urn:xml3d:lightshader:spot">
   <float3 name="intensity">0.9 0.4 0.4</float3>
   <float3 name="attenuation">0 0 1</float3>
   <float3 name="direction">0 1 0</float3>
   <float  name="beamWidth">45.0</float>
   <float  name="cutOffAngle">45.0</float>
   <bool   name="castShadow">true</bool>
 </lightshader>

And here is a scene using a point light shader with a light element to add a light source to the scene:

<xml3d id="MyXml3d" style="width: 150px; height: 100px; border: 1px solid gray"
 xmlns="http://www.xml3d.org/2009/xml3d">
  <defs>
    <lightshader id="ex5_1_lightShader" script="urn:xml3d:lightshader:point">
      <float3 name="intensity">0.9 0.6 0.3</float3>
      <float3 name="attenuation">0 0 1</float3>
      <bool   name="castShadow">true</bool>
    </lightshader>
    <transform id="ex5_1_lightXfm" translation="0 1.5 -4.5"/>
  </defs>
   <group style="-moz-transform: url(#ex5_1_lightXfm)" >
     <light style="shader: url(#ex5_1_lightShader)" intensity="2.0" />
   </group>
   <mesh type="triangles">
     <int name="index">0 1 2  1 2 3</int>
     <float3 name="position">-1 -1 -5 1 -1 -5 -1 1 -5 1 1 -5</float3>
     <float2 name="texcoord">0.0 0.0 1.0 0.0 0.0 1.0 1.0 1.0</float2>
   </mesh>
 </xml3d>

Data Reuse and Composition

Example 6.1

Example 6.1

In more complex 3D scenes it is common to have one piece of geometry replicated and placed at different position throughout the scene  (e.g. a wooden box in a storage room). Since declaring a mesh element with all value elements for every instance of a geometry would blow up the size of the document and increase memory consumption, XML3D allows the user to declare the data once and reuse it multiple times. This is done using the <data> element and the src attribute of the mesh:

<xml3d id="MyXml3d" style="width: 150px; height: 100px; border: 1px solid gray"
 xmlns="http://www.xml3d.org/2009/xml3d">
  <defs>
    <transform id="ex6_1_boxXfm1" translation="-1.5 0 0" />
    <transform id="ex6_1_boxXfm2" translation="1.5 0 0" />
    <data id="ex6_1_squareData" >
      <int name="index">0 1 2  1 2 3</int>
      <float3 name="position">-1 -1 -5 1 -1 -5 -1 1 -5 1 1 -5</float3>
      <float2 name="texcoord">0.0 0.0 1.0 0.0 0.0 1.0 1.0 1.0</float2>
    </data>
  </defs>
  <group style="-moz-transform: url(#ex6_1_boxXfm1); transform: url(#ex6_1_boxXfm1);">
    <mesh id="squareMesh1" type="triangles" src="#ex6_1_squareData" />
  </group>
  <group style="-moz-transform: url(#ex6_1_boxXfm2); transform: url(#ex6_1_boxXfm2);">
    <mesh id="squareMesh2" type="triangles" src="#ex6_1_squareData" />
  </group>
</xml3d>

The <data> element contains all value elements that would be put inside both of the <mesh> elements. The <mesh> elements on the other hand, just refer the <data> element with the src attribute to directly reuse the data.

The <data> element can also be used for more complex data composition tasks. Consider the following 3 shaders:

<shader id="ex6_2_shader1" script="urn:xml3d:shader:phong">
  <float3 name="diffuseColor">1.0 1.0 1.0</float3>
  <float name="ambientIntensity">1.0</float>
  <float3 name="emissiveColor">0 0 0</float3>
  <float3 name="specularColor">0.025 0.025 0.025</float3>
  <texture name="diffuseTexture" wrapS="repeat" wrapT="repeat">
    <img src="textures/Autumn.jpg"/>
  </texture>
</shader>

<shader id="ex6_2_shader2" script="urn:xml3d:shader:phong">
  <float3 name="diffuseColor">1.0 1.0 1.0</float3>
  <float name="ambientIntensity">1.0</float>
  <float3 name="emissiveColor">0 0 0</float3>
  <float3 name="specularColor">0.025 0.025 0.025</float3>
  <texture name="diffuseTexture" wrapS="repeat" wrapT="repeat">
    <img src="textures/Winter.jpg"/>
  </texture>
</shader>

<shader id="ex6_2_shader3" script="urn:xml3d:shader:phong">
  <float3 name="diffuseColor">1.0 1.0 1.0</float3>
  <float name="ambientIntensity">1.0</float>
  <float3 name="emissiveColor">0 0 0</float3>
  <float3 name="specularColor">0.1 0.1 0.1</float3>
  <texture name="diffuseTexture" wrapS="repeat" wrapT="repeat">
    <img src="textures/Spring.jpg"/>
  </texture>
</shader>

In this example, the shader attributes diffuseColor, ambientIntensity and emissiveColor are the same for all shaders. The attribute specularColor is the same for the first two shader as well. It is kind of redundant to specify those attribute for each and every shader (especially if we got even more than 3). Here we can, again, use the <data> element to declare common attributes only once and share them for multiple elements:

<data id="ex6_2_shaderDefault" >
  <float3 name="diffuseColor">1.0 1.0 1.0</float3>
  <float name="ambientIntensity">1.0</float>
  <float3 name="emissiveColor">0 0 0</float3>
  <float3 name="specularColor">0.025 0.025 0.025</float3>
</data>

<shader id="ex6_2_shader2" script="urn:xml3d:shader:phong">
  <data src="#ex6_2_shaderDefault" />
  <texture name="diffuseTexture" wrapS="repeat" wrapT="repeat">
    <img src="textures/Autumn.jpg"/>
  </texture>
</shader> 

<shader id="ex6_2_shader1" script="urn:xml3d:shader:phong">
  <data src="#ex6_2_shaderDefault" />
  <texture name="diffuseTexture" wrapS="repeat" wrapT="repeat">
    <img src="textures/Winter.jpg"/>
  </texture>
</shader>

<shader id="ex6_2_shader2" script="urn:xml3d:shader:phong">
  <data src="#ex6_2_shaderDefault" />
  <texture name="diffuseTexture" wrapS="repeat" wrapT="repeat">
    <img src="textures/Spring.jpg"/>
  </texture>
  <float3 name="specularColor">0.1 0.1 0.1</float3>
</shader>

Here the <data> elements contains the common shader attributes. The individual shaders include a <data> element that referes the <data> element with the common attributes. Additional attributes can still be declared with value elements inside the <shader> elements. Each shader adds its own diffuseTexture, while the third shader even declares it’s own specularColor, overriding the specularColor of the default <data> element.

Viewpoints

 TODO

Scene Modifications via DOM

All scene can be modified arbitrary via generic DOM access or via XML3D specific access.

Generic DOM access

All elements, their relations to each other, references, attributes, CSS properties and text content can be changed using the standard DOM methods. Example:

 <xml3d id="MyXml3d" style="width: 300px; height: 300px" xmlns="http://www.xml3d.org/2009/xml3d">
   <defs>
     <transform id="boxTransform" translation="-2 2 5.0" />
   </defs>
   <group style="transform: url(#boxTransform2);">
     <mesh type="triangles">
       ...
     </mesh>
   </group>
 </xml3d>
 <script type="text/javascript">
   function changeTranslation(id)
   {
     var transform = document.getElementById(id);
     transform.setAttribute("translation", "2 0 1");
   }
 </script>
 <button onclick="changeTranslation('boxTransform')">Move mesh</button>

XML3D specific access

Apart from the generic access, you can modify the scene via interfaces defined for every XML3D element. This is often more convenient and potentially faster than the generic way. In the specification you can find the element specific interfaces (often called IDLs).

 <xml3d id="MyXml3d" style="width: 300px; height: 300px" xmlns="http://www.xml3d.org/2009/xml3d">
   <defs>
     <transform id="boxTransform" translation="-2 2 5.0" />
   </defs>
   <group style="transform: url(#boxTransform2);">
     <mesh type="triangles">
       ...
     </mesh>
   </group>
 </xml3d>
 <script type="text/javascript">
   function moveMesh(id){
     var transform = document.getElementById(id);
     transform.translation.x += 0.1;
   }
 </script>
 <button onclick="moveMesh('boxTransform')">Move mesh</button>

Changing Generic Parameters

As the values of the generic parameters are stored as text value, it’s not as convenient to change them as the modification of attributes. The value can be distributed over several TextNodes. We will provide ways to easily change those parameters via a specific interface in a future version. Until then, just use the function org.xml3d.setParameter from our Script Collection.

 <xml3d id="MyXml3d" style="width: 300px; height: 300px" xmlns="http://www.xml3d.org/2009/xml3d">
   <defs>
     <shader id="redShader" script="urn:xml3d:shader:phong">
       <float3 name="diffuseColor">1.0 0.5 0.5</float3>
       <float name="ambientIntensity">0</float>
     </shader>
   </defs>
   <group style="shader: url(#redShader);">
     <mesh type="triangles">
       <int name="index">0 1 2 1 2 3</int>
       <float3 name="position">-1.0 -1.0 -10.0 1.0 -1.0 -10.0 -1.0  1.0 -10.0 1.0  1.0 -10.0</float3>
       <float3 name="normal">0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0</float3>
       <float2 name="texcoord">0.0 1.0 1.0 1.0 0.0 0.0 1.0 0.0</float2>
     </mesh>
   </group>
 </xml3d>
 <button onclick="org.xml3d.setParameter('redShader', 'diffuseColor', '1.0 1.0 0.0')">Make Yellow</button>

Animations

Animations that are preformed applying changes to the transformation hierarchy without changing the geometry itself, are called Rigid Body Animations. These changes can be done from within your application by modifying the DOM periodically via JavaScript (s. above). Currently there are several formats to describe animations declaratively, include i.e. SMIL. This is the reason, why there is no specific format for these animations in the XML3D spec. If you use CSS3 3D Transforms in your scene, you could use CSS3 Animations to animate your scene. There are some utilities to help you animate objects in the scene in our script collection (s. below).

Events

 TODO

XFlow (Vertex and Image Processing)

Data parallel computation via XFlow is planned for the Milestone 5 release and thus currently not available in the implementations.

Script collection

We collected some useful scripts that implement functionality you might miss in the XML3D spec. We omitted these features intentionally because

  • there are many ways to describe them and we don’t want to tie you to one specific way (s. Animations)
  • we want to keep the spec as small as possible
  • the functionality is easy to implement via JavaScript and not THAT performance-critical

Camera Controller

You can change the navigation behaviour with the “navigation”-tag (available in xml3d.js from version 0.4.6). Currently the modes “walk”, “examine” (default) and “none” are supported. In addition you can set the rotation/zoom speed using the “speed” attribute.

 <navigation mode="examine" speed="100" />

SMIL

 TODO