Skip to content

The Basics of XML3D

lachsen edited this page Feb 28, 2013 · 25 revisions

Introduction

This is a tutorial that leads you through the basics of XML3D. What we will cover:

  • 3D geometry
  • Viewports
  • Transform Hierarchy
  • Surface appearance
  • Light sources

Requirements of this tutorial:

  • Basic understanding of HTML, CSS and JavaScript

Provide correct XHTML

XML3D via xml3d.js currently only works in XHTML documents. So the first step is to make sure you provide correct XHTML:

  • Start your web document with <?xml version="1.0" encoding="UTF-8"?>, followed by <html xmlns="http://www.w3.org/1999/xhtml">
  • For static files: use the .xhtml file extension
  • For dynamic files created by a server: send the files with the MIME-type application/xhtml+xml

First steps

XML3D is an extension to HTML. Just as you write HTML for text and images like so:

<p>
   This is some generic paragraph <span>with a twist</span>
   <img src="yayColors.png" alt="and an image" />
</p>

You can write XML3D for 3D content:

<p>Following this paragraphs we will break the second dimension!</p>
<xml3d xmlns="http://www.xml3d.org/2009/xml3d" >
   <mesh src="yayVertices.xml" />
</xml3d>
<p>... did you see it?</p>

About XML3D inside of XHTML:

  1. All XML3D elements inside of XHTML use the http://www.xml3d.org/2009/xml3d namespace
  2. All 3D content is declared inside an <xml3d> element, which defines the canvas through which the 3D scene is displayed.
  3. The <xml3d> element is displayed as an inline-block element like <canvas> and can be styled exactly the same way.

Displaying our first mesh

We have already established, that all our 3D content is placed inside an <xml3d> element, so let's start with that:

<xml3d xmlns="http://www.xml3d.org/2009/xml3d" >
  <!-- Incomming 3D! -->
</xml3d>

To add some 3D geometry to our scene, we use the <mesh> element. Just as with <img>, the <mesh> element links an external file containing the 3D geometry data. Here is one of these files for the good ol' teapot: teapot.json

Including the mesh is now fairly simple:

<xml3d xmlns="http://www.xml3d.org/2009/xml3d" >
  <mesh src="resource/teapot.json" />
</xml3d>

An this is what we get:

INSERT PICTURE

So where's the teapot? there is just a red square on the top!

Here is, where 3D get's a bit complicated: You teapot is there, it's just that it's scale and position relative to your viewpoint is rather badly chosen.

Why is that?

  • the XML3D viewpoint by default is set at the origin of 3D space (x=y=z=0), looking at direction (0,0, -1), so in negative z direction.
  • most meshes tend to be places around the origin as well

So consequently: our viewpoint is right next to the surface to the mesh.

Let's change the viewpoint to get some distance to the object. XML3D provides the <view> element to define the viewpoint of the scene:

<xml3d xmlns="http://www.xml3d.org/2009/xml3d" class="xml3d">
  <view position="0 0 100" />
  <mesh src="resource/teapot.xml#mesh" />
</xml3d>

Since our viewpoint looks into the direction (0,0,-1), we move along the z coordinate to get some distance, thus the new position (0,0,100).

Now we get this:

INSERT PICTURE

Now we start to recognize our teapot, but it's still a bit high up, not quite inside the center. We could now simplt move the viewpoint up a bit again. However, thanks to relativity, there is a second option: Let's move the mesh instead.

In order to move the mesh, we first have to wrap it inside a <group> element. The group element can enclose multiple <mesh> and other <group> elements and transform all of it's content.

To declare the transformation, we simply use CSS 3D Transformations :

<xml3d xmlns="http://www.xml3d.org/2009/xml3d" class="xml3d">
  <view position="0 0 100" />
  <group  style="transform: translate3d(0px,-20px, 0px)" >
    <mesh src="resource/teapot.xml#mesh" />
  </group>
</xml3d>

The declared transformation moves the teapot downwards, placing it nicely centered in the viewport:

INSERT IMAGE

Shading the teapot

You might have noticed: our teapot is actually just a red silhouette. We can expect more from 3D graphics. So let's change the shading of our 3D object. XML3D provides the <shader> element to define shaders. However, as you will see, we define <shader> not quite like other XML3D nodes. Here an example shader:

<shader id="orange" script="urn:xml3d:shader:flat">
</shader>

We specify a document id for our <shader> (just as we do with other HTML elements) and a script which specifies the behaviour or type of the shader. "urn:xml3d:shader:flat" is a predefined behavior that simply draws fills the element with the provided color.

So how do we specify the color for our new "orange" flat shader? We don't use any more attributes to further configure our <shader>. Instead, we place generic generic ValueElements, such as <float3> inside of <shader>:

<shader id="orange" script="urn:xml3d:shader:flat">
  <float3 name="diffuseColor" >1 0.5 0</float3>
</shader>

We added a ValueElement of type float3 (reads: 3 floating point numbers) with name diffuseColor and values 1, 0.5, and 0. The <shader> will evaluate the input provided by it's child ValueElements to shade as requested. Each float value is used as a color component of an RGB color.

The <shader> element is a generic DataContainer, just like several other XML3D elements. To understand why we choose this rather elaborate way of configuring your element, hava a look at Generic Data in XML3D.

Now we have our new shader! All that remains is connecting it with our <mesh>. We do this using the shader attribute of the <group>:

<xml3d xmlns="http://www.xml3d.org/2009/xml3d" class="xml3d">
  <shader id="orange" script="urn:xml3d:shader:flat">
    <float3 name="diffuseColor" >1 0.5 0</float3>
  </shader>

  <view position="0 0 100" />
  <group shader="#orange" style="transform: translate3d(0px,-20px, 0px)" >
    <mesh src="resource/teapot.xml#mesh" />
  </group>
</xml3d>

Note the # sign before orange: This is the syntax to refer an element of the same document via document id. Note that XML3D also allows us to refer shaders from external files e.g. shader="shader.xml#wood".

We finally got our newly shaded, orange teapot:

INSERT IMAGE

But wait... that's just a different silhouette! We wanted to get some decent shading with a 3D feel to it.

For that we need a different kind of shader: a phong shader.

<xml3d xmlns="http://www.xml3d.org/2009/xml3d" class="xml3d">
  <shader id="orangePhong" script="urn:xml3d:shader:phong">
    <float3 name="diffuseColor" >1 0.5 0</float3>
  </shader>

  <view position="0 0 100" />
  <group shader="#orangePhong" style="transform: translate3d(0px, -20px, 0px)" >
    <mesh src="resource/teapot.xml#mesh" />
  </group>
</xml3d>

So now we get...

INSERT IMAGE

...another silhouette! (Please bear with us)

What is missing this time around: The light source. Phong shading will only look interesting with a light source places somewhere inside the scene. We can, in fact, configure our phong shader to have some ambientIntensity, that will make the defined diffuseColor visible even without any light source:

  <shader id="orangePhong" script="urn:xml3d:shader:phong">
    <float3 name="diffuseColor" >1 0.5 0</float3>
    <float name="ambientIntensity" >0.5</float>
  </shader>

However, this will just result in differently colored silhouette:

INSERT IMAGE

So there is no way around, we have to add a light source. To add a light source, we need to define two elements: a <lightshader> and a <light>, which connects to the lightshader. There are different types of <lightshaders>. For now, let's only consider a directional light source:

<lightshader id="light1" script="urn:xml3d:lightshader:directional" >
  <float3 name="intensity" >1 1 1</float3>
</lightshader>

The <lightshader> is similar to <shader> in that is also accepts a script (here referring to a urn) and is itself a generic DataContainer. For directional lightsources, we can specify an intensity value with a <float3> (each float is the intensity of a channel from an RGB color).

Now we add the <light> element that will refer our new <lightshader>. The final scene looks like this:

<xml3d xmlns="http://www.xml3d.org/2009/xml3d" class="xml3d">
  <shader id="orangePhong" script="urn:xml3d:shader:phong">
    <float3 name="diffuseColor" >1 0.5 0</float3>
    <float name="ambientIntensity" >0.5</float>
  </shader>

  <lightshader id="light1" script="urn:xml3d:lightshader:directional" >
    <float3 name="intensity" >1 1 1</float3>
  </lightshader>

  <light shader="#light1" />

  <view position="0 0 100" />
  <group shader="#orangePhong" style="transform: translate3d(0px,-20px,0px)" >
    <mesh src="resource/teapot.json" />
  </group>
</xml3d>

And finally we get our nicely shaded teapot:

INSERT IMAGE

This almost concludes our tutorial about the basics of XML3D.

As a last step, how about you add the following script to your document:

<script src="http://www.xml3d.org/xml3d/script/tools/camera.js"></script>

This will allow you to rotate and scale the camera around the teapot by clicking and dragging with the left or right mouse button over the visible 3D scene.

Now you can inspect your nicely shaded teapot from all angles!

Further readings

Clone this wiki locally