# DENTHOR/ASPHYXIA'S VGA TRAINERS 3D

Hello everybody! Christmas is over, the last of the chocolates have been eaten, so it’s time to get on with this, the eighth part of the ASPHYXIA Demo Trainer Series. This particular part is primarily about 3-D, but also includes a bit on optimization.

If you are already a 3D guru, you may as well skip this text file, have a quick look at the sample program then go back to sleep, because I am going to explain in minute detail exactly how the routines work ;)

DENTHOR, coder for ... _____ _____ ____ __ __ ___ ___ ___ ___ __ _____ / _ \ / ___> | _ \ | |_| | \ \/ / \ \/ / | | / _ \ | _ | \___ \ | __/ | _ | \ / > < | | | _ | \_/ \_/ <_____/ |__| |__| |__| |__| /__/\__\ |__| \_/ \_/ smith9@batis.bis.und.ac.za The great South African Demo Team! Contact us for info/code exchange!

Grant Smith, alias Denthor of Asphyxia, wrote up several articles on the creation of demo effects in the 90s. I reproduce them here, as they offer so much insight into the demo scene of the time.

These articles apply some formatting to Denthor's original ASCII files, plus a few typo fixes.

## Optimization

Before I begin with the note on 3-D, I would like to stress that many of these routines, and probably most of your own, could be sped up quite a bit with a little optimization. One must realize, however, that you must take a look at *WHAT* to optimize… converting a routine that is only called once at startup into a tightly coded assembler routine may show off your merits as a coder, but does absolutely nothing to speed up your program. Something that is called often per frame is something that needs to be as fast as possible. For some, a much used procedure is the `PutPixel`

procedure. Here is the `putpixel`

procedure I gave you last week:

*NOTE: Don’t take my clock ticks as gospel, I probably got one or two wrong.*

Right, now for some optimizing. Firstly, if you have 286 instructions turned on, you may replace the 6 `shl,1`

with `shl,6`

. Secondly, the Pascal compiler automatically pushes and pops `ES`

, so those two lines may be removed. `DS:[SI]`

is not altered in this procedure, so we may remove those too. Also, instead of moving `COL`

into `ah`

, we move it into `AL`

and call `stosb (es:[di]:=al; inc di)`

. Let’s have a look at the routine now:

Now, let us move the value of `BX`

directly into `DI`

, thereby removing a costly `push`

and `pop`

. The `MOV`

and the `XOR`

of `DX`

can be replaced by its equivalent, `SHL DX,8`

.

As you can see, we have brought the clock ticks down from 153 ticks to 71 ticks… quite an improvement. (The current ASPHYXIA putpixel takes 48 clock ticks). By going through your routines a few times, you can spot and remove unnecessary instructions, thereby greatly increasing the speed of your program.

## Defining a 3-D object

Drawing an object in 3-D is not that easy. Sitting down and plotting a list of X,Y and Z points can be a time consuming business. So, let us first look at the three axes you are drawing them on:

X is the horizontal axis, from left to right. Y is the vertical axis, from top to bottom. Z is the depth, going straight into the screen.

In this trainer, we are using lines, so we define 2 X,Y and Z coordinates, one for each end of the line. A line from far away, in the upper left of the X and Y axes, to close up in the bottom right of the X and Y axes, would look like this:

## Rotating a point with matrixes

Having a 3D object is useless unless you can rotate it some way. For demonstration purposes, I will begin by working in two dimensions, X and Y.

Let us say you have a point, A,B, on a graph.

Now, let us say we rotate this point by 45 degrees anti-clockwise. The new A,B can be easily be calculated using sin and cos, by an adaption of our circle algorithm, i.e.

I recall that in standard 8 and 9, we went rather heavily into this in maths. If you have troubles, find a 8/9/10 maths book and have a look; it will go through the proofs etc.

Anyway, we have now rotated an object in two dimensions, AROUND THE Z AXIS. In matrix form, the equation looks like this:

I will not go too deeply into matrixes math at this stage, as there are many books on the subject (it is not part of matric maths, however). To multiply a matrix, to add the products of the row of the left matrix and the column of the right matrix, and repeat this for all the columns of the left matrix. I don’t explain it as well as my first year maths lecturer, but have a look at how I derived A2 and B2 above. Here are the other matrices:

Matrix for rotation around the Y axis:

Matrix for rotation around the X axis:

By putting all these matrixes together, we can translate out 3D points around the origin of 0,0,0. See the sample program for how we put them together.

In the sample program, we have a constant, never changing base object. This is rotated into a second variable, which is then drawn. I am sure many of you can thing of cool ways to change the base object, the effects of which will appear while the object is rotating. One idea is to “pulsate” a certain point of the object according to the beat of the music being played in the background. Be creative. If you feel up to it, you could make your own version of transformers ;)

## Drawing a 3D point to screen

Having a rotated 3D object is useless unless we can draw it to screen. But how do we show a 3D point on a 2D screen? The answer needs a bit of explaining. Examine the following diagram:

Let us pretend that the centre of the screen is the horizon of our little 3D world. If we draw a three dimensional line from object “o” to the centre of the eye, and place a pixel on the X and Y coordinates where it passes through the screen, we will notice that when we do the same with object o1, the pixel is closer to the horizon, even though their 3D X and Y coords are identical, but “o1”’s Z is larger then “o”’s. This means that the further away a point is, the closer to the horizon it is, or the smaller the object will appear. That sounds right, doesn’t it? “But,” I hear you cry, “how do we translate this into a formula?” The answer is quite simple. Divide your X and your Y by your Z. Think about it. The larger the number you divide by, the closer to zero, or the horizon, is the result! This means, the bigger the Z, the further away is the object! Here it is in equation form:

*NOTE: Zoff is how far away the entire object is, Xoff is the object’s X value, and Yoff is the objects Y value. In the sample program, Xoff starts off at 160 and Yoff starts off at 100, so that the object is in the middle of the screen.*

The 256 that you multiplied by is the perspective with which you are viewing. Changing this value gives you a “fish eye” effect when viewing the object. Anyway, there you have it! Draw a pixel at `nx`

,`ny`

, and voilá! you are now doing 3D! Easy, wasn’t it?

## Possible improvements

This program is not the most optimized routine you will ever encounter (;-)) … it uses 12 `mul`

s and 2 `div`

s per point. (Asphyxia currently has 9 `mul`

s and 2 `div`

s per point) Real math is used for all the calculations in the sample program, which is slow, so fixed point math should be implemented (I will cover fixed point math in a future trainer). The line routine currently being used is very slow. Chain-4 could be used to cut down on screen flipping times.

Color values per line should be added, base object morphing could be put in, polygons could be used instead of lines, handling of more than one object should be implemented, clipping should be added instead of not drawing something if any part of it is out of bounds.

In other words, you have a lot of work ahead of you ;)

## In closing

There are a lot of books out there on 3D, and quite a few sample programs too. Have a look at them, and use the best bits to create your own, unique 3D engine, with which you can do anything you want. I am very interested in 3D (though EzE and Goth wrote most of ASPHYXIA’S 3D routines), and would like to see what you can do with it. Leave me a message through one of the means described above.

I am delving into the murky world of texture mapping. If anyone out there has some routines on the subject and are interested in swapping, give me a buzz!