3D Graphics in Full BASIC

Projective Transformation in Space

Let A=(aij) be a 4 by 4 matrix.
A transformation that moves a point ( x, y, z ) to the point (x'/c, y'/c, z'/c) where




( x' y' z' c ) = ( x y z 1 )
(
a11 a12 a13 a14
a21 a22 a23 a24
a31 a32 a33 a34
a41 a42 a43 a44
)

is called a projective transformation determined by A.

The concept of Projective transformations contains congruent transformations, similar transformations and affine transformations.
For example, the rotation about the x-axis by θ is a projective transformation determined by a matrix

(
1    0 0 0
0 cosθ sinθ 0
0 -sinθ cosθ 0
0 0 0 1
)

the rotation about the x-axis by θ is a projective transformation determined by a matrix

(
cosθ 0 -sinθ 0
0 1    0 0
sinθ 0 cosθ 0
0 0 0 1
)

Furthermore, the translation determined by a vector(a, b, c) is a projective transformation determined by a matrix

(
1    0    0    0
0 1 0 0
0 0 1 0
a b c 1
)

Note.
Transformations are represented in row vectors in Full BASIC. Thus the matrix that represents the composite transformation of a transformation represented by a matrix A and a transformation represented by a matrix B is A*B.

Transformation of a picture with matrices

A DRAW statement can transform the picture by including a 4 by 4 matrix in the WITH-clause.

Let A be a 4 by 4 matrix declared as DIM A(4,4).
DRAW a_pict with A transforms a picture a_pict using a matrix, provided that z-coordinates are ignored when the image is drawn on the screen.
Any product of an arbitrary number of 4-by-4 matrices or supplied transform functions can be written in a WITH-clause of a DRAW statement. Multiplication is represented by a symbol *.


Supplied transform functions are defined as follows, for example,



ROTATE(α) =
(
cosα sinα 0 0
-sinα cosα 0 0
0 0 1    0
0 0 0 1
)


SHIFT(a,b) =
(
1    0 0 0
0 1    0 0
0 0 1    0
a b 0 1
)



For example, preparing a matrix that represents the transformation in which y-coordinates are converted to x-coordinates, z-coordinates are converted to x-coordinates and x-coordinates are converted to z-coordinates



A =
(
0 0 1    0
1    0 0 0
0 1    0 0
0 0 0 1
)

and a matrix that represents the transformation in which x-coordinates are converted to y-coordinates, y-coordinates are converted to z-coordinates and z-coordinates are converted to x-coordinates



B =
(
0 1    0 0
0 0 1    0
1    0 0 0
0 0 0 1
)

enables writing a matrix that represents the rotation about the x-axis by θ as A*ROTATE(θ)*B.

Example
The external picture "tetra" described in 1000 line or later on the following program draws all edges of a regular tetrahedron that has a base that lies in the xy-plane and its barycenter is located at the origin and has a vertex at the point (1,0,0), while the details are explained later.
The following program draws a "tetra" rotating about the x-axis by 120°.

100 DECLARE EXTERNAL PICTURE tetra
110 OPTION ANGLE DEGREES
120 DIM a(4,4), b(4,4)
130 MAT READ a
140 DATA 0,0,1,0
150 DATA 1,0,0,0
160 DATA 0,1,0,0
170 DATA 0,0,0,1
180 MAT READ b
190 DATA 0,1,0,0
200 DATA 0,0,1,0
210 DATA 1,0,0,0
220 DATA 0,0,0,1
230 SET WINDOW -2,2,-2,2
240 DRAW tetra WITH a*ROTATE(120)*b
250 END
260 !
1000 EXTERNAL PICTURE tetra
1010 OPTION ANGLE DEGREES
1020 PICTURE face
1030    PLOT LINES: 1,0; COS(120),SIN(120); COS(240),SIN(240); 1,0
1040 END PICTURE
1050 DIM ry(4,4)
1060 MAT ry=IDN                                          ! IDN represents an identity matrix
1070 LET ry(1,1)=1/3
1080 LET ry(1,3)=-SQR(8)/3
1090 LET ry(3,1)=SQR(8)/3
1100 LET ry(3,3)=1/3
1110 DRAW face
1120 DRAW face WITH SHIFT(1/2,0)*ry*SHIFT(-1/2,0)
1130 DRAW face WITH SHIFT(1/2,0)*ry*SHIFT(-1/2,0)*ROTATE(120)
1140 DRAW face WITH SHIFT(1/2,0)*ry*SHIFT(-1/2,0)*ROTATE(240)
1150 END PICTURE  

Note. DECLARE EXTERNAL PICTURE statement in 100 line may be able to be omitted in the past and current versions of Decimal BASIC. But the Full BASIC standard requires this declaration.

Picture Definitions that draw three-dimensional shapes

Full BASIC has drawing commands that act only on the xy-plane, but transforming a picture which contains drawing commands enables drawing points, lines, or areas in space.
For example, drawing commands are located in the picture "face", lines from 1020 to 1040. Transforming "face" enables drawing faces in space.

Making a picture definition that draws all edges of a regular tetrahedron.

The picture definition "face", lines from 1020 to 1040 in the above program, draws on the xy-plane a regular triangle that has a barycenter at the origin and has a vertex at the point (1, 0, 0), which is the base.
Denoting the face angle of a regular tetrahedron as α, we have cosα = 1/3, sinα = SQR(8)/3, so, we prepare a matrix "ry" which represents the rotation about the y-axis by α.



ry =
(
cosα 0 -sinα 0
0 1    0 0
sinα 0 cosα 0
0 0 0 1
)

As no computational expressions can be written in DATA statements, we make such matrix by assigning an identity matrix and replace the elements that differ from the identity as shown in lines from 1060 to 1100.
A face of a regular tetrahedron can be obtained by rotating the base about the line x=-1/2 by α. This transformation can be made by translating as the line x=-1/2 moves to the y-axis and rotating about the y-axis and translating as the y-axis moves the line x=-1/2 as shown in line 1120.
The other faces can obtained by rotating this face about the z-axis by 120°or 240°(as shown in lines 1130, 1140).

Drawing Faces

When we draw a face, we must distinguish the face is visible or not.
In case of drawing convex a polyhedron as a regular polyhedron, we can use a method that we define the direction of a face and draw a face if its direction is forward.
We adopt right-handed coordinate system, so the positive direction of the z-axis is front of the screen. Hence we draw a face the z-coordinate of whose direction is positive.
Full BASIC provides us with a matrix function TRANSFORM that represents the transformation matrix applied for drawing commands in the picture definition currently executed. Using it, we can obtain the converted normal vector of a face that directs the positive direction of it. Furthermore, we can draw a face varying the brightness according to the angle between the normal vector and the light source.

Drawing a Regular Tetrahedron

Now we draw a tetrahedron a edge of a base of which is parallel to the x-axis and a vertex of which lies on the z-axis.

We prepare a picture definition that draw a equilateral triangle a side of which lies on the x-axis and a vertex of which lies on the y-axis and the side length of which is 2, and make the other sides by transforming.

1210 EXTERNAL PICTURE face
1260    PLOT AREA: -1,0; 1,0; 0, SQR(3)  
1280 END PICTURE


Because the cosine of the angle between the lateral side and the base is 1/3, we find the angle α such that cosα = 1/3, and rotate "face" about the x-axis by α to obtain a prototype of lateral sides. We want to make the top vertex lie on the z-axis, so we translate it by SQR(3)/3 to the negative direction of the y-axis. And we draw it rotated about the z-axis by 120°and 240°, then we have three lateral side.
As the right side of the base must be downward, we turn over the face and translate it by SQR(3)/3 to the negative direction of the y-axis. Turning over can be obtained by rotating about the y-axis by 180°.

1000 EXTERNAL PICTURE tetra
1010 DECLARE EXTERNAL PICTURE face
1020 OPTION ANGLE DEGREES
1030 DIM rx(4,4),ry(4,4)
1040 MAT rx=IDN           ! rx = rotation about the x-axis by ACOS(1/3)
1050 LET a=ACOS(1/3)      ! face angle
1060 LET rx(2,2)=COS(a)
1070 LET rx(2,3)=SIN(a)
1080 LET rx(3,2)=-SIN(a)
1090 LET rx(3,3)=COS(a)
1100 MAT ry=IDN           ! ry = rotation about the y-axis by 180°
1110 LET ry(1,1)=-1
1120 LET ry(3,3)=-1
1130 DRAW face WITH rx * SHIFT(0,-SQR(3)/3)           ! a lateral side
1140 DRAW face WITH rx * SHIFT(0,-SQR(3)/3) * ROTATE(120)
1150 DRAW face WITH rx * SHIFT(0,-SQR(3)/3) * ROTATE(240)
1160 DRAW face WITH ry * SHIFT(0,-SQR(3)/3)           ! the base
1170 END PICTURE

Hide invisible faces ~ Calculation of normal vectors

In case of congruent or similar transformation, the right side of a face can be decided by the transformed vector of the normal vector (0, 0, 1).
The vector to which the vector (0, 0, 1) converts can be calculated by subtracting two vectors to which the origin (0, 0, 0) and the point (0, 0, 1) moves. If we call the subprogram "makeNormal" shown below during execution of the external picture "face", we obtain the normal vector. As Full BASIC cannot define a matrix valued function, we denotes the routine as a subprogram.

1310 EXTERNAL SUB makeNormal(N())
1320 DIM m(4,4),A(4),B(4)
1330 MAT m=TRANSFORM
1340 MAT READ A
1350 DATA 0,0,1,1       ! the point (0,0,1)
1360 MAT A=A*M          
1370 MAT A=(1/A(4))*A   ! the point to which the point (0,0,1) moves
1380 MAT READ B
1390 DATA 0,0,0,1       ! the origin
1400 MAT B=B*M
1410 MAT B=(1/B(4))*B   ! the point to which the origin moves
1420 MAT A=A-B          ! transformed result of the vector(0,0,1)
1430 LET N(1)=A(1)
1440 LET N(2)=A(2)
1450 LET N(3)=A(3)
1460 END SUB 

Decision of the brightness of a face

If we get the normal vector, we can calculate the angle between it and the angle of the light source assumed beforehand, and we can vary the brightness of faces according to the angle.
The following subprogram varies the brightness of the color of index 8 in proportion to the cosine of the angle between the vector (-1, 1, 1) and the parameter given. DOT(A,B) is a supplied function that finds the inner product of two vectors A and B.

1490 EXTERNAL SUB setBrightness(N())
1500 DIM A(3)
1510 MAT READ A      
1520 DATA -1,1,1       ! direction of light source
1530 LET s=DOT(A,N)/(SQR(DOT(A,A))*SQR(DOT(N,N)))
1540 LET s=(0.8*s+1)/2
1550 SET COLOR MIX(8) s,s,s
1560 SET AREA COLOR 8
1570 END SUB

Modification of the picture definition that draws a face

The above two subprogram must be invoked within a picture definition, because the current transform can be obtained only during the execution of a picture definition. Therefore, we modify the picture definition "face" as follows.

1200 EXTERNAL PICTURE face
1210 DECLARE EXTERNAL SUB makeNormal, setBrightness
1220 DIM N(3)
1230 CALL makeNormal(N)
1240 IF N(3)>0 THEN             ! if outside is near side
1250    CALL setBrightness(N)
1260    PLOT AREA: -1,0; 1,0; 0, SQR(3)  
1270 END IF 
1280 END PICTURE



Note.
The normal vector can also be calculated in the picture "face". For example, the normal vector of the face drawn by the execution of

1150 DRAW face WITH rx * SHIFT(0,-SQR(3)/3)             

can be obtained by

    DIM m(4,4),n(3)
    MAT m=TRANSFORM
    MAT m=rx * SHIFT(0,-SQR(3)/3) * m



Projective Transformation

If we want to draw a solid as we see, we must draw near objects bigger and remote objects smaller. Projective transformation realize this.
When we view a point (x, y, z) from the point (0, 0, t) on the z-axis, the point (x, y, z) is observed as if it lies at the point ( x/(1-z/t), y/(1-z/t), 0) on the xy-plane.









If we ignore the z-coordinates of results, this transformation can be obtained by a matrix

(
1    0 0 0
0 1    0 0
0 0 1    -1/t
0 0 0 1
)



In case of projective transformation, the normal vector of a face may not be mapped to the normal vector of the transformed face. hence we calculate the normal vector by calculating the outer vector of the transformed vectors of two vectors in the plane.

100 ! Regular Tetrahedron
110 DECLARE EXTERNAL PICTURE tetra
120 OPTION ANGLE DEGREES
130 LET z0=10          ! The Viewpoint
140 DIM p(4,4)         ! Projection about the point (0,0,z0)               
150 MAT p=IDN
160 LET p(3,4)=-1/z0
170 LET theta0=70
180 REM draw a tetra as if it is viewed from the point (0, 0, 10),
190 REM rotating about the z-axis by theta0 °,
200 REM and rotating about the x-axis by t°
210 SET WINDOW -2, 2, -2, 2
220 FOR t=0 TO -100 STEP -0.1
230    DIM rotx(4,4)      ! rotation about the x-axis
240    MAT rotx=IDN
250    LET rotx(2,2)=COS(t)
260    LET rotx(2,3)=SIN(t)
270    LET rotx(3,2)=-SIN(t)
280    LET rotx(3,3)=COS(t)
290    SET DRAW mode hidden
300    CLEAR
310    DRAW tetra WITH ROTATE(theta0) * rotx * p
320    SET DRAW mode explicit
330    WAIT DELAY 0.01
340 NEXT t
350 END 
360 !
980 ! draw a regular tetrahedron
990 ! the base on the xy-plane, the barycenter of the base the origin
1000 EXTERNAL PICTURE tetra
1010 DECLARE EXTERNAL PICTURE face
1020 OPTION ANGLE DEGREES
1030 DIM rx(4,4),ry(4,4)
1040 MAT rx=IDN           ! rotation about the x-axis by ACOS(1/3)
1050 LET a=ACOS(1/3)      ! face angle
1060 LET rx(2,2)=COS(a)
1070 LET rx(2,3)=SIN(a)
1080 LET rx(3,2)=-SIN(a)
1090 LET rx(3,3)=COS(a)
1100 MAT ry=IDN           ! rotation about the y-axis by 180°
1110 LET ry(1,1)=-1
1120 LET ry(3,3)=-1
1130 DRAW face WITH rx * SHIFT(0,-SQR(3)/3)              ! lateral side
1140 DRAW face WITH rx * SHIFT(0,-SQR(3)/3) * ROTATE(120)
1150 DRAW face WITH rx * SHIFT(0,-SQR(3)/3) * ROTATE(240)
1160 DRAW face WITH ry * SHIFT(0,-SQR(3)/3)              ! the base
1170 END PICTURE
1180 !
1190 ! draw a face
1200 EXTERNAL PICTURE face
1210 DECLARE EXTERNAL SUB makeNormal, setBrightness
1220 DIM N(3)
1230 CALL makeNormal(N)
1240 IF N(3)>0 THEN     ! if outside is near side
1250    CALL setBrightness(N)
1260    PLOT AREA: -1,0; 1,0; 0, SQR(3)  
1270 END IF 
1280 END PICTURE
1290 !
1300 ! find the normal vector in the transformed coordinates
1310 EXTERNAL SUB makeNormal(N())
1320 DIM m(4,4),A(4),B(4),C(4)
1330 MAT m=TRANSFORM
1340 MAT READ A
1350 DATA 0,0,0,1
1360 MAT READ B
1370 DATA 1,0,0,1
1380 MAT READ C
1390 DATA 1,1,0,1
1400 MAT A=A*M
1410 MAT B=B*M
1420 MAT C=C*M
1430 MAT A=(1/A(4))*A
1440 MAT B=(1/B(4))*B
1450 MAT C=(1/C(4))*C
1460 MAT REDIM A(3)
1470 MAT REDIM B(3)
1480 MAT REDIM C(3)
1490 MAT A=B-A
1500 MAT B=C-B
1510 MAT N=CROSS(A,B)
1520 END SUB 
1530 !
1540 ! determine the brightness of the face from the direction of the normal
1550 EXTERNAL SUB setBrightness(N())
1560 DIM A(3)
1570 MAT READ A      ! direction of light source
1580 DATA -1,1,1
1590 LET s=DOT(A,N)/(SQR(DOT(A,A))*SQR(DOT(N,N)))
1600 LET s=(0.8*s+1)/2
1610 SET COLOR MIX(8) s,s,s
1620 SET AREA COLOR 8
1630 END SUB


Note.
An array valued function CROSS(A, B) is an original enhanced of Decimal BASIC, and calculates the outer product of two vectors A and B. This can be replaced by a subprogram that calculates the outer product, if you want to conform the program to the Full BASIC standard.
Also SET DRAW MODE statements in lines 290 and 320 are original enhancements. These two lines can be removed if you want to have a conformed program.

Rotate the solid freely

If you re-write the main program as follows, the solid shall rotate about the x-axis when you drag the mouse vertically on the screen, and rotate about the y-axis when you drag the mouse horizontally on the screen.
However MOUSE POLL statement in 480 line is not compatible with the Full BASIC standard.

100 ! Regular Tetrahedron
110 DECLARE EXTERNAL PICTURE tetra
120 OPTION ANGLE DEGREES
130 LET z0=20          ! The Viewpoint
140 DIM p(4,4)         !  Projection about the point (0,0,z0)                   
150 MAT p=IDN
160 LET p(3,4)=-1/z0
170 LET theta0=45      ! angle of rotation  about the z-axis
180 LET t=-60          ! initial angle of rotation about the x-axis
190 LET s=0            ! initial angle of rotation about the y-axis
260 DIM m(4,4)
270 MAT m=ROTATE(theta0)
280 SET WINDOW -2, 2, -2, 2
290 DO 
300    DIM rotx(4,4)      ! rotation about the x-axis
310    MAT rotx=IDN
320    LET rotx(2,2)=COS(t)
330    LET rotx(2,3)=SIN(t)
340    LET rotx(3,2)=-SIN(t)
350    LET rotx(3,3)=COS(t)
360    DIM roty(4,4)      ! rotation about the y-axis
370    MAT roty=IDN
380    LET roty(1,1)=COS(s)
390    LET roty(1,3)=-SIN(s)
400    LET roty(3,1)=SIN(s)
410    LET roty(3,3)=COS(s)
420    MAT m=m * rotx * roty 
430    SET DRAW mode hidden
440    CLEAR
450    DRAW tetra WITH m * p
460    PLOT TEXT, AT -2,-2: "Drag to rotate. Right click to quit."
470    SET DRAW mode explicit
480    MOUSE POLL x,y,l,r
490    IF r<>0 THEN EXIT DO
500    LET t=0
510    LET s=0
520    IF l<>0 THEN    
530       LET t=-20*(y-y0)
540       LET s= 20*(x-x0)
550    END IF 
560    LET x0=x
570    LET y0=y
580 LOOP
590 END 

Another 3D drawing technique can be found in a sample program 3DPLOT.BAS in the SAMPLE folder.


Back