Creating a 3D engine in Javascript - part 2

Submitted by m_sabal on Tue, 01/08/2013 - 11:29

Next, we should probably cover some important concepts related to 3d programming and math. Look at a photograph of a landscape or street scene. The scene you are look at is three-dimensional, yet it appears in a two-dimensional format. Our brains, however, still process the three dimensional information. The reason is perspective. Three things happen that allow our brains to understand three dimensions, even when looking at a two-dimensional format. First, objects closer to us block objects farther away. This is the concept of z-order. Second, objects in the distance appear smaller than objects nearby. This is the concept of scale. Third, parallel lines appear to converge to a point in the distance. This concept is also called perspective when it applies specifically to methods in art. In some cases, especially painting and photography, an artist can manipulate the blurriness of objects to add dimensionality. Our Javascript library isn't going to deal with this anytime soon; but it may be a cool feature once we've gotten everything else in place.

When we describe an object, such as a cube or a building, we typically use length or depth, width, and height. If we're creating this cube with a hammer and saw, these descriptions are quite useful. However, if we are trying to map a three-dimensional object onto a two-dimensional screen, we need a different way to describe the object. Programmers have taken the idea of Euclidean space, sometimes referred to as the X,Y,Z Coordinate System to handle the mapping task. In two-dimensional space, the X coordinate is horizontal, and the Y coordinate is vertical. There is much less agreement when it comes to the location of the origin point (0,0,0) or the definitions of the planes in three-dimensional space. Programmers not only have to map a three-dimensional object to a two-dimensional screen, but also to one-dimensional memory. This final task used to be manual when graphics were written in pure Assembly or machine language. Thankfully, languages like Javascript handle memory management fairly well behind the scene. Nevertheless, the conventions begun by the manual process have continued with us. As a result, the two-dimensional origin point of the screen is the upper left-hand corner, with the X dimension increasing to the right and the Y dimension increasing downward. Many 3d libraries such as OpenGL consider the Z dimension more negative in the distance and more positive in the direction of the viewer, with the zero point at the viewer's eye. To save typing and some gray matter, I am going to reverse this convention and define greater values of Z as more distant into the screen, and negative values of Z as being out of the screen towards the viewer, making the zero point the screen itself. This will allow us to say that anything with a negative Z won't be rendered.

Every real-life object can be modeled with a collection of triangles (or other polygon), known as a mesh. The size, shape, and number of triangles, which don't all have to be the same, will determine the resolution of the object and how realistic it looks. Each line segment is called an edge, and the points terminating the line segment, typically where edges meet, are called vertexes. Where edges form a closed polygon, a face is formed. Object models are usually stored as arrays of vertexes, with each vertex being given a real-life Euclidean coordinate. The coordinates have no relation to any unit of measure until a scale has been defined. When you use you're camera's zoom feature, the photograph may be either larger or smaller than the actual object. We can also create the illusion of motion by applying geometric transformations equally to all the vertexes of an object model. Let's say we have a 125 cubic foot cube. A cube has eight vertexes. We can define those vertexes as (1,1,1),(1,6,1),(6,1,1),(6,6,1),(1,1,6),(1,6,6),(6,1,6),(6,6,6), with each coordinate unit equaling a foot. The first four vertexes form the front face, and the last four form the back face.

In the next part of this series, we'll start adding some code to resman.js to handle various transformations like scale, slide, rotate, and skew for perspective.