3D Draw

This file is part of and CATS Library Tape 6. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Graphics

This program draws an interactive 3D surface graph, allowing the user to sketch two cross-sectional curves by holding numeric keys — key 1 for a sine wave, keys 5–9 for various manual gradients — and then renders the surface either south-to-north, west-to-east, or both. The first pass (T=1) collects 127 Y-values into array L(), and the second pass (T=2) collects them into H(), representing the front and back edges of the surface. Projection is achieved by offsetting each drawn line by 128 pixels horizontally and 88 pixels vertically, with the height difference between front and back arrays used to compute the DRAW slope. The west-to-east rendering (lines 200–260) steps across all 127 columns, interpolating each column’s path toward the back in 20 sub-steps of fixed increments plus a proportional height correction. The sine-wave auto-fill routine at line 1000 bypasses manual input by computing B using a running SIN accumulation with a step of 0.04 radians, storing results directly into L().


Program Analysis

Program Structure

The program is divided into four logical phases:

  1. Setup and instructions (lines 1–9): Display key bindings and wait for a keypress.
  2. Curve input loop (lines 10–130): Draw the axes, then run a double pass (T=1 and T=2) to collect 127 Y-values for the front curve into L() and the back curve into H().
  3. 3D rendering (lines 145–290): Allow the user to choose south-to-north projection, west-to-east projection, or both, and draw the surface.
  4. Sine-wave auto-fill (lines 1000–1060): Pre-compute a sine-wave curve into L() and jump directly to the rendering phase.

Axes and Coordinate System

Line 10 draws the two axes: a vertical line from (127,0) to (127,175) acting as the depth divider, and a horizontal line from (0,87) to (255,87) acting as the horizon. The front half of the display (columns 0–127) holds the first curve pass; the back half (columns 128–255) holds the second. The variable D is used as a horizontal offset: D=-1 for the first pass and D=127 for the second (set at line 130), so PLOT G+D,A correctly places pixels in each half.

Real-Time Curve Drawing

The inner loop (lines 50–115) polls INKEY$ on every iteration and maps each key to a drawing action:

KeyEffect on ADescription
9NoneStraight horizontal line
8A = A + 1Steep upward gradient
7A = A + 0.5Gentle upward gradient
6A = A − 0.5Gentle downward gradient
5A = A − 1Steep downward gradient
1N/AJump to sine-wave auto-fill

If no key is pressed, line 95 loops back to line 60, effectively spinning until a key is held. This means each pixel column is only plotted when a key is actively depressed, making drawing speed dependent on how long the loop iterates before a key is registered — a deliberate real-time sketching mechanic.

South-to-North Projection (Lines 150–180)

This routine steps through the front-curve array in steps of 4 columns. For each sampled column A, it plots the front point L(A+1) and then issues a single DRAW command to reach the corresponding back point. The DRAW target is offset by 128 pixels right and 88 + ((H(A+1)-88) - L(A+1)) pixels vertically, which computes the signed height difference between the back curve’s deviation from the horizon (88) and the front Y-value. The optional D parameter (entered as radians) passes directly to the DRAW statement’s arc angle, allowing the connecting lines to be drawn as arcs rather than straight segments when a non-zero value is entered.

West-to-East Projection (Lines 200–260)

This routine iterates over all 127 columns and for each column interpolates a path from the front curve point to the back curve point in 20 equal sub-steps. Each sub-step advances A (screen X) by 6.35 and B (screen Y) by 4.4 (a fixed isometric-style offset), plus an additional proportional correction ((H(T+1)-88) - L(T+1)) / 20 to account for the actual height difference between front and back. The 6.35 × 20 = 127 and 4.4 × 20 = 88 products confirm these constants are chosen to span exactly the horizontal half-width and half-height of the display, maintaining a consistent oblique projection angle.

Sine-Wave Auto-Fill (Lines 1000–1060)

Rather than requiring the user to manually draw the front curve, pressing key 1 during the first pass jumps to line 1000. This routine accumulates a sine wave by repeatedly adding SIN(A) to B (starting at Y=43) while incrementing the angle A by 0.04 and the column index D by 0.5 per iteration. Using INT D as the array index and D+0.5 stepping means every other iteration writes to the next integer column, giving 127 samples across columns 1–127. Note that this only fills L() (the front curve); H() is never populated by this routine, so the back curve remains at its initial state (all zeros from DIM H(127)).

Notable Techniques and Idioms

  • Using a single variable A as the running Y-position across the curve input loop avoids any separate Y-tracking array during drawing.
  • GO TO 130 at line 1060 skips the second curve-input pass entirely, meaning projections using the sine wave will have a flat (zero) back curve — a functional but asymmetric result.
  • The RUN statements at lines 192 and 290 restart the entire program (resetting all variables) rather than using a structured loop, which is a common space-saving idiom in short BASIC programs.
  • Line 130 combines the post-first-pass reset and the outer NEXT T on one line, which is valid but unusual formatting.

Bugs and Anomalies

  • The sine-wave fill at line 1000 only populates L(), not H(). After jumping to line 130, H() contains all zeros (the DIM default), so the back curve sits at Y=0 rather than representing a meaningful second cross-section. This will produce a visually odd projection.
  • In the west-to-east loop (line 200), A is used as the screen X accumulator starting from column T, but it is incremented by 6.35 per sub-step across 20 steps, ending at approximately T + 127. For larger values of T, this will exceed the 255-pixel screen width and cause an out-of-screen PLOT error unless the Spectrum silently clips it.
  • The prompt at line 270 reads “SOUTH TO EAST AS WELL?” but logically should say “SOUTH TO NORTH AS WELL?” since selecting Y re-triggers the south-to-north rendering path via line 146.
  • Array indices use L(G) and H(G) with G running 1–127, but L(A+1) and H(A+1) in the rendering loops where A steps 0–126 in steps of 4. This correctly accesses indices 1–127, so there is no off-by-one error here.

Content

Appears On

Capital Area Timex Sinclair User Group’s Library Tape.

Related Products

Related Articles

Related Content

Image Gallery

3D Draw

Source Code

    1 CLS 
    5 REM ***3D*BY*TIM*CLOSS
    6 PRINT "INSTRUCTIONS:": PRINT : PRINT "1 - SINE WAVE": PRINT "5 THRU 8 - VARIOUS GRADIENTS": PRINT "9 - STRAIGHT LINE"
    7 PRINT : PRINT : PRINT "WHEN BOTH HALVES OF GRAPH HAS   BEEN FILLED, FOLLOW THE PROMPTS FOR THE REST OF THE PROGRAM. USECAPITAL LETTERS WHEN ENTERING   DATA.": PRINT : PRINT "    Press any key to begin"
    8 IF INKEY$="" THEN GO TO 8
    9 CLS 
   10 PLOT 127,0: DRAW 0,175: PLOT 0,87: DRAW 255,0
   20 DIM L(127): DIM H(127)
   30 LET A=43
   35 LET D=-1
   40 FOR T=1 TO 2
   50 FOR G=1 TO 127
   60 IF INKEY$="9" THEN PLOT G+D,A: GO TO 100
   70 IF INKEY$="8" THEN LET A=A+1: PLOT G+D,A: GO TO 100
   75 IF INKEY$="5" THEN LET A=A-1: PLOT G+D,A: GO TO 100
   80 IF INKEY$="7" THEN LET A=A+.5: PLOT G+D,A: GO TO 100
   90 IF INKEY$="6" THEN LET A=A-.5: PLOT G+D,A: GO TO 100
   91 IF INKEY$="1" THEN GO TO 1000
   95 GO TO 60
  100 IF T=1 THEN LET L(G)=A: GO TO 115
  110 LET H(G)=A
  115 NEXT G
  130 LET A=131: LET D=127: NEXT T
  145 INPUT "(1) SOUTH TO NORTH OR           (2) WEST  TO EAST ?";O
  146 IF O=1 THEN INPUT "RADIANS?";D: GO TO 150
  147 IF O=2 THEN GO TO 200
  148 GO TO 145
  150 FOR A=0 TO 126 STEP 4
  160 PLOT A,L(A+1)
  170 DRAW 128,88+((H(A+1)-88)-L(A+1)),D
  180 NEXT A
  190 INPUT "WEST TO EAST AS WELL?";O$
  191 IF O$="Y" THEN GO TO 200
  192 RUN 
  200 FOR T=0 TO 126
  210 LET B=L(T+1): LET A=T
  220 FOR G=1 TO 20
  230 LET A=A+6.35: LET B=B+4.4
  240 LET B=B+((H(T+1)-88)-L(T+1))/20
  245 PLOT A,B
  250 NEXT G
  260 NEXT T
  270 INPUT "SOUTH TO EAST AS WELL?";O$
  280 IF O$="Y" THEN LET O=1: GO TO 146
  290 RUN 
 1000 LET B=43
 1010 LET A=1
 1015 LET D=1
 1020 LET L(INT D)=B
 1021 PLOT D,B
 1030 LET B=B+(SIN A)
 1040 LET A=A+.04: LET D=D+.5
 1045 IF D>=127 THEN GO TO 1060
 1050 GO TO 1020
 1060 GO TO 130

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top