Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Public-Domain HTML 3D Library

4.99/5 (31 votes)
21 Apr 2017Public Domain17 min read 68.6K   1.6K  
A public domain JavaScript library for easing the development of HTML 3D applications

Introduction

Image 1

This page will introduce the HTML 3D Library, an open-source JavaScript library that I wrote.

This library contains classes and utility methods to ease the development of HTML 3D applications, such as Web sites, in browsers that support 3D drawing using the HTML5 Canvas.

The library differs from many others because this one is in the public domain, so no license is required to use it.

This page includes information on how to use the HTML 3D library, an overview of its features, and an example of a simple 3D-enabled Web page.

NOTE: This section and the rest of this page will largely discuss the 2.0.0-beta3 version of the HTML 3D library, which differs considerably from the current release (version 1.5.1) of the library. (See the section "History" for more information.)

How to Use

  1. Download the HTML 3D library.
  2. Extract the file "h3du_min.js", and write the following code in every HTML page where you will use the library.

    <code> <script type="text/javascript" src="h3du_min.js"></script></code>
  3. Include an HTML 3D canvas somewhere on the Web page, since drawing 3D objects requires a 3D canvas. You may set its width and height. You should also give it an ID so you can refer to it more easily in your JavaScript code, as shown in this example.

    <code> <canvas width="640" height="480" id="canvas"></canvas></code>
  4. To use the HTML 3D library in JavaScript, either add the JavaScript code to the bottom of the page or use an event listener, as in this example:

    <code> <script>
     window.addEventListener("load",function(){
       var scene=new Scene3D(document.getElementById("canvas"));
       // We have the 3D scene, use it. (See the example code
       // at the bottom of this article for a more complete example.)
     })
     </script></code>

List of Classes

This is an overview of most of the JavaScript classes available in this library:

The following classes concern themselves with the HTML 3D canvas context:

  • H3DU.Scene3D - Holds an HTML 3D canvas context (GL context).
  • H3DU.TextureLoader - Caches textures loaded by the application and maps them to GL contexts.

For much more information on all of these classes, see my documentation for the HTML 3D library.

The following sections detail how a 3D application using this library works.

H3DU.Scene3D

The H3DU.Scene3D class is a renderer for a canvas GL context. It renders batches of 3D shapes in the form of H3DU.Batch3D objects. Each Batch3D represents a so-called "scene graph". It holds 3D objects which will be drawn to the screen, as well as the camera's projection, the camera's position, and light sources to illuminate the 3D scene.

To create a H3DU.Scene3D, you first need to find the HTML canvas in your JavaScript, then you need to pass it to new Scene3D(). Once you do so, H3DU.Scene3D will use that canvas to draw 3D objects. Here is an example. You will also need to create a H3DU.Batch3D to hold 3D objects.

<code>// Find the HTML canvas with the ID "canvas".
var canvas=document.getElementById("canvas")
// Create a 3D scene using that canvas.
var scene=new H3DU.Scene3D(canvas);
var batch=new H3DU.Batch3D();</code>

The "Camera"

The H3DU.Batch3D class has a concept of a "projection transform" and a "view transform". If we use the concept of a "camera", the projection is like setting the camera's focus and lens, and the view transform is like setting its position and orientation. H3DU.Batch3D has methods for setting all these attributes of this abstract "camera". Two of them are perspectiveAspect() and setLookAt(), which are shown in the example below.

<code>// Set the perspective view. Camera has a 45-degree field of view
// and will see objects from 0.1 to 100 units away.
batch.perspectiveAspect(45,0.1,100);
// Move the camera back 40 units.
batch.setLookAt([0,0,40]);
// Move the camera back 30 units instead, and turn it so it
// points at (0, 2, 0), that is, up 2 units.
batch.setLookAt([0,0,30], [0,2,0]);</code>

For more information, see The "Camera" and Geometric Transforms.

3D Models

Every 3D scene is made up of "meshes", or the triangles, lines, and points that make up a geometric three-dimensional object. Meshes can be simple, such as a cube, or very complex, such as a town model complete with houses. You create a mesh using the H3DU.Mesh class, or create a built-in geometric shape using a method in the H3DU.Meshes class. The example below shows how you can create a box mesh:

<code>// Create a box mesh 10 units in width, 20 units
// in height, and 25 units in depth
var mesh=H3DU.Meshes.createBox(10,20,25);</code>

Here are some other built-in mesh methods. This page doesn't explain all the features or parameters in the Meshes class; for that, see the Meshes API documentation.

  • H3DU.Meshes.createSphere(radius)
    Creates a sphere with the given radius.
  • H3DU.Meshes.createCylinder(base, top, height)
    Creates a cylinder with the given base radius, top radius, and height. Can be used to create a cone if base or top is 0.
  • H3DU.Meshes.createClosedCylinder(base, top, height)
    Like createCylinder, except it also covers the base and top.
  • H3DU.Meshes.createPartialDisk(inner, outer, start, sweep)
    Creates a circular ring, of radius outer with a hole of radius inner, starting at start degrees and sweeping sweep degrees.
  • H3DU.Meshes.createDisk(inner, outer)
    Same as calling createPartialDisk with start 0 and sweep 360.

For more information on meshes, see Creating shapes using the Public Domain HTML 3D Library.

Shapes

Once a mesh is created, it needs to be added to the 3D scene in order to be rendered. Use the H3DU.Shape constructor method to convert the mesh to a shape. Then you can set the shape's properties such as color, size, and position. Then, call addShape() to add the shape to the 3D object batch.

<code>// Create a shape based on the mesh
var shape=new H3DU.Shape(mesh);
// Make it red (you can also use the HTML color string
// "#FF0000" instead)
shape.setColor("red");
// Move it 1 unit along the X axis
shape.setPosition(1,0,0);
// Add the shape to the scene
batch.addShape(shape);</code>

The appearance of a 3D shape is known in the 3D graphics world as a "material". It includes textures (images), colors, and light reflection parameters. The Material class holds data on some of these parameters, and is part of the definition of a shape. The PbrMaterial class does the same, but uses physically-based shading algorithms.

Here are details on some of the Shape class's methods.

  • shape.setPosition(x, y, z)
    Sets the shape's position to the given coordinates.
  • shape.setScale(x, y, z)
    Sets the shape's scaling along the x, y, and z axes. Examples: (1, 1, 1) means no scaling, (2, 1, 1) means a doubled width, (1, 1, 0.5) means a halved depth.
  • shape.getTransform().setRotation(angle, x, y, z)
    Sets the shape's rotation given an angle in degrees, and an axis of rotation (the x, y, and z parameters). Example: (40, 1, 0, 0) means a 40-degree rotation around the X axis (x is 1 in the axis of rotation).
  • shape.setColor(color)
    Gives the shape a particular color. color can be an HTML color ("#ff0000"), CSS color ("red"), RGB color("rgb(20, 30, 40)") or HSL color("hsl(20, 50%, 50%)"), or a set of values from 0 to 1 (example: [1.0,0.5,0.0]). See my colors tutorial.
  • shape.setTexture(name)
    Gives the shape a particular texture, with the URL name. The texture should be in the same origin as the Web page (which usually means the same directory).
  • shape.copy()
    Creates a copy of this shape. Can be more efficient than calling new H3DU.Shape if the same geometric mesh will be used more than once in the same 3D scene, with different positions and attributes.

The Render Loop

An important part of a 3D application is the render loop. The render loop is a block of code that is called many times a second (or many "frames" a second) to redraw the 3D scene. Each frame, the state of the application is updated, and the 3D scene is re-rendered to account for that state. To render a scene, use the H3DU.Scene3D.render() method, passing a batch of shapes to render. Render loops are created using the H3DU.renderLoop() method. Here is an example of a render loop.

<code>// Set up the render loop
H3DU.renderLoop(function(time){
 // This will be called once each frame.
 // Here, we render the scene
 scene.render(batch);
});</code>

The render loop method takes a parameter (here "time"), containing the number of milliseconds since the page was started.  This can be used to implement frame-rate independent animations.

A Skeleton for 3D Apps

The following is a minimal skeleton you can use for writing HTML apps using this library.

<code><head>
<meta charset=utf-8>
<meta name="viewport" content="user-scalable=no,initial-scale=1,maximum-scale=1">
<script type="text/javascript" src="h3du_min.js"></script>
</head>
<body style="margin:0px">
<canvas id=canvas style="width:100%; height:100%; overflow: hidden;"></canvas>
<script>
// Your script goes here
</script>
</body></code>

Demos

The following are HTML Web pages showing a variety of features of the HTML 3D library. Each demo includes a link to access source code for that demo.

Simple Demos

Materials

Shapes and meshes

Paths

Curves and Surfaces

Textures

Shaders

Particle Systems

Loading 3D Models

Selecting Objects

Lights

Text

  • demos/textwith3D.html - Demonstrates loading bitmap fonts and displaying text with them. Demonstrates showing bitmap font text on top of a 3D animation.

Projections

Miscellaneous

Example

The following is a simple example of an HTML page that uses the HTML 3D library. It sets up the 3D scene, generates a 3D box, colors it red, and rotates it each frame as time passes. Look at the comments; they explain better what each part of the code is doing. Also note the <canvas> element it uses on the page.

<code><head>
<script type="text/javascript" src="h3du_min.js"></script>
</head>
<body>
<canvas width="600" height="450" id=canvas></canvas>
<script>
 // Create the 3D scene; find the HTML canvas and pass it
 // to Scene3D.
 var scene=new H3DU.Scene3D(document.getElementById("canvas"));
 var sub=new H3DU.Batch3D();
  // Set the perspective view. Camera has a 45-degree field of view
  // and will see objects from 0.1 to 100 units away.
  .perspectiveAspect(45,0.1,100)
  // Move the camera back 40 units.
  .setLookAt([0,0,40]);
sub.getLights().setBasic();
 // Create a box mesh 10 units in size
 var mesh=H3DU.Meshes.createBox(10,20,20);
 // Create a shape based on the mesh and give it a red color
 var shape=new H3DU.Shape(mesh).setColor("red");
 // Add the shape to the scene
 sub.addShape(shape);
 // Create a timer
 var timer={};
 // Set up the render loop
 H3DU.renderLoop(function(time){
  // Update the shape's rotation
  var q=H3DU.Math.quatFromTaitBryan(
    360*H3DU.getTimePosition(timer,time,6000),
    360*H3DU.getTimePosition(timer,time,12000),
    0
  );
  shape.setQuaternion(q);
  // Render the scene
  scene.render(sub);
});
//-->
</script>
</body></code>

History

Version 2.0.0-beta3

The changes in beta 3 from beta 2 include:

  • The main library files were converted to ECMAScript's import/export convention. The rollup tool is used to help generate the h3du_min.js file.
  • HTML documentation included in distribution.
  • "Norm" methods in H3DU.Math were renamed to use "Normalize" instead.
  • New convex.js in extras folder generates the convex hull of a set of points.
  • New interp.js in extras folder provides a cubic Bézier interpolation function.
  • New spline.js in extras folder generates piecewise interpolating curves.
  • New demos added, including demos showing how to generate procedural content using shaders.
  • Several methods in H3DU.GraphicsPath were reimplemented.
  • H3DU.BezierCurve and H3DU.BezierSpline are deprecated.
  • H3DU.CurveBuilder and H3DU.SurfaceBuilder classes were created; they replace now-deprecated H3DU.CurveEval and H3DU.SurfaceEval classes.
  • H3DU.MeshBuffer contains many new methods; in exchange, many of the H3DU.Mesh methods reimplemented in H3DU.MeshBuffer are deprecated.
  • H3DU.Mesh is considerably deemphasized in this version; that class should only be used for building meshes, not storing them.
  • H3DU.Curve and H3DU.Surface were created; these classes represent parametric curves and surfaces and offer methods for querying information at a given point on the curve or surface. Made several class derive from either class, including H3DU.BSplineCurve, H3DU.BSplineSurface, and new class H3DU.PiecewiseCurve.
  • H3DU.RenderPass3D renamed to H3DU.RenderPass.
  • Deleted fromBasic and fromBasicTexture methods from H3DU.PbrMaterial.
  • Added JOINTS and WEIGHTS constants to H3DU.Semantic.
  • Preliminary support for occlusion maps.
  • Default diffuse/albedo in Material and PbrMaterial is now (1,1,1,1).
  • New H3DU.BufferAccessor class represents a single vertex buffer.
  • Many methods outside H3DU.Mesh now return H3DU.MeshBuffer instead of H3DU.Mesh.
  • Bug fixes.

Version 2.0.0-beta2

The changes in beta 2 from beta 1 include:

  • Added H3DU.PbrMaterial class and supported physically-based shading in the default shader.
  • H3DU.Shape objects contain H3DU.PbrMaterial by default.
  • Extras folder contains a glTF loader, which is preliminary and incomplete.
  • H3DU.Scene3D will create a WebGL 2 rendering context if possible and supported by the browser.
  • H3DU.MeshBuffer stores vertex data by semantic (such as position, normal or texture coordinates), rather than by name.
  • The new H3DU.Semantic class contains constants for attribute and uniform semantics.
  • The new H3DU.TextureInfo class is a lightweight class for storing a texture's settings, but not its data.
  • H3DU.ShaderInfo class can now accept H3DU.TextureInfo objects as uniform values.
  • H3DU.Material can accept a parameter object in the constructor as it can in the setParams method, similarly to the new H3DU.PbrMaterial class.
  • Added fromBasic and fromBasicTexture methods to H3DU.Material class.
  • Many new methods were added to the H3DU.Math class, including methods to add and subtract 4-element vectors, to clamp vectors, and to convert to and from linear RGB colors, as well as vec3proj, vec4proj, mat3invert, and vec3fromWindowPoint methods. The frustumHasBox method was improved.
  • The shapeCount, getShape, setShape, and copy methods were added to H3DU.ShapeGroup.
  • New H3DU.CubeMap class holds information on the textures that make up a cube map. However, cube maps are not yet supported in the default shader (its code is currently commented out)
  • In the H3DU.GraphicsPath extra, added methods for high-level shapes and path interpolation and improved code on path triangulation.
  • H3DU.TextFont extra supports multichannel signed distance field fonts.
  • Several new demos were added.
  • Some methods were removed: setMaterialParams methods from both H3DU.Shape and H3DU.ShapeGroup; mapTexture and mapTexturesAll methods from TextureLoader; and forShader method from H3DU.Material.
  • Renamed setOrientation and multOrientation in H3DU.Transform to setRotation and multRotation, and deprecated the old names.
  • Bug fixes.

Version 2.0.0-beta1:

  • All classes in the main library are moved to a new namespace called H3DU. For example, Shape is now H3DU.Shape and Mesh is now H3DU.Mesh. Many classes in the "extras" directory are also moved to the H3DU namespace.
  • Scene3D, now H3DU.Scene3D, is no longer meant to be a scene graph of objects to draw. That job now belongs to the new H3DU.Batch3D class. Scene3D's render method now takes an array of Batch3Ds to render. For compatibility, though, the methods allowing it to manage 3D models and the coordinate system, such as makeShape and setPerspective, can still be used until H3DU.Scene3D renders a custom H3DU.Batch3D. This compatibility behavior may be dropped in the future.
  • Alpha is disabled in WebGL contexts created with the H3DU.get3DOr2DContext method.
  • The Scene3D H3DU.Scene3D#useProgram method was deprecated and now does nothing.
  • New H3DU.RenderPass class holds information about how a batch of 3D models is to be rendered. It replaces the Scene3D H3DU.Scene3D#useFilter method, which now does nothing.
  • New H3DU.FrameBufferInfo class holds information about a frame buffer; it replaces H3DU.FrameBuffer.
  • The BufferedMesh, FrameBuffer, and ShaderProgram classes are deprecated because they are too tightly coupled with a particular WebGL context. Instead, use H3DU.MeshBuffer, H3DU.FrameBufferInfo, and H3DU.ShaderInfo, respectively, which are not coupled to WebGL contexts.
  • Rendering can make use of vertex array objects internally, if supported by the WebGL implementation.
  • The H3DU.Shape object is no longer coupled to vertex buffers.
  • The H3DU.LightSource class now supports a radius of the light.
  • The H3DU.TextureLoader class was added for loading textures; a single object of this class can load and upload images from multiple WebGL contexts. This is unlike BufferedMesh, FrameBuffer, and ShaderProgram, which are tied to the WebGL context.
  • GLMath, now H3DU.Math, was expanded with many new methods. The documentation for it is now very detailed. New methods include H3DU.Math.vec3perp, H3DU.Math.vec3toWindowPoint, and H3DU.Math.mat4projectVec3.
  • Two new classes in the "extras" folder support 2D text rendering and texture atlases (as sprite sheets), namely, H3DU.TextFont and H3DU.TextureAtlas.
  • The "doc" folder contains the documentation to the library in the form of Markdown text files.
  • The Camera class, now H3DU.Camera, was rewritten.
  • A build script was included in the repository. This build includes a style checker which is run on the library's JavaScript files.
  • Many methods were added to many classes. Some methods that didn't return a value now return the value of the object called on, for example, the clear method of H3DU.Scene3D.
  • New demos, including spinbox.html and quatlerp.html. For example, the gears.html demo was moved from the separate "html-gears" repository to here. Other demos were expanded or rewritten. Viewport meta tags were added to the demos.
  • The underlying code used in H3DU.toGLColor was rewritten. In particular, the "#RRGGBBAA" format is now supported.
  • The JavaScript source code better conforms to a uniform code style.
  • The experimental 2D canvas renderer in surfaces2d.html, was abandoned.
  • Added dispose method to H3DU.Scene3D.
  • Added createPointedStar and createLathe methods to H3DU.Meshes.
  • Added getBounds and toLinePath methods to H3DU.GraphicsPath, an extra, as well as an extra that adds methods that compute the intersection, difference, union, and XOR of two polygons. Path triangulation now supports polygons with holes.
  • The default light configuration is no lights when creating a H3DU.LightSource. The exception, for compatibility purposes, is when using a H3DU.Scene3D without rendering a custom Batch3D, in which case the default is one light source with its default values.
  • The default value for specular materials (H3DU.Material) is now (0.1, 0.1, 0.1). The default value for shininess is now 32.
  • The Mesh class no longer supports multiple primitive types (lines, triangles, points). Using different modes that use the same primitive type (for example, TRIANGLE_FAN and QUAD_STRIP) in the same mesh is still supported.
  • Many of the tutorials were edited heavily to accommodate the new version. The GraphicsPath tutorial was added.
  • There were also numerous bug fixes.
  • A known issue: When using the H3DU.Camera in conjunction with the compatibility behavior of H3DU.Scene3D, only one side of the scene will appear lighted by default.

See older version history.

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication