-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
                     INTRODUCTION TO 3D SERIES #1
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Writer: Matthew River Knight
Have you ever played Quake and wished you could make a similar game in
Qbasic? Have you ever tried to learn how to code a 3d program in Qbasic,
only to find that there are no good tutorials out there? Yep? Well then
this tutorial is just for you! ^_^
I remember when I wanted to learn how to do 3d, it was a total nightmare.
I went to every shop I knew of in search of a book - they had books on the
subject, but they were all aimed at C programmers...there was nothing for
Qbasic coders such as myself. Next I decided to search around the internet
for a decent tutorial. I found several tutorials, but to my alarm, they were
all so complicated! I'm sure that some of you have, at some stage,
downloaded a certain 3d tutorial by Matt Bross. What a mistake that was eh?!
It is a pathetic excuse for a tutorial. It consists only of extremely 
complicated and difficult to read code, then followed by a very brief
explanation of what it does, and an even briefer explanation of how it goes
about achieving this.
In order to fill the obvious void in the QB world for a decent 3d programming
tutorial, I have decided to do a series about it right here in QBCM! We are
going to take things step-by-step, progressing from the very simplest 
aspects of 3d programming, right up to the more complicated, but extremely
fun stuff! ^_^
Don't worry if you aren't good at maths, or aren't a programming guru. I
am going to explain things in such a way that they are going to be very
easy to understand, regardless of your ability! I do however recommend that
you have at least an intermediate knowledge of Qbasic. As far as the maths
is concerned, there is a large misconception amongst the programming circles
that in order to do 3d, you have to be a genius with mathematics. Not so.
You will need to have a good knowledge of Algebra, Geometry, and Analytical
Algebra. That's it. It does help to know Trigonometry, but it is not a
necessity.
Okay, I have rambled on long enough! Let's start learning how to program
in 3d!!! To begin with, we need to know how to define a point in a 3d world.
You already know how to define a point in 2d - it's simple...you have your
X coordinate to describe the point/pixel's location across the screen, and
you have your Y coordinate to describe the point/pixel's location down the
screen. In 3d it works exactly the same way, however, we have to add another
coordinate: Z. The Z coordinate describes the depth, or in other words,
how far the point/pixel is away from the viewer. In a 3d world, the exact
center of the world is X,Y,Z = (0,0,0). So, a point that is 100 pixels
to the left of the center of the 3d world would be at (-100,0,0). A point
that is 50 pixels to the right of the center of the 3d world, 100 pixels
higher than the center of the 3d world, and 10 pixels closer to the viewer
than the center of the 3d world, would be at (-50,-100,10). All of the
points in your 3d world are collectively called the world coordinates.
Using the above method, it is easy to create a 3d world. If, for example,
you wanted a quadrilateral (such as a cube) in your 3d world, you would
compose it by defining points which are the vertices of the object. Later
on, when actually drawing the object on the screen, we connect all of the
points/pixels together by using the LINE statement. This gives us what is
called a wireframe representation of the object. But, before we can draw
our 3d objects on the screen there's some stuff you have to know - we'll
cover that at a later stage.
Once we have defined all of our world coordinates, we have to place the
camera in the 3d world. The camera (also called the eye or the viewer) is
what actually looks at the world. If you place it high above the 3d world,
then you see the world in much the same way that it would be seen from a
high tree, or a building. If you place the camera much lower down, then
you will see the 3d world from an ants point of view! The camera's position
is defined in exactly the same way as the world coordinates: you describe
the camera's position in the 3d world with X, Y, and Z coordinates. It is
important to note that the camera will ALWAYS 'look' to the center of the
3d world (0,0,0).
Now that we have defined our world coordinates, and have defined our camera
position, we have to find a way to plot the 3d world on the screen, relative
to the camera's point of view. Now the most obvious question is "how on
Earth do I plot a 3d object on a 2d surface like the screen??!!" Well, let's
take this one step at a time.
Okay, let's say we have defined a single point in a 3d world where:
x_world = 100
y_world = 20
z_world = 10
The first step in getting our 3d world onto the screen is changing these
world coordinates into what is called the camera coordinates. The camera
coordinates describe the world coordinates as they are seen from the
camera's point of view.
Now, in order to change the world coordinates into camera coordinates, we
have to use a set of mathematical formulae. "Nooooo!" I hear you say. Heheh,
don't worry, it isn't difficult at all...and I am going to explain how it
works. ^_^
Now let's think about this logically. Suppose we are in a 3d car racing
game. Our camera (which is basically the same as the person inside our
car in the game) is at (100,10,10) and is looking at the center of the 3d
world (0,0,0) (you will recall that the camera in a 3d world will always
look to the center of this world). With the camera at this position, the
center of the world is at (-100,-10,-10). From this information, it seems
that:
x_camera = x_world - camerapos_x
y_camera = y_world - camerapos_y
z_camera = z_world - camerapos_z
where:
x_camera = x coordinate of a point (camera coordinate system).
           Ditto with y_camera, and z_camera.
x_world = x coordinate of a point (world coordinate system).
          Ditto with y_world, and z_world.
camerapos_x = x coordinate, describing the position of the camera in the 3d
              world. Ditto with camerapos_y, and camerapos_z.
And guess what...those equations are actually the equations we use to
convert world coordinates into camera coordinates!!! ^_^
It is important to note that you can place the camera anywhere in the 3d
world, except for one place - you CANNOT place the camera in the center of
the 3d world (0,0,0). You can put it anywhere but there. Why? Well, since
the camera will always look to the center of the world, if the camera was
in the center of the world it would be looking at itself. Can you look at
your eyes??!! Nope, of course not (not without a mirror anyway.) So you
can't put the camera at (0,0,0). If you do put the camera in the center of
the world, then some of the mathematical formulae which we are about to
describe will not work, and the program will crash.
Okay, so now we have converted our world coordinates into camera
coordinates. But we still can't draw our 3d world/object(s) on the screen
yet. We still have points which are described by X, Y, and Z, but the PSET
and LINE statements can only draw with points defined by X and Y (which is
2d) - this is logical really...the screen is, after all, a 2d surface.
In order to draw in 3d on the screen using PSET or LINE, we have to convert
our camera coordinates (which describe the 3d world coordinates relative to
the camera's point of view) into 2d screen coordinates. How? Simple. We use
a set of mathematical formulae!!! (Do I hear groaning?! ^_^)
Once again, we have to think about the problem at hand with a bit of logic
and common sense. In real life, objects that are further away from us
look smaller than they do when you are right next to them. The principle
is the same with 3d computer graphics. For example, imagine that in our
3d world we have two points/pixels that are 10 pixels length apart. If their
Z coordinates are both decreased by 1, then the two points are each going to
move one pixel length closer to the other. This information demonstrates
the golden wisdom of every 3d programmer: "The screen coordinates could be
calculated by dividing the X and Y position through the depth (z coord-
inate)."
This shown as a formula is:
x_screen = x_camera / z_camera
y_screen = y_camera / z_camera
where:
x_screen = x coordinate of the pixel on the screen.
y_screen = y coordinate of the pixel on the screen.
x_camera, y_camera, z_camera = (see above).
However, we have several different screen modes at our disposal, and (0,0)
on the screen is actually the top left hand side of the screen, so we have
to change the formulae a little if we want the 3d object to be centered on
the screen and if we want the program to work in all screen modes. The final
set of formulae for conversion of camera coordinates to screen coordinates
is as follows:
x_screen = (x_camera / z_camera) * srx + srx / 2
y_screen = (y_camera / z_camera) * sry + sry / 2
where:
srx and sry describe the screen resolution. In SCREEN 13, srx would be
equal to 320, and sry would be equal to 200.
Another very important thing that I must mention is that if any of our
points in the 3d world go behind the camera, or in line with the camera,
then the math for projection of the camera coordinates onto the screen goes
all haywire. This is logical really. In real life, if an object is behind
you, or in line with your eyes on the side, then you cannot see it. This is
the same with 3d computer graphics, but the problem is that the computer
doesn't yet know that we must not be able to see these points, so it
attempts to use the math on them anyway, and it goes nuts!!! ;)
We'll say that points in our world coordinates that are in line with or
behind the camera are "out of range". In order to fix this problem, it is
necessary that we do a test on all of the points in our 3d world (the world
coordinates) to see if they are "out of range" and if they are, then we
have to temporarily eliminate them. When they are back in range again, then
we can put them back and have them plotted on the screen. Let's explain this
another way: if the value of the world Z coordinate of a point is equal to
camerapos_z or greater than camerapos_z then it is "out of range" and we
must eliminate it (ie. we don't draw it!) Simple eh?! Here's some code
for this:
IF x_world >= camerapos_z THEN 'Don't PSET this point!
Please note that when you are doing a 3d engine you should NEVER use PSET
do draw everything in the world. That would be terribly slow. LINE is a
much faster alternative, however, I used PSET here in order to make the
explanation easier to understand.
Well, this concludes the first entry into the INTRODUCTION TO 3D SERIES. I
hope you enjoyed it! Next issue we'll be covering 3d rotation, how to code
a 3d program in which you can 'walk' about the world, and hidden surface
removal. We'll also add some source code to help ya out! ^_^
Cya next month!