Since I have been working on a 3D modeller (or editor, or drawing program, whatever), called 3DES Designer (or 3DES for short) for quite some time now, I figured it would be nice to combine the 3D tutorial with a 3DES tutorial, also because I have since received many emails regaring the use of the models created in 3DES. Soon I will release a 3DES SDK (or Software Development Kit) for use with your own programs.
As you might have noticed, the 3DES zipfile came with a small program called LOAD3DP.BAS which explained the 3DP file format that 3DES uses to store it's models. However, this is not sufficent for most users and therefore I will try to explain a little about the 3DES models in this article.
But first you'll have to understand the basics of 3D graphics, so here we go... Firstly, three dimensional objects consist of points in a 3D space, and for the totally braindead among us, three dimensional points have three coordinates: the X, Y and Z coordinates.
In maths classes at school (at least mine) they teach you Z is the horizontal axis and Y
is the axis that points into the depth... bummer for them, 'cause I hereby treat Z as the
'depth' axis, and X and Y as the 2D axis that lie on your computer screen... let's use a
nice ASCII drawing to support that:
(just imagine that the drawing is 3D and that the Z-axis points into the depth)
o--------> x-axis |\ | \ | \ z-axis | \/ y-axisMind that 3D coordinates are notated in the following order: X,Y,Z
FlatX = X * 256 / Z FlatY = Y * 256 / ZWhere FlatX and FlatY are the 2D coordinates that you can plot to the screen right away. Noticed the number 256 in there? Right, now that is the value that controls one of the most important things in the world of 3D graphics, perspective (meaning things get smaller the further they are away from the viewer). The larger the value, the less perspective in your object, keep that in mind. 256 is a pretty good 'default' value. You don't need to change it unless your model's perspective looks exaggerated or something.
Okay, so we've gotten quite far now. You now ought to know how to draw a 3D object
consisting of points on a 2D screen...
if that is still unclear, let me clarify it for you, here's a little source code to get you started:
-------------8<-------------8<-------------8<-------------8<------------- '// Ajust this value to load larger models or save memory CONST numberOfPoints = 100 '// Ajust this value to zoom in or out on the object CONST zoomLevel = 0 TYPE ThreeDeePoint X AS SINGLE Y AS SINGLE Z AS SINGLE END TYPE '// Set up an array of 3D points DIM MyArray(1 TO numberOfPoints) AS ThreeDeePoint '// Load a model into the arrayAnd voila! your model is here! Offcourse it still looks like shit, since you only used dots to draw the points.
'// Draw all the points FOR pointIdx = 1 TO numberOfPoints '// Do not draw points that are behind the screen IF MyArray(pointIdx).Z + zoomLevel > 0 THEN '// Translate points flatX = MyArray(pointIdx).X * 256 / (MyArray(pointIdx).Z + zoomLevel) flatY = MyArray(pointIdx).Y * 256 / (MyArray(pointIdx).Z + zoomLevel) '// Plot a white dot at the point's translated coordinates PSET (flatX, flatX), 15 END IF NEXT -------------8<-------------8<-------------8<-------------8<-------------
o - point 1 / \ / \ point 4 - o \ \ \ point 3 - o-----o - point 2The drawing above is a face consisting of four points, to draw it, just translate all four points to 2D, draw a line from point 1 to 2, 2 to 3, 3 to 4 and from 4 back to 1, and hey presto! A face!
So, with a little creativity, you can apply the face-technique to the sourcecode above,
making it a so-called wireframe 3D engine. Hurray!
Still, we are missing the main part of a true 3D engine... manipulation of the model. It's very nice and all, a still of a 3D model, but it's much more fun when the thing actually rotates around it's axis.
3D rotation is basically not very different from 2D rotation, not to say exactly the same.
The only thing you need to do is rotate each point three times, one time for each axis (X,Y and Z).
Rotating a 2D point can be accomplished by using this formula:
newX = COS(degrees) * X - SIN(degrees) * Y newY = SIN(degrees) * X + COS(degrees) * YTo translate a 3D point, you'll have to treat the rotation around each axis (3 in total) as a 2D rotation using the remaining two coordinates.
Assuming you put the above rotation function in a SUBroutine defined like this: SUB rotatePoint (X, Y, newX, newY, degrees), the correct code to rotate a point around the axis would be:
-------------8<-------------8<-------------8<-------------8<------------- '// around X-axis CALL rotatePoint (Z, Y, newZ, newY, degrees) '// around Y-axis CALL rotatePoint (X, Z, newX, newZ, degrees) '// around Z-axis CALL rotatePoint (Y, X, newY, newX, degrees) -------------8<-------------8<-------------8<-------------8<-------------Then all you have to do is just rotate all points like in the example above, then translate them and then draw the bloody thing =)
Well folks, that is the end of part 1, this series will be continued in future issues of the QB Times, see yers!