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

Adding nice shading <view>

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.

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>

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

Let's make a tree of meshes: <group> and <transform>

TODO: Write section

Enough with those monotone colors: <light> and <shader>

TODO: Write section

Clone this wiki locally