Interactive 3D Viewer Written in SVG

Keywords: 3D, viewer, ECMAScript

Cemile B. Otkunc
Software Developer
Schema Software Inc.
Vancouver
British Columbia
Canada
bukeo@schemasoft.com
http://www.schemasoft.com

Biography

Buke Otkunc graduated with honors from Istanbul Technical University, Turkey with a B.Sc. in Control and Computer Engineering. After a year of industry experience she continued her academic studies at the University of British Columbia to receive her M.A.Sc. degree in Electrical and Computer Engineering. The focus of her Masters work was on real-time operating systems. She has been employed as a software developer with Schema Software Inc. in Vancouver BC for the last three years. Among many other tasks she had in this position, Buke was involved in a project for converting a presentation file format to SVG.

Philip A. Mansfield, Ph.D.
President
Schema Software Inc.
Vancouver
British Columbia
Canada
philipm@schemasoft.com
http://www.schemasoft.com

Biography

After receiving his Ph.D. in Mathematical Physics from Yale University in 1989, Philip spent a year as Assistant Professor of Physics at Knox College, followed by four years as Assistant Professor of Mathematics at the University of Toronto. His background in Differential Geometry and in computer modelling of physical phenomena served as unorthodox preparation for his subsequent move into industry as a Software Engineer with an emphasis on Computer Graphics. By 1997 Philip was in charge of a software research team creating early Web technologies based on HTML, XML, CSS and Java. Philip now lives and works in Vancouver, Canada, where he is President of SchemaSoft (http://www.schemasoft.com/), a software development consulting company he co-founded in 1999. He is an Advisory Committee Representative of the World Wide Web Consortium (http://www.w3.org/), and has been a member of the W3C Scalable Vector Graphics Working Group (http://www.w3.org/Graphics/SVG/) since its inception in 1998. Philip is Chair of the BC Advanced Systems Institute International Scientific Advisory Board (http://www.asi.bc.ca/). He is also a Director of the Vancouver XML Developers Association (http://www.vanx.org/), an organization that he co-founded in 2000. He regularly writes and lectures on topics related to software engineering, XML and SVG.


Abstract


In order to represent the real world on our computer screens, we must make use of three-dimensional modelling techniques. Even though SVG has been defined as a language for describing two-dimensional graphics, this paper will show that SVG is powerful enough to be used in a 3D application. In particular, we will present Aquila, a 3D interactive viewer prototype implemented in SVG and ECMAScript. Just as SVG is becoming a very versatile tool on the web for displaying 2D vector graphics images, Aquila carries the SVG to the next level: displaying interactive 3D vector graphics. Aquila constructs and modifies SVG DOM nodes on the fly in response to user feedback. The presentation will cover software design, technology choices, and functionality. It will be supported with demonstrations and illustrative examples.


Table of Contents


1. Motivation
     1.1 Viewing 3D on the Web
     1.2 Using SVG and ECMAScript for Displaying 3D Data
     1.3 Using XML to Store 3D Data
2. Features of the Prototype
     2.1 Requirements from an Interactive 3D Viewer
     2.2 Represent 3D Data
     2.3 Transform 3D Data
         2.3.1 Projection Method
         2.3.2 Lighting Model
         2.3.3 Visible Surface Detection
     2.4 Store 2D Views
     2.5 Provide UI
     2.6 Change 2D View
3. Enhancements to the Viewer
     3.1 Gouraud Shading
4. Conclusion
5. Further Work
Bibliography

1. Motivation

1.1 Viewing 3D on the Web

Viewers and file formats that have been developed for the Web have been mainly applicable to 2D. This non-3D content is in contrast with what we experience in the real world. Importance of viewing 3D on the Internet has shown itself with the emerging standards such as VRML [VRML] and X3D [X3D] . However, there has not been a natively supported 3D viewer available to Web users.

1.2 Using SVG and ECMAScript for Displaying 3D Data

It is possible to create and view 3D images using CAD and 3D design applications. However, these applications support proprietary formats. Thus, it is not possible to view these images on our browsers unless they are converted to a bitmap image format. With the use of SVG and ECMAScript [ECMA] we can view non-proprietary 3D data stored in XML format on any SVG enabled browser.

1.3 Using XML to Store 3D Data

SVG is an XML format, therefore the use of XML for storing the 3D data is a natural choice. Some modelling tools such as AutoCAD now have functionality to save user-created 3D images as XML. XML data can be stored in memory as DOM nodes that can be manipulated using ECMAScript.

2. Features of the Prototype

2.1 Requirements from an Interactive 3D Viewer

The 3D viewing process is more complicated than the 2D viewing process. The complexity arises from the third spatial dimension, the depth, to be emulated in the 2D space of our displays. Fortunately, the series of steps used in a 3D viewing process have already been defined by scientists. Describing the theory behind 3D graphics and the methods that are used is beyond the scope of this paper. However, describing the basic requirements from a 3D viewer is appropriate, as it helps to clarify the expectations from such a 3D viewer. In order to claim to have a 3D viewer, one must meet these basic requirements:

  1. Store a 3D representation of the scene being modelled, including objects and lighting conditions
  2. Store a 2D view of the 3D model under specified viewing conditions
  3. Provide UI for altering the viewing conditions
  4. Change the 2D view in response to changing viewing conditions

The parts of the viewer that implement the requirements listed above are described in the following subsections.

2.2 Represent 3D Data

An important part of a 3D viewer is providing a format for defining and storing 3D objects. We introduce the world3D XML grammar for representing 3D data. world3D XML grammar is similar to the X3D standard but much simpler and therefore more appropriate for illustrative purposes. world3D can encode a scene of multiple polyhedra illuminated by a light source of any colour and position viewed from any viewpoint and orientation. A polyhedron is a 3 dimensional shape, which consists of faces that are defined by polygons.

The XML Schema for world3D format can be seen in Figure 1 below.

<?xml version="1.0" encoding="UTF-8"?>
<schema targetNamespace="world3D.xsd" xmlns:poly="world3D.xsd" xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
  <element name="polyhedron">
    <complexType>
      <sequence>
        <element name="viewPlane">
          <complexType>
            <sequence>
              <element name="vector" type="poly:vectorType"/>
              <element name="vector" type="poly:vectorType"/>
            </sequence>
            <attribute name="zoom" type="decimal" default="1"/>
            <attribute name="originX" type="decimal" default="0"/>
            <attribute name="originY" type="decimal" default="0"/>
          </complexType>
        </element>
        <element name="lightSource">
          <complexType>
            <sequence>
              <element name="vector" type="poly:vectorType"/>
              <element name="color" type="poly:colorType"/>
            </sequence>
          </complexType>
        </element>
        <element name="edge">
          <complexType>
            <sequence>
              <element name="color" type="poly:colorType"/>
            </sequence>
            <attribute name="show" type="boolean" default="false"/>
          </complexType>
        </element>
        <element name="faces">
          <complexType>
            <sequence minOccurs="0" maxOccurs="unbounded">
              <element name="face">
                <complexType>
                  <sequence>
                    <element name="vector" type="poly:vectorType"/>
                    <element name="vector" type="poly:vectorType"/>
                    <element name="vector" type="poly:vectorType"/>
                    <element name="vector" type="poly:vectorType"/>
                  </sequence>
                </complexType>
              </element>
            </sequence>
          </complexType>
        </element>
      </sequence>
    </complexType>
  </element>
  <complexType name="vectorType">
    <attribute name="x" type="decimal" use="required"/>
    <attribute name="y" type="decimal" use="required"/>
    <attribute name="z" type="decimal" use="required"/>
  </complexType>
  <complexType name="colorType">
    <attribute name="red" type="unsignedByte" use="required"/>
    <attribute name="green" type="unsignedByte" use="required"/>
    <attribute name="blue" type="unsignedByte" use="required"/>
  </complexType>
</schema>

Figure 1: XML Schema for world3D Format

Description of world3D XML Grammar Elements
<faces>
Faces element consists of a collection of polygonal faces for representing 3D objects. Each face is defined as a collection of (x, y, z) coordinate vectors representing vertices of polygons.
<viewPlane>
View plane is defined by two unit vectors, each one representing x and y axes of the view plane. View model is parallel projection in the direction of the normal of the view plane.
<lightSource>
LightSource element consists of a light vector for representing the direction of parallel rays of light illuminating the 3D object. Light source includes a light color which is used for calculating the color of a face depending on the intersection angle between the light ray and the face.
<edge>
Edge element is used to define a separate edge color to reveal edges more clearly.

Figure 2 shows a sample 3D cube definition with world3D.

<?xml version="1.0" encoding="UTF-8"?>
<world3D
  xmlns="http://www.schemasoft.com/schema/polyhedron.xsd"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.schemasoft.com/schema/polyhedron.xsd
  polyhedron.xsd">
  <viewPlane zoom="187.1" originX="250" originY="200">
    <vector x="-0.5774" y="0.5774" z="-0.5774"/>
    <vector x="-0.7715" y="-0.1543" z="0.6172"/>
  </viewPlane>
  <lightSource>
    <vector x="0.2673" y="0.8018" z="0.5345"/>
    <color red="255" green="0" blue="255"/>
  </lightSource>
  <edge show="true">
    <color red="0" green="0" blue="255"/>
  </edge>
  <faces>
    <face>
      <vector x="0" y="0" z="0"/>
      <vector x="0" y="1" z="0"/>
      <vector x="1" y="1" z="0"/>
      <vector x="1" y="0" z="0"/>
    </face>
    <face>
      <vector x="0" y="0" z="0"/>
      <vector x="0" y="0" z="1"/>
      <vector x="0" y="1" z="1"/>
      <vector x="0" y="1" z="0"/>
    </face>
    <face>
      <vector x="0" y="0" z="0"/>
      <vector x="1" y="0" z="0"/>
      <vector x="1" y="0" z="1"/>
      <vector x="0" y="0" z="1"/>
    </face>
    <face>
      <vector x="0" y="0" z="1"/>
      <vector x="1" y="0" z="1"/>
      <vector x="1" y="1" z="1"/>
      <vector x="0" y="1" z="1"/>
    </face>
    <face>
      <vector x="1" y="0" z="0"/>
      <vector x="1" y="1" z="0"/>
      <vector x="1" y="1" z="1"/>
      <vector x="1" y="0" z="1"/>
    </face>
    <face>
      <vector x="0" y="1" z="0"/>
      <vector x="0" y="1" z="1"/>
      <vector x="1" y="1" z="1"/>
      <vector x="1" y="1" z="0"/>
    </face>
  </faces>
</world3D>

Figure 2: Sample world3D XML: 3D Cube

2.3 Transform 3D Data

One of the main tasks of a 3D viewer is converting the object, which is represented in real world coordinates, into a 2 coordinate system. This is done through a projection method. A projection method is based on a virtual camera placed at an arbitrary position around the object. The 2D view of the object is a photograph of the real world that camera takes.

In addition to projecting faces, it is also necessary to determine whether a face is visible by the observer. This information is used to remove faces that do not need to be processed by the viewer. Hidden surface removal enables to display only the faces that are visible to the observer.

Another important expectation from a 3D viewer is the ability to represent a lighting model. Applying a lighting model to the 2D view of the object enhances the real-world look and feel of the object. A lighting model is represented with different colors applied to the different parts of the object. The choice of color is based on how much the face is illuminated.

Aquila uses ECMAScript for all the calculations required for the transformations.

The transformation models and methods that we have chosen are described in the following subsections.

2.3.1 Projection Method

In order to represent 3D points in SVG format we need to use a 3D to 2D planar projection method. For this prototype we chose the oblique projection [COMP97] , [COMP90] method. Oblique projection is a form of parallel projection in which the projectors are parallel to each other but are not perpendicular to the projection plane.

2.3.2 Lighting Model

A great way to enhance the viewing of objects in 3D is through the use of a lighting model. For this prototype we chose a free directional lighting [COMP97] , [COMP90] model. This model represents a global type of light, which is considered to be infinitely far away. The direction of the light is used to determine the angle at which the light intersects with a surface. If the surface is perpendicular to the light rays it will be rendered brightest. The more oblique the surface to the light rays the less it is illuminated.

2.3.3 Visible Surface Detection

Those surfaces on a 3D object that are not visible by the observer need not be rendered by the viewer. Detecting and removing invisible surfaces reduces from the rendering time. Our viewer uses back face culling [COMP97] , [COMP90] method for eliminating invisible faces. In this method if the normal of a surface is pointing away from the observer (i.e. the normal of the projection plane) then the face is hidden and should not be rendered.

2.4 Store 2D Views

After 3D data is transformed the 2D data is stored as SVG. ECMAScript modifies the SVG nodes, for creating the SVG representation of the 3D image, using SVG DOM implementation.

Figure 3 shows the 3D cube, which was described in Figure 2 , rendered in SVG. SVG code for the same image can be found in Figure 4 .

cube.svg

Figure 3: Sample Cube Rendered as SVG

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="-600 -600 1200 1200"
     xmlns="http://www.w3.org/2000/svg" version="1.1">
    <desc>View cube.xml as svg</desc>
    <defs>
        <marker id="ArrowHead"
                viewBox="0 0 10 10" refX="0" refY="5" 
                markerUnits="strokeWidth"
                markerWidth="8" markerHeight="6"
                orient="auto">
                <path d="M 0 0 L 10 5 L 0 10 z" />
        </marker>
    </defs>
    <g id="Background">
        <rect x="-600" y="-600" width="1200" height="1200" fill="#F0F0E0" stroke="none"/>
    </g>
    <g id="CoordinateAxes" transform="scale(1,-1)">
        <path fill="none" stroke="#000000" stroke-width="1" marker-end="url(#ArrowHead)" d="M 250 200 L 33.93691 -88.695299"/>
  <text fill="red" font-size="20pt" x="33.93691" y="-88.695299" transform="translate(33.93691,-88.695299) scale(1,-1) translate(-33.93691,88.695299)">x</text>
        <path fill="none" stroke="#000000" stroke-width="1" marker-end="url(#ArrowHead)" d="M 250 200 L 466.06308 142.26094"/>
  <text fill="red" font-size="20pt" x="466.06308" y="142.26094" transform="translate(466.06308,142.26094) scale(1,-1) translate(-466.06308,-142.26094)">y</text>
        <path fill="none" stroke="#000000" stroke-width="1" marker-end="url(#ArrowHead)" d="M 250 200 L 33.93691 430.95624"/>     
  <text fill="red" font-size="20pt" x="33.93691" y="430.95624" transform="translate(33.93691,430.95624) scale(1,-1) translate(-33.93691,-430.95624)">z</text>
    </g>
    <g id="ThreeDimensionalShape" transform="scale(1,-1)">
        <polygon fill="none" stroke="none" points="250,200 358.03154,171.13047 250,26.782820 141.96846,55.65235"/>
        <polygon fill="none" stroke="none" points="250,200 141.96846,315.47812 250,286.60859 358.03154,171.13047"/>
        <polygon fill="none" stroke="none" points="250,200 141.96846,55.65235 33.93691,171.13047 141.96846,315.47812"/>
        <polygon fill="#880088" stroke-width="2" stroke-linejoin="bevel" stroke="#0000ff" points="141.96846,315.47812 33.93691,171.13047 141.96846,142.26094 250,286.60859"/>
        <polygon fill="#440044" stroke-width="2" stroke-linejoin="bevel" stroke="#0000ff" points="141.96846,55.65235 250,26.782820 141.96846,142.26094 33.93691,171.13047"/>
        <polygon fill="#CC00CC" stroke-width="2" stroke-linejoin="bevel" stroke="#0000ff" points="358.03154,171.13047 250,286.60859 141.96846,142.26094 250,26.782820"/>
    </g>
</svg>

Figure 4: Sample Cube SVG

In this example, the SVG group element with the id "ThreeDimensionalShape" represents the shape. Each polygon element corresponds to one projected face of the cube. The fill attribute values are calculated using the free directional lighting model. The polygons with fill and stroke attributes set as "none" are detected as invisible surfaces using the Back Face Culling method. The group element with the id "CoordinateAxis" is used for drawing 3 coordinate axis in order to assist in orientation within the SVG representation of the 3D image.

2.5 Provide UI

In real world we cannot see an object in full unless we go around it in every direction, or take it in our hand and rotate it. Similarly a 3D viewer cannot display all faces of a 3D object. For that reason, Aquila provides the ability to rotate image along the 3 axes and zoom. The user interface is created as SVG. User feedback is received as DOM events on SVG elements.

2.6 Change 2D View

Aquila provides the user with buttons for rotation and zooming. The mouse events are captured and the SVG nodes are modified with ECMAScript to reflect the changes that the user requested. ECMAScript handlers of DOM events modify DOM nodes in order to create the effect of a shifting view in response to user input on the view UI. Since SVG supports external script files, it is possible to separate the code completely from the world3D content, allowing the viewer code to be easily re-used on arbitrary world3D content.

3. Enhancements to the Viewer

SVG has a number of features that can be used to add to the realism of the 2D views. These can be listed as follows:

The use of Gouraud shading will be shown as an example in the following subsection.

3.1 Gouraud Shading

Free directional lighting model used for the viewer adds to our goal: attaining 3D realism. By adding shading effect to the model we can achieve smooth continuation between surfaces, thus approximate a curved surface look and feel. Such effect can be obtained with the use of an interpolated shading method. The shading information is linearly interpolated across a polygon from values determined for its vertices. Gouraud shading is one of these methods.

Simulation of Gouraud shading can be achieved by adding edge-perpendicular linear gradients using the SVG <feCompositve> arithmetic operator. As a demonstration, the following SVG file produces the shaded two faces shown below.

GouraudShading.svg

Figure 5: Gouraud Shading Example Rendered in SVG

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 4 7">
  <defs>
    <filter id="colorAdd">
      <feComposite in="SourceGraphic" in2="BackgroundImage" operator="arithmetic" k2="1" k3="1"/>
    </filter>
    <linearGradient id="grad1" x1="2" y1="0" x2="0" y2="5" gradientUnits="userSpaceOnUse">
      <stop offset="0" stop-color="#300030" stop-opacity="1"/>
      <stop offset="1" stop-color="#300030" stop-opacity="0"/>
    </linearGradient>
    <linearGradient id="grad2" x1="0" y1="2" x2="2" y2="3" gradientUnits="userSpaceOnUse">
      <stop offset="0" stop-color="#000000" stop-opacity="1"/>
      <stop offset="1" stop-color="#000000" stop-opacity="0"/>
    </linearGradient>
    <linearGradient id="grad3" x1="0" y1="5" x2="2" y2="0" gradientUnits="userSpaceOnUse">
      <stop offset="0" stop-color="#600060" stop-opacity="1"/>
      <stop offset="1" stop-color="#600060" stop-opacity="0"/>
    </linearGradient>
    <linearGradient id="grad4" x1="2" y1="3" x2="0" y2="2" gradientUnits="userSpaceOnUse">
      <stop offset="0" stop-color="#B000B0" stop-opacity="1"/>
      <stop offset="1" stop-color="#B000B0" stop-opacity="0"/>
    </linearGradient>

    <linearGradient id="grad5" x1="2" y1="0" x2="4" y2="5" gradientUnits="userSpaceOnUse">
      <stop offset="0" stop-color="#300030" stop-opacity="1"/>
      <stop offset="1" stop-color="#300030" stop-opacity="0"/>
    </linearGradient>
    <linearGradient id="grad6" x1="4" y1="2" x2="2" y2="3" gradientUnits="userSpaceOnUse">
      <stop offset="0" stop-color="#000000" stop-opacity="1"/>
      <stop offset="1" stop-color="#000000" stop-opacity="0"/>
    </linearGradient>
    <linearGradient id="grad7" x1="4" y1="5" x2="2" y2="0" gradientUnits="userSpaceOnUse">
      <stop offset="0" stop-color="#600060" stop-opacity="1"/>
      <stop offset="1" stop-color="#600060" stop-opacity="0"/>
    </linearGradient>
    <linearGradient id="grad8" x1="2" y1="3" x2="4" y2="2" gradientUnits="userSpaceOnUse">
      <stop offset="0" stop-color="#B000B0" stop-opacity="1"/>
      <stop offset="1" stop-color="#B000B0" stop-opacity="0"/>
    </linearGradient>

    <polygon id="chevronRight" points="2,0 4,2 4,5 2,3"/>
    <polygon id="chevronLeft" points="2,0 2,3 0,5 0,2"/>
  </defs>
  <use xlink:href="#chevronLeft" fill="url(#grad1)"/>
  <use xlink:href="#chevronLeft" fill="url(#grad2)" filter="url(#colorAdd)"/>
  <use xlink:href="#chevronLeft" fill="url(#grad3)" filter="url(#colorAdd)"/>
  <use xlink:href="#chevronLeft" fill="url(#grad4)" filter="url(#colorAdd)"/>

  <use xlink:href="#chevronRight" fill="url(#grad5)"/>
  <use xlink:href="#chevronRight" fill="url(#grad6)" filter="url(#colorAdd)"/>
  <use xlink:href="#chevronRight" fill="url(#grad7)" filter="url(#colorAdd)"/>
  <use xlink:href="#chevronRight" fill="url(#grad8)" filter="url(#colorAdd)"/>
</svg>

Figure 6: Gouraud Shading Example SVG Code

4. Conclusion

In order to view 3D object models on the Web a 3D viewer is required. Our creation of Aquila proves that SVG is suitable for viewing 3D object models. We have showed that via the scripting and DOM capabilities of SVG it is possible to implement such a viewer. Additionally, SVG provides features that are directly applicable for further enhancing such viewer. Among these features are gradients, filters and texture. By using SVG for viewing 3D models an easy to distribute XML compliant tool can be provided to the users of the Web.

5. Further Work

3D graphics is a rich topic in which many technological advances have been made. While Aquila demonstrates the principle of using SVG for a 3D application, there remain many opportunities to extend the 3D model, add to the features, specialize to specific use-cases and optimize the performance.

Bibliography

[COMP97]
Computer Graphics, J. D. Foley et al., Addison-Wesley, 1997.
[COMP90]
Computer Graphics Principles and Practice, J. D. Foley et al., Addison-Wesley, 1990.
[ECMA]
ECMAScript Language Specification, ECMA General Assembly, June 1997. Available at (http://www.el-mundo.es/internet/ecmascript.html)
[SVG]
Scalable Vector Graphics (SVG) 1.0 Specification, J. Ferraiolo, editor, W3C Recommendation, 4 September 2001. Available at (http://www.w3.org/TR/SVG)
[VRML]
Virtual Reality Modeling Language (VRML), International Standard ISO/IEC 14772-1:1997, VRML Consortium Incorporated, 1997. Available at (http://www.web3d.org/technicalinfo/specifications/vrml97/index.htm)
[X3D]
Extensible 3D Graphics (X3D). Available at (http://www.web3d.org/x3d.html)

XHTML rendition created by gcapaper Web Publisher v2.0, © 2001-3 Schema Software Inc.