Hi everybody
I need some help as I don't know if I'm doing things wrong or there is an issue with the compiler.
I tried to translate into UGBASIC's syntax, but without success, the following routine written with Epyx toolkit for the Commodore 64's BASIC. It works fine with Epyx toolkit installed, and draws a 3D picture of a figure that looks like a hat.
10 RESET:MULTI:BACKGROUNDBLACK:BORDERBLACK:
20 P=160
30 Q=100:XP=144:XR=1.5*pi:YP=56:YR=1
50 ZP=64:XF=XR/XP:YF=YP/YR:ZF=XR/ZP
60 FORZI=QTOQ1
70 IF ZI<ZP OR ZI>ZP GOTO150
80 ZT=ZI*XP/ZP:ZZ=ZI
90 XL=INT (.5+SQR(XP*XPZT*ZT))
100 FOR XI=XLTOXL
110 XT=SQR(XI*XI+ZT*ZT)*XF:XX=XI
120 YY=(SIN(XT)+.4*SIN(3*XT))*YF
130 GOSUB 170
140 NEXT XI
150 NEXT ZI
160 GOTO 160
170 X1=XX+ZZ+P:Y1=YYZZ+Q
180 COLORGREEN:DOT X1,Y1
190 IF Y1=0 GOTO 220
200 COLORBLACK: LINE X1,Y11TOX1,0
210 RETURN
My translation is the following. I can't see what's wrong but it does not work
BITMAP ENABLE (320,200,16):CLS BLACK:
p1=160
q=100:xp=144:xr=01.5*PI:yp=56:yr=01
zp=64:xf=xr/xp:yf=yp/yr:zf=xr/zp
FOR zi=q TO q1
IF zi<zp OR zi>zp THEN GOTO endloop
zt=zi*xp/zp:zz=zi
xl=INT(.5+SQR(xp^2zt^2))
FOR xi=xl TO xl
DEGREE
xt=(SQR(xi*xi+zt*zt)*xf)*180/PI:xx=xi
yy=(SIN (xt)+.4*SIN (3*xt))*yf
GOSUB continue
NEXT
endloop:
NEXT
loop:
GOTO loop
continue:
x1=xx+zz+p1:y1=INT(yyzz+q)
PLOT x1,y1,GREEN
IF y1=0 THEN GOTO draw_line
draw_line:
INK BLACK:LINE x1,y11 TO x1,0
RETURN
I tried an alternative with a similar but shorter routine, which works fine with Tool 64 installed.
10 graphic:sclear
20 xp=144:xr=4.71238905:xf=xr/xp
30 forzi=64to64
40 zt=zi*2.25:zs=zt*zt
50 xl=int(sqr(20736zs)+.5)
60 forxi=0xltoxl
70 xt=sqr(xi*xi+zs)*xf
80 yy=(sin(xt)+sin(xt*3)*0.4)*56
90 x1=xi+zi+160:y1=110+yyzi
100 plotx1,y1,1
110 rem ify1=0thengoto120
120 rem movex1,y11:drawx1,0,0: rem remplacer drawx1,y150,0
130 next:next
140 rem goto130
My translation was unsuccessful as well unfortunately:
10 graphic:sclear
20 xp=144:xr=4.71238905:xf=xr/xp
30 forzi=64to64
40 zt=zi*2.25:zs=zt*zt
50 xl=int(sqr(20736zs)+.5)
60 forxi=0xltoxl
70 xt=sqr(xi*xi+zs)*xf
80 yy=(sin(xt)+sin(xt*3)*0.4)*56
90 x1=xi+zi+160:y1=110+yyzi
100 plotx1,y1,1
110 rem ify1=0thengoto120
120 rem movex1,y11:drawx1,0,0: rem remplacer drawx1,y150,0
130 next:next
140 rem goto130
Do you have any idea what could be wrong?
Thanks in advance
Issues with a 3D plotting routine

 Site Admin
 Posts: 171
 Joined: Fri Oct 06, 2023 8:25 pm
Re: Issues with a 3D plotting routine
Hi lightbeing, and welcome!
I would like to point out that, for performance reasons, ugBASIC is an "Integer BASIC" and does not use float types natively. This has a series of consequences, the most notable of which is that variables are born integer, and not floating point. Therefore, it is not always possible to directly port the sources of other BASICs to floating point without a minimal adaptation. In this case, there are some things that cannot work on ugBASIC, and that should be rethought. I started from your first rewrite, not from the original source, although I was unable to get a significant figure, but I think it depends on the fact that I did not understand well the algorithm with which the points are calculated (I am very sorry!).
DEFINING VARIABLES
When working with the FLOAT type, it is necessary to define all variables correctly, to prevent the compiler from "promoting" them to integers, as already written. The solution of defining them all as FLOAT is only viable if you are sure of what you want to do, and taking into account that the memory footprint grows as you use them.
In this case (if I understood well):
If you need help from the compiler, you can require that all variables be defined before they are used, with the OPTION EXPLICIT command. This way, the compiler will warn you (with an error) if you are using a variable that has not yet been defined, and you will be able to choose the type.
RADIANS VERSUS DEGREES
Although the DEGREE statement is present, for easy of use, using it for trigonometric functions means introducing a slowdown for each operation, in addition to taking up much more space in terms of assembly code. It would therefore be advisable to work without making translations proportional to the PI. This avoid additional divisions and multiplications, too.
"RAISE TO A POWER" ONLY FOR INTEGER
The exponentiation instruction is only available for integer types, and not for floating point types. In this specific case there are no particular problems in replacing them, because exponentiation is done with a constant (2). So the instruction:
Should be rewritten as:
APPROXIMATE SQUARE ROOT
Also the square root function is implemented only for integer types, and this introduces a large approximation, which could compromise the execution of this specific program.
Here the result on some platforms:Amstrad CPC 664  Commodore 128  ColecoVision
Again, the result is not particularly significant on 6502 based processors, but this could depend on the approximations introduced by the use of functions that work with integers.
Let me know if I can be of any help!
First of all I ask you to kindly download the latest COLDFIX released today, which contains a series of fixes on the trigonometric section for MOS 6502 processors, as well as on the management of numeric constants of type FLOAT. This could be the basis of the problem encountered.lightbeing wrote: ↑Fri Oct 18, 2024 4:43 pm I need some help as I don't know if I'm doing things wrong or there is an issue with the compiler.
I would like to point out that, for performance reasons, ugBASIC is an "Integer BASIC" and does not use float types natively. This has a series of consequences, the most notable of which is that variables are born integer, and not floating point. Therefore, it is not always possible to directly port the sources of other BASICs to floating point without a minimal adaptation. In this case, there are some things that cannot work on ugBASIC, and that should be rethought. I started from your first rewrite, not from the original source, although I was unable to get a significant figure, but I think it depends on the fact that I did not understand well the algorithm with which the points are calculated (I am very sorry!).
DEFINING VARIABLES
When working with the FLOAT type, it is necessary to define all variables correctly, to prevent the compiler from "promoting" them to integers, as already written. The solution of defining them all as FLOAT is only viable if you are sure of what you want to do, and taking into account that the memory footprint grows as you use them.
In this case (if I understood well):
Code: Select all
DIM p AS FLOAT, q AS INT
DIM xp AS FLOAT, yp AS FLOAT, zp AS FLOAT
DIM xf AS FLOAT, yf AS FLOAT, zf AS FLOAT
DIM xr AS FLOAT, yr AS FLOAT, zr AS FLOAT
DIM xt AS FLOAT, yt AS FLOAT, zt AS FLOAT
DIM xx AS FLOAT, yy AS FLOAT, zz AS FLOAT
DIM zi AS INTEGER, p1 AS INTEGER, zt AS FLOAT
DIM xl AS INTEGER, yl AS INTEGER
DIM x1 AS INTEGER, y1 AS INTEGER
RADIANS VERSUS DEGREES
Although the DEGREE statement is present, for easy of use, using it for trigonometric functions means introducing a slowdown for each operation, in addition to taking up much more space in terms of assembly code. It would therefore be advisable to work without making translations proportional to the PI. This avoid additional divisions and multiplications, too.
"RAISE TO A POWER" ONLY FOR INTEGER
The exponentiation instruction is only available for integer types, and not for floating point types. In this specific case there are no particular problems in replacing them, because exponentiation is done with a constant (2). So the instruction:
Code: Select all
xt=(SQR(xi^2i+zt^2)*xf)*180/PI:xx=xi
Code: Select all
xt=(SQR(xi*xi+zt*zt)*xf)*180/PI:xx=xi
Also the square root function is implemented only for integer types, and this introduces a large approximation, which could compromise the execution of this specific program.
I tried to rewrite it as best I could, so I apologize if I made any mistakes.lightbeing wrote: ↑Fri Oct 18, 2024 4:43 pm I tried an alternative with a similar but shorter routine, which works fine with Tool 64 installed.
Code: Select all
OPTION EXPLICIT
DIM xp AS FLOAT, xf AS FLOAT, xr AS FLOAT
DIM zt AS FLOAT, zi AS INT, xi AS INT
DIM zs AS FLOAT, xl AS INT, xt AS FLOAT
DIM yy AS FLOAT, x1 AS INT, y1 AS INT
BITMAP ENABLE(320,200)
CLS
xp=144
xr=4.71238905
xf=xr/xp
FOR zi = 64 TO 64
zt = zi*2.25
zs = zt*zt
xl = INT(SQR(20736zs)+.5)
FOR xi = 0xl TO xl
xt = SQR(xi*xi+zs)*xf
yy = (SIN(xt)+SIN(xt*3)*0.4)*56
x1=xi+zi+160
y1=yyzi
PLOT x1,y1,YELLOW
NEXT
NEXT
Again, the result is not particularly significant on 6502 based processors, but this could depend on the approximations introduced by the use of functions that work with integers.
Let me know if I can be of any help!