Ryan Byrd dot net

3D Graphics

3D Javascript cube

I didn't write this 3D javascript cube, but I can explain how it works. Scroll down below the cube for the description.

degrees

Description

The first step in displaying a 3D figure is to create a way to draw a dot on given location of the screen (a pixel primitive function some might say). This demo is a bit crazy -- instead of using an actual pixel on the screen, it uses HTML table cells as pixels. No matter -- just think of the HTML table as our canvas and the cells as our dots. The variables: THEWIDTH = 40; and THEHEIGHT = 40; determine the rows and columns of our HTML table. We'll use two nested loops to draw the table:
addtext = "";
addtext +="<br><br><br><center><table border=1 cellspacing=0 
  cellpadding=0>";
for (x=0;x<=THEWIDTH;x++){
  addtext += "<tr>";
  for (y=0;y<=THEHEIGHT;y++){
    addtext += "<td bgcolor=#222222 id=\'" + x + "_" + y + "\' 
  width=" + THESCALEF +
" height=" + THESCALEF + "></td>";
  }
  addtext += "</tr>";
}
addtext += "</table></center>";
document.write(addtext);

We'll need a function to color our dots (change the background color of our HTML table cells.) Here it is:

function setpx(x,y,col){
 theid = document.getElementById(x + "_" + y);
 if (theid){
   theid.style.backgroundColor=col;
    }
   }
Next we'll need a function to draw a straight line between points we choose (the corners (vertices) of our cube.) A smart guy named Bresenham came up with an efficient line drawing algorithm that, given two points, will produce the points in between. It's called, fittingly, Bresenham's Line Algorithm. It's particularly neat because it does not use multiplication or division. Ours is a javascript implementation that includes a final parameter, line color:
/*Bresenham's Line Algorithm
Ported from version by Mark Feldman*/
function line(x1,y1,x2, y2,col){
  deltax = Math.abs(x2 - x1);
  deltay = Math.abs(y2 - y1);
  if (deltax >= deltay){
    numpixels = deltax + 1;
    d = (2 * deltay) - deltax;
    dinc1 = deltay << 1;
    dinc2 = (deltay - deltax) << 1;
    xinc1 = 1;
    xinc2 = 1;
    yinc1 = 0;
    yinc2 = 1;
  }else{
    numpixels = deltay + 1;
    d = (2 * deltax) - deltay;
    dinc1 = deltax << 1;
    dinc2 = (deltax - deltay) << 1;
    xinc1 = 0;
    xinc2 = 1;
    yinc1 = 1;
    yinc2 = 1;
  }
  if (x1 > x2){
    xinc1 = - xinc1;
    xinc2 = - xinc2;
  }
  if (y1 > y2){
    yinc1 = - yinc1;
    yinc2 = - yinc2;
  }
  x = x1;
  y = y1;
  for (i = 1; i < numpixels; i++){
    setpx(x, y, col);
    if (d < 0){
      d = d + dinc1;
      x = x + xinc1;
      y = y + yinc1;
    }else{
      d = d + dinc2;
      x = x + xinc2;
      y = y + yinc2;
    }
  }
}

Before we get to our main loop, there are two pesky matters: rotation and projection (converting our three dimensional cube into a two dimensional representation (the screen). It's the Z axis that needs converting.)
First, 2D rotation:

An easy way to think about rotation is to convert from cartesian coordinates to polar coordinates. (cf BYU CS 455)

Cartesian coordinates are your standard (x,y) pairs. Polar coordinates define a ray starting at the origin and extending distance r at angle theta(which is 0 at the positive x axis) until reaching point (x,y)

When a point is described in polar notation, it is trivial to rotate the point -- we simply increase the angle theta.

so, knowing x=r*cos(theta),y=r*sin(theta), point (x,y): (in matrix notation)
[x]
[y]
becomes
[r*cos(theta)]
[r*sin(theta)]


Then, the rotation is a simple angle addition to theta. For example, to rotate R degrees:

[r*cos(theta+R)]
[r*sin(theta+R)]


we can apply the sum angles formula to simplify:

[r*cos(theta)cos(T)-r*sin(theta)sin(T)]
[r*sin(theta)cos(T)+r*sin(T)cos(theta)]


and substituting x=r*cos(theta),y=r*sin(theta) back into our rotation we have:
[x*cos(T)-y*sin(T)]
[x*sin(T)+ycos(T)]
which is:
[cos(T) -sin(T)][x]
[sin(T) cos(T) ][y]


In summary, given a point
[x]
[y]
to rotate T degrees around the origin, we simply matrix multiply the point by
[cos(T) -sin(T)]
[sin(T) cos(T) ]




Send to a friend * Print this page * Join the club * Talk with my robot * Advertise here * Search this Site * Donate * Link to me


Web hosting by Utah Hub *  Powered by CreativeTap *  In association with Segomo
Unless otherwise noted, Copyright 2004-2008, Ryan Byrd. All Rights Reserved.
Ryan Byrd dot net -- probably the coolest site in Utah