Creating a 3D engine in Javascript - part 3

Submitted by m_sabal on Wed, 01/09/2013 - 13:47

We're going to start by adding a new function to resman.js:


function draw_vertexes(gc, scale, offset, vertexes) {
for (ctr=0; ctr<vertexes.length; ctr++) {
gc.beginPath();
gc.arc(Math.floor((vertexes[ctr][0]*scale)+offset[0]),
Math.floor((vertexes[ctr][1]*scale)+offset[1]),
2,0,Math.PI*2,true);
gc.fill();
}
}

In this function, we're going to take the object model, defined as an array of vertexes, and draw a filled circle on the canvas for each corner. The purpose here is to demonstrate and prepare the functions used for transformation, which will become important when we start drawing edges and faces. Javascript does not have a function for drawing circles, but it does have one for drawing arcs. A full circle is just a 360 degree arc, or 2*PI radians. The variable gc refers to the graphics context returned from resman_start(). The scale parameter is our first transformation, from model units to pixels. The offset is our slide transformation, defined as [x,y] in pixels. The arc function has six parameters: center x, center y, radius, start angle, stop angle, and anti-clockwise. If this last parameter is true, the arc will be drawn counterclockwise; if false, clockwise. For a circle, it doesn't matter whether it's clockwise or not, since the beginning and ending points will be the same. In order to draw an open circle, use the stroke() function instead of fill().

Next, we want to change wireframe.js. Instead of drawing a vertical line, we're going to draw the corners of a cube:


function wireframe_start(cantag) {
var context;
context = resman_start(cantag,true,"#000000");
can = document.getElementById(cantag);
h = can.height;
w = can.width;
context.fillStyle="rgb(0,255,0)";
var cube = [
[1,1,1],
[1,6,1],
[6,1,1],
[6,6,1],
[1,1,6],
[1,6,6],
[6,1,6],
[6,6,6]
];
draw_vertexes(context,100,[100,100],cube);
}

Our object model, cube, is created as an array of three-dimensional coordinates. For this first example, we are scaling the figure to 100 pixels per object unit, and moving the object 100 pixels right and 100 pixels down. When you open index.html in your browser, you will only see four dots on the canvas. This is because the back face of the cube is exactly hidden by the front face, and we haven't applied a skew transformation.

Change the scale figure from 100 to 50 and refresh your browser page. You'll notice that not only did the scale change, but the offset changed as well. How come? The reason is that the offset applies to the origin point (0,0,0), not to the center of the object. We could (and will, later) write a new function that will calculate the true center point of the object; but for now, we'll just redefine our vertexes instead. Change cube to this:

var cube = [
[-2.5,-2.5,-2.5],
[-2.5,2.5,-2.5],
[2.5,-2.5,-2.5],
[2.5,2.5,-2.5],
[-2.5,-2.5,2.5],
[-2.5,2.5,2.5],
[2.5,-2.5,2.5],
[2.5,2.5,2.5],
];

Now only one point is showing up, so we need to adjust our offset accordingly. Let's put the center of the object in the center of the canvas. To do that, change the [100,100] offset to [Math.floor(w/2),Math.floor(h/2)]. Now play around with the scale. The object remains centered, but appropriately changes size in place. We'll add the skew and rotate transformations in part 4.