Wednesday, May 25, 2022

Ray tracing in BASIC

This port is from a year and a half ago. The original code rendered in B&W so it took some time to get a good color image.  It's kinda what you'd expect from BASIC for "ray tracing".  You'll notice some oddness in the image, the color coding is hard wired just for this, and it takes a LONG time to run on an old 8 bit computer... but it does run.


 

 REM SET COCO 3 HIGH SPEED MODE AND INSTALL MULTIPLY PATCH
0 POKE 65497,0:GOSUB10000

5 PALETTE 0,63:PALETTE 1,0:PALETTE 2,11:PALETTE 3,7:HSCREEN 2


REM PLACE CONSTANTS IN VARIABLES TO ELIMINATE ASCII TO FLOAT CONVERSION OVERHEAD LATER
9 RX=0:RY=0:RZ=0:T=0:OX=0:OY=0:OZ=0:X1=0:X2=0:A=0:B=1:C=2:D=5:E=-1:F=1/320:G=1/2:H=192:M=1/5:J=.95:L=.001

10 DIM KX(10), KY(10), KZ(10), KR(10)

11 AK=3-1                                  :REM NUMBER OF BALLS (-1 BECAUSE OF THE FOR LOOP IN LINE 91)
12 KX(0)=3:   KY(0)=9: KZ(0)=50: KR(0)=9   :REM KUGEL X Y Z RADIUS
13 KX(1)=-12: KY(1)=7: KZ(1)=80: KR(1)=7
14 KX(2)=-3:  KY(2)=3: KZ(2)=35: KR(2)=3
15 BX=0: BY=5: BZ=-17: BE=25               :REM VIEWER X Y Z, DISTANCE TO THE GRILLE(SIZE OF THE ANGLE OF VIEW)
16 LX=-50: LY=300: LZ=50                   :REM LIGHT SOURCE X Y Z
17 GB=10                                   :REM GRID WIDTH (SCENE RESOLUTION)

REM Y PIXEL LOCATION
21 FOR Y = 0 TO 191

REM X PIXEL LOCATION
30 FOR X = 0 to 319


REM BEAM VIEWER-> GRID POINT (X, Y) (DIRECTIONAL VECTOR)
32 ZW=GB*F:RX=X*ZW-GB*G:RY=-Y*ZW+H*G*ZW:RZ=BE

REM UNIT VECTOR FROM DIRECTIONAL VECTOR
33 ZW=SQR(RX*RX+RY*RY+RZ*RZ):RX=RX/ZW:RY=RY/ZW:RZ=RZ/ZW

REM POSITION OF THE VIEWER (LOCATION VECTOR)
34 OX=BX:OY=BY:OZ=BZ


REM  BEGIN RAYTRACEING

REM SECTION OF VISIBLE STEEL BALLS (SET K = WHICH BALL (-1 = NONE) AND T = DISTANCE TO THE CUT)
40 GOSUB90

REM CUT CLOSER TO THE FLOOR THAN WITH BALLS? THEN CONTINUE, ELSE GOTO 50
42 ON-((OY+T*RY)>A)GOTO50

REM CUT WITH FLOOR
REM INTERFACE WITH GROUND
44 LA=-OY/RY:SX=OX+LA*RX:SY=A:SZ=OZ+LA*RZ

REM CHESSBOARD PATTERN (FA = COLOR 0 OR 1)
45 ZW=(INT(SX*M)AND B)+(INT(SZ*M)AND B):FA=(ZW=B)+B


REM SHADOW CALCULATION, SECTION: (INTERFACE GROUND) -> LIGHT SOURCE WITH BALLS
46 OX=SX:OY=SY:OZ=SZ:RX=OX+LX:RY=OY+LY:RZ=OZ+LZ:GOSUB90

REM IF NO BALL HIT (NO SHADOW) THEN GOTO 80
47 ON -(K=E)GOTO80

REM TREASURE MUSTER
'48 FA=((X AND B)<>(Y AND B))+B
48 IF FA=A THEN FA=3

REM PIXEL DONE
49 GOTO80

50 REM CUT WITH SKY

REM IF NEITHER BOTTOM OR BALLS HAVE BEEN CUT, THEN COLOR = GRAY AND GOTO 80         
51 IFK=E THEN FA=C:GOTO80

60 REM CUT WITH BALLS

REM CALCULATION OF THE EDGE OF THE CUT BALL, BY DISTANCE FROM THE BALL CENTER TO THE SIGHT STEEL
62 X1=KX(K)*RX+KY(K)*RY+KZ(K)*RZ:X2=OX*RX+OY*RY+OZ*RZ:X3=RX*RX+RY*RY+RZ*RZ

63 LA=(X1-X2)/X3:F1=(OX+LA*RX)-KX(K):F2=(OY+LA*RY)-KY(K):F3=(OZ+LA*RZ)-KZ(K)

REM MINIMUM DISTANCE SIGHT STEEL-> BALL CENTER POINT
64 D=SQR(F1*F1+F2*F2+F3*F3)

REM HIT BALL ONLY ON THE EDGE? , THEN COLOR = BLACK AND GOTO 80
65 IF(KR(K)*J<D)THENFA=B:GOTO80

70 REM CALCULATION OF BALL REFLECTION

REM THE INTERFACE WITH THE BALL IS THE NEW LOCATION VECTOR
71 OX=OX+T*RX:OY=OY+T*RY:OZ=OZ+T*RZ

REM INVENTORY LOT (NORMAL) FOR REFECTION CALCULATION
72 NX=KX(K)-OX:NY=KY(K)-OY:NZ=KZ(K)-OZ

REM NEW DIRECTIONAL VECTOR IS THE REFLECTIVE STEEL FROM THE BALL
73 ZW=NX*RX+NY*RY+NZ*RZ:RX=RX-C*ZW*NX:RY=RY-C*ZW*NY:RZ=RZ-C*ZW*NZ

REM UNIFORM NEW DIRECTIONS VECTOR (UNIT VECTOR)
74 ZW=SQR(RX*RX+RY*RY+RZ*RZ):RX=RX/ZW:RY=RY/ZW:RZ=RZ/ZW

REM NEW RAYTRACE STEP WITH REFLECTIVE STEEL AS A NEW "VIEWER POSITION"
75 GOTO40

REM PIXEL COLOR HAS BEEN CALCULATED
80 HSET(X,Y,FA)

REM DIDN'T USE NEXT X,Y SO I CAN PLAY WITH LOOP ORDER
82 NEXT
84 NEXT

85 GOTO 85



REM FUNCTION: MINIMUM DISTANCE FROM THE INTERSECTION POINT SIGHT STEEL-> BALLS

REM INIT  K = CUT BALL, T = DISTANCE TO CUT
90 K=-1:T=99999

92 REM CUTTING DISTANCE TO THE BALL USING THE P, Q FORMULA
93 ZW= B/(RX*RX+RY*RY+RZ*RZ)

REM ALL BALLS ON CUT THROUGHOUT
94 FOR I=A TO AK

95 P=(C*(RX*(OX-KX(I))+RY*(OY-KY(I))+ RZ*(OZ-KZ(I))))*ZW

96 Q=((OX-KX(I))*(OX-KX(I))+(OY-KY(I))*(OY-KY(I))+(OZ-KZ(I))*(OZ-KZ(I))-KR(I)*KR(I))*ZW

REM INTERIM RESULTS
97 Z1=-P*G

98 Z2=((P*P)/4-Q)

REM THERE IS NO CUT WITH THE BALL, TEST NEXT BALL
99 IF Z2<0 THEN NEXT: RETURN

100 WU=SQR(Z2)

REM THE 2 SOLUTIONS OF THE PQ FORMULA (CUTTING DISTANCES)
101 X1=Z1+WU:X2=Z1-WU

REM IF X1<T THEN K=I: T=X1
102 Z0=-((X1>L)AND(X1<T)):Z1=-Z0+B:K=Z0*I+Z1*K:T=Z0*X1+Z1*T

REM IF X2<T THEN K=I: T=X2
103 Z0=-((X2>L)AND(X2<T)):Z1=-Z0+B:K=Z0*I+Z1*K:T=Z0*X2+Z1*T

REM TEST THE NEXT BALL
104 NEXT: RETURN








REM COCO3 HARDWARE MULTIPLY PATCH.
REM JUST ADD A GOSUB 10000 AT THE TOP OF YOUR CODE TO ADD IT
REM ADDRESS WE ARE STORING THE MULTIPLY PATCH IN RAM
10000 AD=VAL("&HFA0C")
REM POKE THE MULTIPLY PATCH INTO RAM
10001 FORI=0 TO 64:READ B$:A=VAL("&H"+B$):POKE AD+I,A:NEXT
REM MAKE BASIC JUMP TO OUR MULTIPY INSTEAD OF USING IT'S CODE. $BB00 JMP $FA0C
10002 POKE VAL("&HBB02"),VAL("&H7E"):POKE VAL("&HBB03"),VAL("&HFA"):POKE VAL("&HBB04"),VAL("&H0C")
10003 RETURN
10004 DATA 32,79,E7,60,96,60,3D,ED,63,E6,60,96,5E,3D,ED,61,E6,60,96,5D
10005 DATA 3D,ED,65,E6,60,96,5F,3D,E3,62,ED,62,EC,65,E9,61,89,00,ED,60
10006 DATA EC,63,D3,15,97,16,D7,63,EC,61,D9,14,99,13,DD,14,A6,60,89,00
10007 DATA 97,13,32,67,39

3 comments:

  1. If you don't like the large black border around the spheres, you can try this. Subtracting a larger number will reduce the size, but the edge of some spheres will may disappear. Since the constant isn't in a variable this will be slower than it has to be, but I'm not going to worry about it:

    65 IF(KR(K)*J<D-.25)THENFA=B:GOTO80

    ReplyDelete
  2. I posted an update to the code. Blogspot had reformatted the code, and it was horrible. The hardware multiply patch code has also been updated.

    ReplyDelete
  3. I posted a new version of the patch this morning that enables 6309 native mode. You can drop that into the code over lines 10000 on

    ReplyDelete