Once upon a time, a friend and dedicated hobby-programmer asked me, how do I all this 3 dimensional drawing stuff, 
and as I found out he was not the only one, who had problems getting the math in the right way. So here's a little
explanation of the underlying math of my SVG-VML-3D pages for all those, who are also fiddling around whith this topic.
Let's say you have your 3D objects in the range of the box
{ xmin, xmax, ymin, ymax, zmin, zmax }
By a first coordinate transformation shift the box, so that its center is in the origin: 
xd=(xmin+xmax)/2, 
yd=(ymin+ymax)/2, 
zd=(zmin+zmax)/2
 
x'=x-xd, y'=y-yd, z'=z-zd
So you get your objects now in the range of the box
{ -x'm, x'm, -y'm, y'm, -z'm, z'm }
Now its time to introduce our 3D coordinate system:
    z
    |
    |
    |
    |_______ y
    /
   /
  /
 x
Let's say you stand at (1000,0,0) and look at the origin (0,0,0) where you see all your 3D objects which are near to (0,0,0).
Now let's turn the objects around the z-axis by an angle of Φ. What will be the new position of a point (x', y' z')
after that? As it is easy to see, the z-component doesn't change, so we get z''=z'. But what about x' and y'?
When we look from the top of the coordinate system, we see this:
   _______________ y
  |. .
  | .   .
  |  .     .
  |   .___/   .
  |    .  Φ     * (x'', y'')
  |     .
  |      .
  |       * (x', y')
  |    
  x
It seems to be difficult to find a formula which calculates x'' and y'' from x', y' and Φ, but when we do a separate
calculation for x' and y', it get's easier, look at this:  
   _______________ y                                       * (x'', y'') 
  |.                                                   .                    x''= - y' sin(Φ)
  | .                                               .                       y''=   y' cos(Φ)
  |  .               x'' = x' cos(Φ)              |----------*---- y
  |   .              y'' = x' sin(Φ)              |        (0, y')
  |    .                                          |
  |     * (x'', y'')                              |
  * (x', 0)                                       |
  |                                               |
  x                                               x
Now we can add the components for x, y and z and write it down properly:
x'' = x'*cos(Φ) - y'*sin(Φ) + z'*0
y'' = x'*sin(Φ) + y'*cos(Φ) + z'*0
z'' = x'*0      + y'*0      + z'*1
It's a fine thing to do this with matrix and vector, so it will look like this:
| ( | x'' | ) |  | ( | cosΦ | -sinΦ | 0 | ) |  | ( | x' | ) | 
|---|
| y'' | = | sinΦ | cosΦ | 0 | * | y' | 
| z'' |  | 0 | 0 | 1 |  | z' | 
OK, but how about turning all the stuff additionally around the y-axis by an angle of Θ, so it looks as if you view
from a higher position down to the 3D objects (view from a higher position down to the objects - doesn't it sound
great?). Also in this way the z-axis will still remain vertically, so this is what
you often will need for 3D-representations when the z-axis should always point to the top of the screen. So lets try to 
apply the same math that we used for the rotation around the z-axis. When we look from the right side, the coordinate system
looks like this:
                z                                        z
                |                                        |
   (x''', z''') |                               (0, z'') *  (x''', z''')  
          *     |  x'''=x'' cos(Θ)                       |    *
            .   |  z'''=x'' sin(Θ)                       |  .       x'''= - z'' sin(Θ)
              . |                                        |.         z'''=   z'' cos(Θ)
   x ---*-------|                           x ------------
    (x'', 0)
Writing the stuff fine together, we get
x''' = x''*cos(Θ) - y''*0 - z''*sin(Θ)
y''' = x''*0      + y''*1 + z''*0
z''' = x''*sin(Θ) + y''*0 + z''*cos(Θ)
And in matrix notation:
| ( | x''' | ) |  | ( | cosΘ | 0 | -sinΘ | ) |  | ( | x'' | ) | 
|---|
| y''' | = | 0 | 1 | 0 | * | y'' | 
| z''' |  | sinΘ | 0 | cosΘ |  | z'' | 
Now let's do the two rotations in one step whithout calculating the (x'', y'', z'') vector:
| ( | x''' | ) |  | ( | cosΘ | 0 | -sinΘ | ) |  | [ | ( | cosΦ | -sinΦ | 0 | ) |  | ( | x' | ) | ] | 
|---|
| y''' | = | 0 | 1 | 0 | * | sinΦ | cosΦ | 0 | * | y' | 
| z''' |  | sinΘ | 0 | cosΘ |  | 0 | 0 | 1 |  | z' | 
You probably know from your Algebra lessons, that we can use A*(B*C)=(A*B)*C to simplify the matrix multiplication,
so we get:
| ( | x''' | ) |  | ( | cosΦcosΘ | -sinΦcosΘ | -sinΘ | ) |  | ( | x' | ) | 
|---|
| y''' | = | sinΦ | cosΦ | 0 | * | y' | 
| z''' |  | cosΦsinΘ | -sinΦsinΘ | cosΘ |  | z' | 
Finally, we get the position of a point in the screen coordinate system by
xs = y''' = sinΦ x' + cosΦ y'
ys = z''' = cosΦsinΘ x' - sinΦsinΘ y' + cosΘ z'
zs = x''' = cosΦcosΘ x' - sinΦcosΘ y' + sinΘ z'
The pixel count in y is from top to down, so you will get the appropriate pixel numbers by
x
pixel=x
center+x
s and y
pixel=y
center-y
s.
The z
s can be used to order the objects before drawing, so you would start the drawing with the
object which has the smallest z
s.
The current picture will not show any perspective, it looks as if you were standing very far away.
If you want to get a more realistic impression, you must change the formula just a little bit.
Assume your position is (0,0,d), so d is your distance from the origin. When you look at a point (x
s, 0, z
s),
then its picture will be (x'
s, 0, 0), as all picture points are located in the same plane, where z=0:
        |       (x's,0,0)
     ---|--------*---------- x         
        |       .
        |      .
        |     * (xs,0,zs)
        |    .
        |   .
        |  . 
        | .
        |.
        o (0,0,d)
        |
        z
Then you get by similar triangles
(x's-xs)/zs = xs/(d-zs)
so the new screen coordinate with perspective is
x's = xs * (d /(d-zs))
y's = ys * (d /(d-zs))
Note, that now also the drawing order must be changed: Instead of sorting the objects according to their z
s,
the objects should now be sorted according to their distance to (0,0,d).
O.k. folks, that's enough for the beginning, if you want to see how I implemented this, then have a look at my
SVG-VML-3D examples.
© Lutz Tautenhahn, 2002