Writer: Matthew River Knight
Welcome back! Are you ready to get back into action and break the barriers of the third dimension? Yes? Let's get crackin' then! ^_^
We covered some very simple stuff last issue. We learned how to define our 3d world coordinates, how to convert these world coordinates into camera coordinates, and finally how to convert the 3d camera coordinates into 2d screen coordinates. You will recall that we also covered some of the problems that you are likely to encounter, and we fixed them :)
There is a lot that we have to cover this issue. Firstly, we need to learn how to make our 3d world rotate. Another thing is that thus far we have only dealt with wireframe 3d. You are unlikely to come across a wireframe 3d game in the shop, so why should we do it with Qbasic?! Pardon? Did I hear you say that Qbasic is possibly too slow? Oh nonsense! I'll teach you how to get rid of any possible slowdown...so you can't blame Qbasic! And anway, a bad workman always blames his tools! So we are going to push the wireframe aside, and learn how to generate filled polygons in QB! Yep, it's possible! ^_^
Before we start learning anything new, it is necessary that I mention one little thing. You may have read some other 3d tutorials before, and you then will have noticed that the formulae they use are very different to the one's we have been using in this tutorial. This requires some explaining. There are MANY different methods of doing 3d. I know of about five different methods myself...I'm sure there are many more that have yet to be descovered. In just about every 3d tutorial I have ever read, they use a different method of doing 3d. It actually starts to get quite confusing...you are left wondering which writer you should believe...which method is best, and so on. Well, push all your worries aside, because the methods of doing 3d that are described in this tutorial series are ALWAYS the best methods I know of, and in most cases, are easier to understand and generally more logical.
Okay, I'm done extrapolating...let's get down to business!!!
To start with, we are going to cover 3d rotation. Rotation is a very important elemant of any 3d program. In any 3d game you may have, notice that in order to look around, the world seems to rotate around you. Now believe it or not, the 3d world really is rotating around you! Well...not exactly...but we'll get to that just now...let's take this one step at a time.
In order to make your 3d world/object rotate, you have to rotate all of the world coordinates around a point. But which point? Simple. The formulae which we are about to descover will ALWAYS rotate the world coordinates around the center of the world (0,0,0). Simple! ^_^
Now for the formulae!!! Hmmmm...before I say anything else, I have to explain one simple thing. In order to understand these formulae, it is necessary that you have a knowledge of trigonometry. The trig that you'll need to know isn't that difficult...you will only need to know the most elementary concepts of it...but I am no math teacher, so I am not going to explain it to you. I'm sure you will be able to find a decent book at your nearest public library with information on simple trig. What? Did you say that math is so boring? Rubbish! As I have said time and time again, mathematics is only boring if you don't have a use for it. I also used to find math boring...but when I started programming, I suddenly realised how much I needed to know math, and so the subject suddenly became utterly facinating. It will for you too!
Once you have mastered the basics of trigonometry, it will immediately become clear how to do rotation in 3d. You'll understand right away. But for those of you who are too lazy to figure out the formulae on your own, I have listed them here for you! You don't need to know how we came up with the formulae in order to use them...however, I personally like to learn these sorts of things...maybe you will too...so it is worth looking into understanding the formulae. Note that in these formulae, x', y' and z' represent the values of x, y and z, respectively, prior to transformation. Let me also just remind you that these formulae work with the world coordinates.
The first set of algorithms is for rotation about the x axis:
x = x' y = (sin(angle) * z') + (cos(angle) * y') z = (cos(angle) * z') - (sin(angle) * y')
The second set of algorithms is for rotation about the y axis:
x = (cos(angle) * x') - (sin(angle) * z') y = y' z = (sin(angle) * x') + (cos(angle) * z')
The third set of algorithms is for rotation about the z axis:
x = (cos(angle) * x') + (sin(angle) * y') y = (cos(angle) * y') - (sin(angle) * x') z = z'
By using these three sets of algorithms, it is possible to rotate a 3d object in literally any direction!!! Cool huh?! ^_^
Oh yeah...very important point...the trigonometric functions provided by Qbasic (SIN, COS, etc) require the angle argument to be in radians. Because it is easier and more natural to think in degrees, a simple conversion can be used to convert degrees to radians:
Radians = Degrees * .017453 Degrees = Radians * 57.29577
Simple! With what you now know, you can create a 3d object/world, and rotate it in any direction you want! Now that wasn't so hard was it?! ;)
Now it's time to discuss some optimizations! The SIN, COS, etc. functions are quite slow. In order to get your program running faster, it would be wise to create what is known as trig tables. But what the heck is a trig table?! Heh, it is basically a very grand sounding name for something that is actually very simple. What you do is create two arrays. In the one array you save all the values of COS. In the next you save all the values of SIN. Now instead of using the SIN and COS functions in your calculations, work with the array values instead! Simple! The result will be a program that is MUCH faster than it would otherwise have been!!! ^_^
Okay, so now we have a rotating 3d object...but wouldn't it be awesome if we could 'walk' around inside that 3d object, as seen in games like Quake?! Heh, well, it is actually very simple to do that!
Now there are A LOT of ways to do this, but I am going to describe the method which I find easiest to understand. Basically, although it may seem logical to move the camera around in order to 'walk' in your 3d world, it doesn't work that way. Try it. You'll see what I mean. So what do we do? It's easy... imagine you have a flat piece of ground in space...you are facing in any given direction, and are standing roughly in the center of this piece of ground...now, in order to move forward, you could add 1 to each of the Z values in the world coordinates! Then you would be further forward on that piece of ground! To move backwards, all you have to do is subtract 1 from each of the Z values of the world coordinates! Could life possibly be any easier?! ^_^
For an example of everything that you have learned so far, check out 3DPROGGY.BAS which has been included with this issue of QBCM! It is fully commented, and will help you develop an even greater insight into the totally awesome world of 3d in Qbasic!!! ^_^
Three-dimensional drawing can become very complex. Most three-dimensional models are created with a series of planes that represent the shell of the object. If the planes are filled, then the plane is considered to be nontransparent. Similarly, if the plane is not filled, the plane is considered to be transparent.
When rotating or moving three-dimensional objects, it is often necessary to remove parts of objects, or even entire objects, in order to provide realistic representations of the environment. The method by which these objects are altered is called hidden surface removal. The most common types of hidden surface removal are discussed in this tutorial.
There are two basic types of hidden surface removal. These are object-space methods and image-space methods. Three-dimensional information is used with object-space methods to decide which surfaces should be hidden and which surfaces should overlay others. Image-space methods use two-dimensional information to determine the hidden surfaces.
The most common method of hidden surface removal for personal computers is probably the plane equation method, which is an object-space method. In general terms, the plane equation method determines if a point is in front of, on, or behind a specified plane. By testing each point against the viewing position, always (0,0,0), the visible and hidden planes are determined.
The equation of a plane is:
Ax + By + Cz + D
where x, y, and z define a point on the surface of the plane. The A, B, C, and D values are constants and are derived as follows when three points on the plane are specified (x1,y1,z1 ; x2,y2,z2 ; x3,y3,z3).
A = y1(z2-z3) + y2(z3-z1) + y3(z1-z2) B = z1(x2-x3) + z2(x3-x1) + z3(x1-x2) C = x1(y2-y3) + x2(y3-y1) + x3(y1-y2) D = -x1(y2z3-y3z2) - x2(y3z1-y1z3) - x3(y1z2-y2z1)
By identifying three points on a plane, solving for A, B, C, and D, substituting A, B, C, and D into the plane equation, and passing each object point through the new plane equation, you can determine whether or not each point is on, in front of, or behind the defined plane. If the plane equation evaluates to a positive value, the point is hidden. If the plane equation evaluates to zero, the point is on the plane and is usually defined as visible. If the equation evaluates to a negative value, the point is visible.
When using this method it is important that the points used to derive the equations are plotted in a counterclockwise direction and can be viewed as part of a convex polyhedron. A convex polyhedron is a figure that has many faces and is curved outward, such as a cube.
Whew! What a huge entry into the series this has been! With what you now know, it will be possible for you to do some really cool stuff. If you make anything cool then please send me a copy! This entry is the last in this 3d programming series. I had originally intended it to continue for at least another month, however, it seems that I have covered everything I wished to discuss already! There is still more to learn...there's always more to learn, but I think this information is more than enough to get you up and running.
Good luck with your 3d programming! ^_^