Thank you for the official release of Machikania for PicoCalc.
This is an old-fashioned 3D demo program I created with the support of copilot.
It’s quite verbose and inelegant, but Machikania runs it so quickly that it doesn’t seem like BASIC at all.
If I tried to do something like this on the computer when I was a kid, I can’t imagine how many seconds it would have taken to draw one screen.

rem 3D WIREFRAME SIMPLE DEMO
usevar movingPhase
usevar eyeX#, eyeY#, eyeZ#
usevar eyePitch#
usevar eyeYaw#
usevar pxp#,pyp#,pzp#,xpp#,ypp#
DIM pxp#(8),pyp#(8),pzp#(8)
DIM xpp#(8),ypp#(8)
usevar cx#,cy#,cz#,PwidtH#,height#,depth#
USEVAR x1#,y1#,z1#,x2#,y2#,z2#,xp1#,yp1#,xp2#,yp2#
USEVAR x1A,y1A,z1A,x2A,y2A,z2A,xp1A,yp1A,xp2A,yp2A
usevar tt#
usevar xc#, yc#, zc#
usevar xpc#, ypc#
rem Sub Transform3D
usevar xt3a,yt3a,zt3a,xpt3a,ypt3a
usevar xt3#,yt3#,zt3#,xpt3#,ypt3#
usevar radYaw#
usevar tempX#, tempZ#
usevar radPitch#
usevar tempY#
usevar focalLength#
REM LINE COLOR
USEVAR LCOL
rem eyePitch# = -55.00
movingPhase# = 0
eyeX# = -20.0
eyeY# = 4.0
eyeZ# = -80.0
eyeYaw# = 0.0
eyePitch# = 0.0
rem ----------
Do
gCls
If movingPhase = 0 Then
eyeYaw# = 0.0
eyePitch# = 0.0
eyeX# = eyeX# + 1.5
If eyeX# >= 10.0 Then movingPhase = 10
ELSEIf movingPhase = 10 Then
eyeYaw# = 0.0
eyeZ# = eyeZ# + 6.0
REM CURSOR 0,25
REM PRINT eyeZ#
If eyeZ# >= 10.0 Then movingPhase = 20
ELSEIf movingPhase = 20 Then
eyeY# = eyeY# +2
If eyeY# >= 50.0 Then movingPhase = 30
ELSEIf movingPhase = 30 Then
eyePitch# = eyePitch# -1.5
If eyePitch# <= -70.0 Then movingPhase = 40
ElseIf movingPhase = 40 Then
eyeZ# = eyeZ# + 1.5
REM eyeY# = eyeY# + .5
If eyeZ# >= 50.0 Then movingPhase = 60
ELSEIf movingPhase = 60 Then
eyeYaw# = eyeYaw# -8
If eyeYaw# <= -135 Then movingPhase = 70
ElseIf movingPhase = 70 Then
eyeX# = eyeX# + 1
eyeY# = eyeY# + 2
REM eyeY# = eyeY# - 1
If eyeX# >= 50.0 Then movingPhase = 80
ELSEIf movingPhase = 80 Then
eyeYaw# = eyeYaw# -3
If eyeYaw# <= -225 Then movingPhase = 85
ELSEIf movingPhase = 85 Then
eyeY# = eyeY# - 2
If eyeY# <= 70 Then movingPhase = 90
ElseIf movingPhase = 90 Then
eyeZ# = eyeZ# - 2
REM eyeY# = eyeY# - 1
If eyeZ# <= -10.0 Then movingPhase = 100
ELSEIf movingPhase = 100 Then
eyeYaw# = eyeYaw# -3
If eyeYaw# <= -315 Then movingPhase = 110
ElseIf movingPhase = 110 Then
eyeX# = eyeX# - 2
REM eyeY# = eyeY# -0
eyeZ#=eyeZ#-0.25
If eyeX# <= 10.0 Then eyeX# = 10.0: eyeZ# = -20.0: movingPhase = 120
ELSEIf movingPhase = 120 Then
eyeYaw# = eyeYaw# -3
If eyeYaw# <= -360 Then movingPhase = 130
ELSEIf movingPhase = 130 Then
eyePitch# = eyePitch# + 1
If eyePitch# >= 0 Then eyePitch# = 0: movingPhase = 140
ELSEIf movingPhase = 140 Then
eyeY# = eyeY# - 1
If eyeY# <= 4 Then eyeY# = 4: movingPhase = 10
EndIf
CURSOR 0,39
rem PRINT "PHASE=";movingPhase
PRINT movingPhase
rem PRINT eyeX#,eyeY#,eyeZ#
GOSUB( DrawRectangularPrism ,0.0, 0.0, 0.0, 10.0, 25.0, 10.0,6)
GOSUB( DrawRectangularPrism ,0.0, 0.0, 20.0, 10.0, 45.0, 10.0,4)
GOSUB( DrawRectangularPrism ,0.0, 0.0, 40.0, 10.0, 15.0, 10.0,4)
GOSUB( DrawRectangularPrism ,0.0, 0.0, 60.0, 10.0, 40.0, 10.0,4)
GOSUB( DrawRectangularPrism ,0.0, 40.0, 60.0, 5.0, 2.0, 5.0,3)
GOSUB( DrawRectangularPrism ,20.0, 0.0, 0.0, 10.0, 20.0, 10.0,4)
GOSUB( DrawRectangularPrism ,20.0, 0.0, 20.0, 10.0, 35.0, 10.0,7)
GOSUB( DrawRectangularPrism ,20.0, 0.0, 40.0, 10.0, 40.0, 10.0,4)
GOSUB( DrawRectangularPrism ,20.0, 40.0, 40.0, 3.0, 10.0, 3.0,5)
GOSUB( DrawRectangularPrism ,20.0, 0.0, 60.0, 10.0, 15.0, 10.0,4)
GOSUB( DrawRectangularPrism ,40.0, 0.0, 0.0, 10.0, 15.0, 10.0,1)
GOSUB( DrawRectangularPrism ,40.0, 0.0, 20.0, 10.0, 45.0, 10.0,4)
GOSUB( DrawRectangularPrism ,40.0, 0.0, 40.0, 10.0, 5.0, 10.0,4)
GOSUB( DrawRectangularPrism ,40.0, 5.0, 40.0, 5.0, 30.0, 5.0,5)
GOSUB( DrawRectangularPrism ,40.0, 0.0, 60.0, 10.0, 10.0, 10.0,2)
GOSUB( DrawRectangularPrism ,60.0, 0.0, 0.0, 10.0, 10.0, 10.0,4)
GOSUB( DrawRectangularPrism ,60.0, 0.0, 20.0, 10.0, 35.0, 10.0,4)
GOSUB( DrawRectangularPrism ,60.0, 0.0, 40.0, 10.0, 15.0, 10.0,4)
GOSUB( DrawRectangularPrism ,60.0, 15.0, 40.0, 5.0, 30.0, 5.0,3)
GOSUB( DrawRectangularPrism ,60.0, 0.0, 60.0, 10.0, 20.0, 10.0,2)
rem WAIT 1
rem I=INKEY()
REM PRINT I
rem LOOP UNTIL I
LOOP UNTIL 0
END
REM ----------
REM Sub DrawRectangularPrism (cx As Single, cy As Single, cz As Single, width As Single, height As Single, depth As Single, LINECOLOR)
LABEL DrawRectangularPrism
rem usevar cx#,cy#,cz#,PwidtH#,height#,depth#
var cx#,cy#,cz#,PwidtH#,height#,depth#
cx#=args#(1)
cy#=args#(2)
cz#=args#(3)
Pwidth#=args#(4)
height#=args#(5)
depth#=args#(6)
LCOL=ARGS(7)
rem CURSOR 0,22
rem PRINT CX#,CY#,CZ#,PWIDTH#,HEIGHT#,DEPTH#
rem Dim px(8) As Single, py(8) As Single, pz(8) As Single-->pxp#(,pyp#(,pzp#(
rem Dim xp(8) As Single, yp(8) As Single-->xpp#(,ypp#(
pxp#(1) = cx# - Pwidth# / 2: pyp#(1) = cy#: pzp#(1) = cz# - depth# / 2
pxp#(2) = cx# + Pwidth# / 2: pyp#(2) = cy#: pzp#(2) = cz# - depth# / 2
pxp#(3) = cx# + Pwidth# / 2: pyp#(3) = cy#: pzp#(3) = cz# + depth# / 2
pxp#(4) = cx# - Pwidth# / 2: pyp#(4) = cy#: pzp#(4) = cz# + depth# / 2
pxp#(5) = pxp#(1): pyp#(5) = cy# + height#: pzp#(5) = pzp#(1)
pxp#(6) = pxp#(2): pyp#(6) = pyp#(2) + height#: pzp#(6) = pzp#(2)
pxp#(7) = pxp#(3): pyp#(7) = pyp#(3) + height#: pzp#(7) = pzp#(3)
pxp#(8) = pxp#(4): pyp#(8) = pyp#(4) + height#: pzp#(8) = pzp#(4)
For i = 1 To 8
REM CURSOR 0,20
REM PRINT PXP#(I),PYP#(I),PZP#(I)
rem GOSUB(Transform3D, pxp#(i), pyp#(i), pzp#(i), xpp#(i), ypp#(i))
GOSUB(Transform3D, pxp+(4*i), pyp+(4*i), pzp+(4*i), xpp+(4*i), ypp+(4*i))
Next
rem GOSUB( DrawLineIfVisible, pxp#(1), pyp#(1), pzp#(1), pxp#(2), pyp#(2), pzp#(2), xpp#(1), ypp#(1), xpp#(2), ypp#(2) )
GOSUB(DrawLineIfVisible,pxp+(4*1),pyp+(4*1),pzp+(4*1),pxp+(4*2),pyp+(4*2),pzp+(4*2),xpp+(4*1),ypp+(4*1),xpp+(4*2),ypp+(4*2))
rem GOSUB( DrawLineIfVisible, pxp#(2), pyp#(2), pzp#(2), pxp#(3), pyp#(3), pzp#(3), xpp#(2), ypp#(2), xpp#(3), ypp#(3) )
GOSUB(DrawLineIfVisible,pxp+(4*2),pyp+(4*2),pzp+(4*2),pxp+(4*3),pyp+(4*3),pzp+(4*3),xpp+(4*2),ypp+(4*2),xpp+(4*3),ypp+(4*3))
rem GOSUB( DrawLineIfVisible, pxp#(3), pyp#(3), pzp#(3), pxp#(4), pyp#(4), pzp#(4), xpp#(3), ypp#(3), xpp#(4), ypp#(4) )
GOSUB(DrawLineIfVisible,pxp+(4*3),pyp+(4*3),pzp+(4*3),pxp+(4*4),pyp+(4*4),pzp+(4*4),xpp+(4*3),ypp+(4*3),xpp+(4*4),ypp+(4*4))
rem GOSUB( DrawLineIfVisible, pxp#(4), pyp#(4), pzp#(4), pxp#(1), pyp#(1), pzp#(1), xpp#(4), ypp#(4), xpp#(1), ypp#(1) )
GOSUB(DrawLineIfVisible,pxp+(4*4),pyp+(4*4),pzp+(4*4),pxp+(4*1),pyp+(4*1),pzp+(4*1),xpp+(4*4),ypp+(4*4),xpp+(4*1),ypp+(4*1))
rem GOSUB( DrawLineIfVisible, pxp#(5), pyp#(5), pzp#(5), pxp#(6), pyp#(6), pzp#(6), xpp#(5), ypp#(5), xpp#(6), ypp#(6) )
GOSUB(DrawLineIfVisible,pxp+(4*5),pyp+(4*5),pzp+(4*5),pxp+(4*6),pyp+(4*6),pzp+(4*6),xpp+(4*5),ypp+(4*5),xpp+(4*6),ypp+(4*6))
rem GOSUB( DrawLineIfVisible, pxp#(6), pyp#(6), pzp#(6), pxp#(7), pyp#(7), pzp#(7), xpp#(6), ypp#(6), xpp#(7), ypp#(7) )
GOSUB(DrawLineIfVisible,pxp+(4*6),pyp+(4*6),pzp+(4*6),pxp+(4*7),pyp+(4*7),pzp+(4*7),xpp+(4*6),ypp+(4*6),xpp+(4*7),ypp+(4*7))
rem GOSUB( DrawLineIfVisible, pxp#(7), pyp#(7), pzp#(7), pxp#(8), pyp#(8), pzp#(8), xpp#(7), ypp#(7), xpp#(8), ypp#(8) )
GOSUB(DrawLineIfVisible,pxp+(4*7),pyp+(4*7),pzp+(4*7),pxp+(4*8),pyp+(4*8),pzp+(4*8),xpp+(4*7),ypp+(4*7),xpp+(4*8),ypp+(4*8))
rem GOSUB( DrawLineIfVisible, pxp#(8), pyp#(8), pzp#(8), pxp#(5), pyp#(5), pzp#(5), xpp#(8), ypp#(8), xpp#(5), ypp#(5) )
GOSUB(DrawLineIfVisible,pxp+(4*8),pyp+(4*8),pzp+(4*8),pxp+(4*5),pyp+(4*5),pzp+(4*5),xpp+(4*8),ypp+(4*8),xpp+(4*5),ypp+(4*5))
rem GOSUB( DrawLineIfVisible, pxp#(1), pyp#(1), pzp#(1), pxp#(5), pyp#(5), pzp#(5), xpp#(1), ypp#(1), xpp#(5), ypp#(5) )
GOSUB(DrawLineIfVisible,pxp+(4*1),pyp+(4*1),pzp+(4*1),pxp+(4*5),pyp+(4*5),pzp+(4*5),xpp+(4*1),ypp+(4*1),xpp+(4*5),ypp+(4*5))
rem GOSUB( DrawLineIfVisible, pxp#(2), pyp#(2), pzp#(2), pxp#(6), pyp#(6), pzp#(6), xpp#(2), ypp#(2), xpp#(6), ypp#(6) )
GOSUB(DrawLineIfVisible,pxp+(4*2),pyp+(4*2),pzp+(4*2),pxp+(4*6),pyp+(4*6),pzp+(4*6),xpp+(4*2),ypp+(4*2),xpp+(4*6),ypp+(4*6))
rem GOSUB( DrawLineIfVisible, pxp#(3), pyp#(3), pzp#(3), pxp#(7), pyp#(7), pzp#(7), xpp#(3), ypp#(3), xpp#(7), ypp#(7) )
GOSUB(DrawLineIfVisible,pxp+(4*3),pyp+(4*3),pzp+(4*3),pxp+(4*7),pyp+(4*7),pzp+(4*7),xpp+(4*3),ypp+(4*3),xpp+(4*7),ypp+(4*7))
rem GOSUB( DrawLineIfVisible, pxp#(4), pyp#(4), pzp#(4), pxp#(8), pyp#(8), pzp#(8), xpp#(4), ypp#(4), xpp#(8), ypp#(8) )
GOSUB(DrawLineIfVisible,pxp+(4*4),pyp+(4*4),pzp+(4*4),pxp+(4*8),pyp+(4*8),pzp+(4*8),xpp+(4*4),ypp+(4*4),xpp+(4*8),ypp+(4*8))
REM End Sub
RETURN
REM ----------
REM Sub DrawLineIfVisible (x1 As Single, y1 As Single, z1 As Single, x2 As Single, y2 As Single, z2 As Single, xp1 As Single, yp1 As Single, xp2 As Single, yp2 As Single)
rem gosub DrawLineIfVisible (&x1, &y1, &z1, &x2, &y2, &z2, &xp1, &yp1, &xp, &yp2)
LABEL DrawLineIfVisible
rem USEVAR x1#,y1#,z1#,x2#,y2#,z2#,xp1#,yp1#,xp2#,yp2#
rem USEVAR x1a,y1a,z1a,x2a,y2a,z2a,xp1a,yp1a,xp2a,yp2a
VAR x1#,y1#,z1#,x2#,y2#,z2#,xp1#,yp1#,xp2#,yp2#
VAR x1a,y1a,z1a,x2a,y2a,z2a,xp1a,yp1a,xp2a,yp2a
x1a=ARGS(1)
y1a=ARGS(2)
z1a=ARGS(3)
x2a=ARGS(4)
y2a=ARGS(5)
z2a=ARGS(6)
xp1a=ARGS(7)
yp1a=ARGS(8)
xp2a=ARGS(9)
yp2a=ARGS(10)
x1=peek32(x1a)
y1=peek32(y1a)
z1=peek32(z1a)
x2=peek32(x2a)
y2=peek32(y2a)
z2=peek32(z2a)
xp1=peek32(xp1a)
yp1=peek32(yp1a)
xp2=peek32(xp2a)
yp2=peek32(yp2a)
var tt#,xc#,yc#,zc#,xpc#,ypc#
If z1# > 0.0 And z2# > 0.0 Then
rem Line int(xp1#), int(yp1#), int(xp2#), int(yp2#), 3
Line int(xp1#/2.0), int(yp1#/2.0), int(xp2#/2.0), int(yp2#/2.0), LCOL
ElseIf z1# > 0.0 And z2# <= 0.0 Then
rem t = z1 / (z1 - z2 + 1E-6)
tt# = z1# / (z1# - z2# + 0.000001 )
xc# = x1# + tt# * (x2# - x1#)
yc# = y1# + tt# * (y2# - y1#)
zc# = z1# + tt# * (z2# - z1#)
GOSUB( Transform3D, &xc, &yc, &zc, &xpc, &ypc)
If zc# > 0.0 Then
rem Line int(xp1#), int(yp1#), int(xpc#), int(ypc#), LCOL
Line int(xp1#/2.0), int(yp1#/2.0), int(xpc#/2.0), int(ypc#/2.0), 3
ENDIF
ElseIf z1# <= 0.0 And z2# > 0.0 Then
tt# = z2# / (z2# - z1# + 0.00001 )
xc# = x2# + tt# * (x1# - x2#)
yc# = y2# + tt# * (y1# - y2#)
zc# = z2# + tt# * (z1# - z2#)
GOSUB( Transform3D, &xc, &yc, &zc, &xpc, &ypc)
If zc# > 0.0 Then
rem Line int(xpc#), int(ypc#), int(xp2#), int(yp2#), LCOL
Line int(xpc#/2.0), int(ypc#/2.0), int(xp2#/2.0), int(yp2#/2.0), 3
ENDIF
EndIf
REM End Sub
RETURN
REM -----
REM Sub Transform3D (x As Single, y As Single, z As Single, xp As Single, yp As Single)
REM GOSUB(Transform3D,&x,&y,&z,&xp,&yp)
LABEL Transform3D
rem usevar xt3a,yt3a,zt3a,xpt3a,ypt3a
rem usevar xt3#,yt3#,zt3#,xpt3#,ypt3#
var xt3a,yt3a,zt3a,xpt3a,ypt3a
var xt3#,yt3#,zt3#,xpt3#,ypt3#
xt3a=args(1)
yt3a=args(2)
zt3a=args(3)
xpt3a=args(4)
ypt3a=args(5)
xt3=peek32(xt3a)
yt3=peek32(yt3a)
zt3=peek32(zt3a)
xpt3=peek32(xpt3a)
ypt3=peek32(ypt3a)
xt3# = xt3# - eyeX#
yt3# = yt3# - eyeY#
zt3# = zt3# - eyeZ#
rem usevar radYaw#
var radYaw#
radYaw# = eyeYaw# * 3.14159265 / 180.0
rem usevar tempX#, tempZ#
var tempX#
VAR tempZ#
tempX# = xt3# * Cos#(radYaw#) + zt3# * Sin#(radYaw#)
tempZ# = -xt3# * Sin#(radYaw#) + zt3# * Cos#(radYaw#)
xt3# = tempX#
zt3# = tempZ#
rem usevar radPitch#
var radPitch#
radPitch# = eyePitch# * 3.14159265 / 180.0
rem usevar tempY#
var tempY#
tempY# = yt3# * Cos#(radPitch#) - zt3# * Sin#(radPitch#)
tempZ# = yt3# * Sin#(radPitch#) + zt3# * Cos#(radPitch#)
yt3# = tempY#
zt3# = tempZ#
rem usevar focalLength#
var focalLength#
focalLength# = 600.0
If zt3# > 0 Then
xpt3# = 320.0 + focalLength# * xt3# / zt3#
ypt3# = 240.0 - focalLength# * yt3# / zt3#
Else
xpt3# = -1.0: ypt3# = -1.0
EndIf
poke32 xt3a,xt3
poke32 yt3a,yt3
poke32 zt3a,zt3
poke32 xpt3a,xpt3
poke32 ypt3a,ypt3
rem End Sub
RETURN