3D graphics is what games are all about today. At the time the Commodore 64 and other 8 bit computers were common, 2D games were the most popular. Still, some 3D titles were available for these machines, and they represented technical marvels at the time. I think Freescape games (like Driller or Castle Master) were the most advanced 3D software available back then. The Sinclair Spectrum could offer very good speed performances with such games, while the Commodore 64 was somewhat slower. But, it could offer better colors and in-game music. As mathematics is all that is behind 3D vector graphics, the Z80 usually enjoys an advantage over the 6510 as it is slightly faster and it has 16 bit internal registers. The Commodore 64 can do the calculations required as well, but due to the pure 8 bit nature of the 6510 and its clock speed, calculations will take more time. Bear in mind however that Z80 instructions usually require more cycles than 6510 ones, so the Z80 is not as faster as the clock speed ratio may lead you think. Still, efficient programming allows for nice 3D performances on the Commodore 64 as well, and games like “Stunt Car Racer” are an evidence of this.
But what’s inside 3D graphics? First of all, we are talking about true 3D graphics here, that is, 3D graphics based on vector calculations. 3D effects may be achieved even without using vectors actually, but such routines are not true 3D (this is an example).
What is a vector? On a 2D plane (that is, a drawing sheet or the screen) each point may be represented mathematically by using a vector. A coordinate system can be used, so that you can tell the position of each point.
Two axes (x and y) are used (they are positive in the direction of the arrows). The point P can be found on the plane by using the coordinates xp (x coordinate) and yp (y coordinate). The point can be expressed as P (xp, yp). This is called a vector, as it is not a simple number but a couple of numbers (this is NOT the true definition of a vector actually, but that’s just what can be enough here).
On 3D space, three axes are necessary. That means, a point on space can be found by using three coordinates (x, y and z coordinate). On 2D you have width and height – 3D adds dept.
So, a point on space can be represented by the vector P(x1, y1, z1). Just imagine a vector as a set of given coordinates that make up a point.
A wireframe 3D cube is a cube whose vertexes are represented by vector points, joined together by lines. That’s exactly what we will be drawing. So, we just have to find the coordinates of each vertex, like on the previous picture.
If we center the cube to the origin O, the coordinates of the centre of the cube are of course (0, 0, 0) and if the size of the cube is 2*L, it’s easy to see that its vertexes can be represented by the following vectors:
p1 = (-L, -L, -L) p2 = (-L, L, -L) p3 = (L, L, -L) p4 = (L, -L, -L) p5 = (-L, -L, L) p6 = (-L, L, L) p7 = (L, L, L) p8 = (L, -L, L)
Now, the problem is drawing the cube. As the screen is a 2D plane, how dept can be represented?
We need a formula to project the points that is capable of keeping dept into account. That way, we will make the illusion of a solid object, even if it is drawn on the plane.
Vertex coordinates on the screen (two coordinates) can be calculated as follows:
vx = 160 + (x*fs)/(z + fs) vy = 100 + (y*fs)/(z + fs)
vx and vy are just the x and y coordinates of the point to plot on the screen.
fs is a scale factor that determines how much the cube is zoomed. In the code that will follow a value of 200 has been used. As you can see, x and y coordinates are transformed using the dept z. That is what is giving the illusion of dept that we need.
The numbers 160 and 100 are dealing with the resolution of the screen. As the Commodore 64 screen is 320 x 200, the theoretical origin (0,0) used earlier actually becomes (160,100). And all points are simply translated like that. We will use the 320 x 200 resolution even on the PC, just to have an idea of what the C64 version may look like.
Once we have drawn the cube, we can rotate it. Rotation of a solid can be performed about the x, y or z axes. Rotations can be combined so that a more sophisticated movement can be achieved.
The idea is to use mathematical relations that will change the coordinates of a point according to the rotation angle. If we want to rotate the cube about the z axes, only x and y coordinates must be changed. If we want to rotate the cube about the x axes, only the y and z coordinates must be changed, and so on. Those transformations can be expressed as linear combinations of the coordinates of the point to be rotated and of the sine and cosine functions evaluated on the rotation angle.
Without any further explanation, here is the Freebasic (PC) code:
The cube is drawn by plotting lines between its vertexes. Notice that the code here is quite simple and it does not perform hidden lines clipping. So, the shape of the cube may be a little confusing at times, but its geometry is actually correct.
A simple Simons’ BASIC version that can be run on the Commodore 64 is as follows:
Simons’ BASIC can be downloaded here.
The Simons’ BASIC version is obviously quite slow, but it demonstrates the concept. If you use a C64 emulator (for instance, X64 on VICE), it is possible to set emulation speed to 1500% so that the animation can be performed at a decent speed.
Machine language is the key to get such a program running fast on the Commodore 64, that’s clear. We already have the instruments needed to code such a program, as we have already coded programs that can draw lines, perform multiplications and divisions (please check that same line drawing program and this article), evaluate sine and cosine functions. We just have to put things together. But, those programs are not optimized in order to get good performances on 3D. The approach used on the lines drawing program has been useful to test my integer math routines, but it was not aimed at speed. So, simpler and faster line drawing routines must be developed.
A Commodore 64 assembly implementation can be found on this article.