TECHNICAL GRAPHICS
by Toni Baker
part 2 of 3, ZX Computing February 1987

Toni Baker prepares you for a graphic encounter of the 3-dimensional kind.


In this article we start to look at the fundamentals of 3D - that is,
three dimensional space. A solid object - a cabbage for instance, has
three different dimensions - those of length, width and height. A flat
object - such as a picture of a cabbage - has only two dimensions -
length and width. As it happens, the image on the Spectrum's TV screen
is flat (two dimensional). Any picture which appears on this screen
must also be flat (two dimensional), which means that it is impossible
to produce truly three dimensional images (ie. solid images) on any
TV, no matter how hard you try. This would require the use of a true
three dimensional image system, such as a hologram. Some time in the
future home computers may indeed be able to produce true 3D
holographic images, but for the moment we are restricted to flatness.
We can, however, create an illusion of depth. This process is known,
perhaps mistakenly, as 3D-graphics.

The trick is to convert something which is three dimensional to a
representation which is two dimensional. Take the cabbage for
instance. Whilst a picture of a cabbage is only drawn onto a flat
surface, it nonetheless looks like a real cabbage. This, then, is the
key - we need a representation which is in fact a picture of something
three dimensional. This task seems to be much easier for humans than
it is for computers.


Things in space

The first thing we need to know is how to represent objects in three
dimensional space. Imagine a piece of paper (or, if your imagination
is not that good, use a real one). Now draw x and y axes on the paper,
with the origin near the bottom left-hand corner. The x axis goes off
to the right, whilst the y axis goes up towards the top of the paper.
Any point on the paper can be represented by two co-ordinates (x,y).
This is two dimensional co-ordinate geometry. The PLOT command on the
Spectrum uses this system, so you should be used to it.

Now imagine a third axis, also emanating from the same origin. This
axis is to go physically upwards, off the surface of the paper, away
from the table on which the paper is resting, and up towards the
ceiling of the room. This is the z axis. Any point in the room you are
now sitting may be specified by three co-ordinates (x,y,z). For
instance - take the paper itself. Any point on the paper which has two
dimensional co-ordinates (x,y) also has three dimensional co-ordinates
(x,y,0) with z being zero.

Imagine that a bumble bee enters the room and starts hovering just
inches above the origin drawn on the piece of paper. Measure the
height of the bumble bee above the origin, using the same units of
measurement as the x and y axes are measured in, and preferably
without being stung. Suppose the height of the bee was four units -
the co-ordinates of the bee would be (0,0,4). Suppose it buzzed three
units along in the direction of the x axis. Its co-ordinates would
then be (3,0,4). Finally, suppose it flew two units in the direction
of the y axis. Its co-ordinates would then be (3,2,4). This is three
dimensional co-ordinate geometry.

Armed with this knowledge, we can now start to think about solid
objects, and how they may be represented in this system. Imagine a
cube, ten units along each side. Place the cube, in your mind, with
one of its corners touching the origin. The cube should be sitting on
the piece of paper with its edges running parallel to the x, y and z
axes. Clearly, the co-ordinates of one of the corners is (0,0,0). It
doesn't take too much imagination to figure out that the remaining
seven corners have co-ordinates (0,0,10), (0,10,0), (0,10,10),
(10,0,0), (10,0,10), (10,10,0) and (10,10,10), but these co-ordinates
are not sufficient to define a cube - all they define are eight dots,
four of them on the paper, and the other four floating in space ten
units above the paper. What about the cube itself?


On edge

Since this series is concerned only with line drawings, the only thing
we will need to know about the cube are its lines - or edges. This
means that we need to record which points are connected to which other
points.

Look at Figure One [TECH2_1.GIF]. This is a drawing of a cube, but
with every vertex (corner) marked with the letter P and a number
between one and eight, and with every line marked with the letter L
and a number between one and twelve. Notice that there are more lines
than there are vertices.

Figure Two shows a BASIC program which draws the cube in Figure One.
Don't worry too much at the USR statement in line 540 - it's just the
points and lines we're interested in at the moment. Line 10 dimensions
an array P() to hold all the points. It is dimensioned eight by three
because there are eight points, and three co-ordinates for each point.
Line 20 dimensions an array L() to hold all the lines. It is
dimensioned twelve by two because there are twelve lines, and two
points at the two ends of each line.

Lines 30 to 110 initialise the array P() to hold the co-ordinates of
each of the corners of the cube in such a way as to maintain the
numbering in Figure One. Lines 120 to 190 initialise the array L().
Note that this time we have to use DATA because there's no easy
mathematical way to work them all out as there was with the vertices.
The rest of the program just draws the cube. You can run this program
if you like, but make sure that the machine code is in place first.

Incidentally, if you change lines 60 to 80 so that they end 8*K, 10*J
and 12*I respectively then you'll get a cuboid, not a cube - a
rectangular block. Try it - it presents a much more pleasing picture
because the front and back corners don't overlap.

This brings us to the most important question of all. How does it all
work? We need to understand the general principle of converting a
three dimensional solid object down to a two dimensional picture. Look
again at Figure One. Notice that, for instance, line L7 is connected
to points P7 and P8 - but figure one is a picture, not a real cube. In
other words, line L7 is connected to points P7 and P8 both in the real
three dimensional cube, and in the two dimensional picture. This is
true for all of the lines, not just for L7. Although this may seem
stunningly obvious, it is nonetheless the most important piece of
information in 3D graphics. It means that if you can work out
whereabouts on the screen the image of P7 will fall, and if you can
also work out whereabouts on the screen the image of P8 will fall,
then it is obvious that the image of the line L7 will just be a
straight line connecting the image of P7 with the image of P8. This we
can do on the Spectrum's screen using PLOT and DRAW as normal in
BASIC. All we now need is a method for working out the position on
screen of the images of all the points.

There are many, many methods of transforming three dimensional
co-ordinates down to two dimensional co-ordinates. The simplest
possible means is just to throw away the z co-ordinate leaving just x
and y. This gives you a plan view of the object - not very
satisfactory, however - we need something a bit more daring than that.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Figure 2

  10 DIM p(8,3)
  20 DIM l(12,2)
  30 FOR i=0 TO 1
  40 FOR j=0 TO 1
  50 FOR k=0 TO 1
  60 LET p(4*i+2*j+k+1,1)=10*k
  70 LET p(4*i+2*j+k+1,2)=10*j
  80 LET p(4*i+2*j+k+1,3)=10*i
  90 NEXT k
 100 NEXT j
 110 NEXT i
 120 FOR i=1 TO 12
 130 FOR j=1 TO 2
 140 READ l(i,j)
 150 NEXT j
 160 NEXT i
 170 DATA 1,2,2,4,4,3,3,1
 180 DATA 5,6,6,8,8,7,7,5
 190 DATA 1,5,2,6,4,8,3,7
 200 FOR i=1 TO 12
 210 LET a=1: GO SUB 500
 220 LET p1=5*p+128
 230 LET q1=5*q+88
 240 PLOT p1,q1
 250 LET a=2: GO SUB 500
 260 DRAW 5*p+128-p1,5*q+88-q1
 270 NEXT i
 280 STOP 
 500 LET a=l(i,a)
 510 LET x=p(a,1)
 520 LET y=p(a,2)
 530 LET z=p(a,3)
 540 RANDOMIZE USR 33320
 550 RETURN 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


Projection

The method we shall use is a technique called Isometric Projection.
The idea is that you have to imagine a camera floating in space
looking at the object. In isometric projection the camera is always
located at co-ordinates (N,N,N). N can be any, very large, positive
number - the larger the better, since the camera is assumed to be a
long way from the origin. The camera is pointing directly towards the
origin. It is the right way up, and it has a very powerful zoom lens,
so it can see the object (which is located at or near the origin). The
image that the camera would see is the picture which is to appear on
the screen.

There are other types of projection (many other types), which have the
camera and the object at different positions in space, but the idea is
always the same - what the camera sees, the Spectrum draws.

In future issues, I will show you how to use all these other
projections, but for now we shall concentrate on isometric. It is
sufficiently powerful to be able to demonstrate the basic ideas of 3D
and projection, whilst at the same time it is sufficiently simple
(mathematically speaking) so that anyone who knows anything about
BASIC will be able to understand it.

Let's look at the mathematical side of things first, shall we? Suppose
a point in three dimensional space has co-ordinates (x,y,z) - any
point will do. Suppose also that the image of this point appears on
the screen with PLOT co-ordinates (p,q). What we need to know is how
we can calculate p and q, given only x, y and z.

The solution turns out to be so easy that we can do the task in BASIC.
The following two LET statements will make the projection:

	LET p=SQR(3)*(y-x)/2
	LET q=z-(y+x)/2

In other words, we can do the whole task in BASIC - we don't need any
machine code at all. We can define the points in space and the lines
joining them; we can transform the points using the above formulae; we
can PLOT the new points, and we can DRAW the connecting lines. All
very easy.

The machine code I have included is really only intended to work out
the above formulae - that is - given x, y and z the machine code will
work out the values of p and q. Despite being in machine code, the
machine code program uses the values from BASIC variables, and assigns
BASIC variables with the results. You may care to examine the machine
code to see how this is achieved. None of it is really difficult - it
all hinges on the way that BASIC variables are stored in the variables
area.

In next month's article - which will be the final part of this series
- we shall look at isometric projection a little deeper. We shall use
it to draw three dimensional graphs, using the simplest of hidden-line
algorithms so that lines which would be hidden to the camera won't be
drawn on the screen. And - oh yes - there will be lots of machine code
involved.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Listing 1

8200 2A4B5C   SEARCHVAR LD   HL,(VARS)     ;HL points to variables area
8203 7E       S_V_LOOP  LD   A,(HL)        ;A= next variable byte
8204 E67F               AND  #7F           ;Ignore bit 7
8206 37                 SCF
8207 C8                 RET  Z             ;Return with Carry set if byte 80h
                                           ;reached (ie. if variable not found)
8208 B9                 CP   C
8209 C8                 RET  Z             ;Return with Carry reset if
                                           ;variable found
820A C5                 PUSH BC            ;Stack variable name searched for
820B CDB819             CALL NEXT_ONE      ;DE points to next variable
820E EB                 EX   DE,HL         ;HL points to next variable
820F C1                 POP  BC            ;C= variable name
8210 18F1               JR   S_V_LOOP      ;Jump back to continue search

8212 0E7A     STK_ZYX   LD   C,#7A         ;C= code for variable Z
8214 CD1E82             CALL GET_VAR       ;Stack variable Z
8217 0E79     STK_YX    LD   C,#79         ;C= code for variable Y
8219 CD1E82             CALL GET_VAR       ;Stack variable Y
821C 0E78               LD   C,#78         ;C= code for variable X
821E CD0082   GET_VAR   CALL SEARCHVAR     ;Search for variable
8221 DA2E1C             JP   C,REPORT_2    ;Error if variable not found
8224 23                 INC  HL            ;HL points to variable contents
8225 C3B433             JP   STACK_NUM     ;Stack the variable contents onto
                                           ;the calculator stack, and return

8228 CD1782   TRANSFORM CALL STK_YX        ;Get Y and X onto calculator stack
822B EF                 RST  #28           Y,X
822C 03                 subtract           Y-X
822D 3440B00003         stk data 3         Y-X,3
8232 28                 sqr                Y-X,SQR(3)
     04                 multiply           SQR(3)*(Y-X)
8234 A2                 const half         SQR(3)*(Y-X),1/2
8235 04                 multiply           SQR(3)*(Y-X)/2
8236 38                 endcalc
8237 0E70               LD   C,#70         ;C= code for variable P
8239 CD4782             CALL ASSIGN_VAR    ;LET P=SQR(3)*(Y-X)/2
823C CD1282             CALL STK_ZYX       ;Get Z,Y,X onto calculator stack
823F EF                 RST  #28           Z,Y,X
8240 0F                 add                Z,Y+X
8241 A2                 const half         Z,Y+X,1/2
8242 04                 multiply           Z,(Y+X)/2
8243 03                 subtract           Z-(Y+X)/2
8244 38                 endcalc
8245 0E71               LD   C,#71         ;C= code for variable Q
8247 CD0082   ASSIGNVAR CALL SEARCHVAR     ;Search for variable
824A 300A               JR   NC,ASSIGNVA2  ;Jump if variable located
824C C5                 PUSH BC            ;Stack code for variable name
824D 010600             LD   BC,#0006
8250 CD5516             CALL MAKE_ROOM     ;Create room for variable
8253 23                 INC  HL            ;HL points to start of new room
8254 C1                 POP  BC            ;C= code for variable name
8255 71                 LD   (HL),C        ;Store the variable name
8256 23       ASSIGNVA2 INC  HL            ;HL points to variable contents
8257 E5                 PUSH HL            ;Stack address of variable contents
8258 CDBF35             CALL STK_PNTRS     ;HL= address of last item on stack
825B 22655C             LD   (STKEND),HL   ;Delete the item from the stack
825E D1                 POP  DE            ;DE points to variable contents
825F 010500             LD   BC,#0005
8262 EDB0               LDIR               ;Copy number into variable
8264 C9                 RET                ;Return
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

