Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.
|
Forum Index : Microcontroller and PC projects : donut for picomite or MMB4W etc
Author | Message | ||||
TassyJim Guru Joined: 07/08/2011 Location: AustraliaPosts: 6100 |
Should run on any mmbasic with LCD screen and MMB4W. ' donut ' https://www.a1k0n.net/2011/07/20/donut-math.html OPTION EXPLICIT OPTION DEFAULT INTEGER CONST theta_spacing = 0.07 CONST phi_spacing = 0.02 DIM FLOAT R1 = 1 DIM FLOAT R2 = 2 DIM FLOAT K2 = 5 CONST screen_width = 320 CONST screen_height = 240 ' Calculate K1 based on screen size: the maximum x-distance occurs ' roughly at the edge of the torus, which is at x=R1+R2, z=0. we ' want that to be displaced 3/8ths of the width of the screen, which ' is 3/4th of the way from the center to the side of the screen. ' screen_width*3/8 = K1*(R1+R2)/(K2+0) ' screen_width*K2*3/(8*(R1+R2)) = K1 DIM FLOAT K1 = screen_width*K2*2/(8*(R1+R2)) SUB render_frame(A AS FLOAT, B AS FLOAT) ' precompute sines and cosines of A and B LOCAL FLOAT cosA = COS(A), sinA = SIN(A) LOCAL FLOAT cosB = COS(B), sinB = SIN(B) LOCAL FLOAT costheta, sintheta LOCAL FLOAT cosphi , sinphi LOCAL FLOAT theta, phi LOCAL FLOAT circlex, circley, x,y, z, ooz, L LOCAL INTEGER xp, yp CLS ' theta goes around the cross-sectional circle of A torus FOR theta=0 TO 2*PI STEP theta_spacing ' precompute sines and cosines of theta costheta = COS(theta) : sintheta = SIN(theta) ' phi goes around the center of revolution of A torus FOR phi=0 TO 2*PI STEP phi_spacing ' precompute sines and cosines of phi cosphi = COS(phi) : sinphi = SIN(phi) ' the x,y coordinate of the circle, before revolving (factored ' out of the above equations) circlex = R2 + R1*costheta circley = R1*sintheta ' final 3D (x,y,z) coordinate after rotations, directly from ' our math above x = circlex*(cosB*cosphi + sinA*sinB*sinphi) - circley*cosA*sinB y = circlex*(sinB*cosphi - sinA*cosB*sinphi) + circley*cosA*cosB z = K2 + cosA*circlex*sinphi + circley*sinA ooz = 1/z ' "one over z" ' x and y projection. note that y is negated here, because y ' goes up in 3D space but down on 2D displays. xp = INT(screen_width/2 + K1*ooz*x) yp = INT(screen_height/2 - K1*ooz*y) ' calculate luminance. ugly, but correct. L = cosphi*costheta*sinB - cosA*costheta*sinphi L = 0.7*(L - sinA*sintheta + cosB*(cosA*sintheta - costheta*sinA*sinphi)) ' L ranges from -sqrt(2) to +sqrt(2). If it's < 0, the surface ' is pointing away from us, so we won't bother trying to plot it. IF (L > 0) THEN BOX xp,yp,3,3,1,RGB(L*255,L*255,L*255) ENDIF NEXT NEXT END SUB render_frame(1,1) DO:LOOP I failed in my attempt to get the ASCII version running. Jim VK7JH MMedit MMBasic Help |
||||
Martin H. Guru Joined: 04/06/2022 Location: GermanyPosts: 1114 |
Nice .. just tested on MMB4W To keep it flexible, I just changed two lines : CONST screen_width = MM.HRES CONST screen_height = MM.VRES Cheers Mart!n 'no comment |
||||
lizby Guru Joined: 17/05/2016 Location: United StatesPosts: 3150 |
On a 480x320 ILI9488 by a picomite, with BMP file converted to JPG: PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed |
||||
TassyJim Guru Joined: 07/08/2011 Location: AustraliaPosts: 6100 |
This one should run on the picomiteVGA in 640 x 480 mode. ' donut ' https://www.a1k0n.net/2011/07/20/donut-math.html OPTION EXPLICIT OPTION DEFAULT INTEGER CONST theta_spacing = 0.07 CONST phi_spacing = 0.02 DIM FLOAT R1 = 1 DIM FLOAT R2 = 2 DIM FLOAT K2 = 5 CONST screen_width = 160 CONST screen_height = 120 ' Calculate K1 based on screen size: the maximum x-distance occurs ' roughly at the edge of the torus, which is at x=R1+R2, z=0. we ' want that to be displaced 3/8ths of the width of the screen, which ' is 3/4th of the way from the center to the side of the screen. ' screen_width*3/8 = K1*(R1+R2)/(K2+0) ' screen_width*K2*3/(8*(R1+R2)) = K1 DIM FLOAT K1 = screen_width*K2*2/(8*(R1+R2)) SUB render_frame(A AS FLOAT, B AS FLOAT) ' precompute sines and cosines of A and B LOCAL FLOAT cosA = COS(A), sinA = SIN(A) LOCAL FLOAT cosB = COS(B), sinB = SIN(B) LOCAL FLOAT costheta, sintheta LOCAL FLOAT cosphi , sinphi LOCAL FLOAT theta, phi LOCAL FLOAT circlex, circley, x,y, z, ooz, L LOCAL INTEGER xp, yp, n CLS ' theta goes around the cross-sectional circle of A torus FOR theta=0 TO 2*PI STEP theta_spacing ' precompute sines and cosines of theta costheta = COS(theta) : sintheta = SIN(theta) ' phi goes around the center of revolution of A torus FOR phi=0 TO 2*PI STEP phi_spacing ' precompute sines and cosines of phi cosphi = COS(phi) : sinphi = SIN(phi) ' the x,y coordinate of the circle, before revolving (factored ' out of the above equations) circlex = R2 + R1*costheta circley = R1*sintheta ' final 3D (x,y,z) coordinate after rotations, directly from ' our math above x = circlex*(cosB*cosphi + sinA*sinB*sinphi) - circley*cosA*sinB y = circlex*(sinB*cosphi - sinA*cosB*sinphi) + circley*cosA*cosB z = K2 + cosA*circlex*sinphi + circley*sinA ooz = 1/z ' "one over z" ' x and y projection. note that y is negated here, because y ' goes up in 3D space but down on 2D displays. xp = INT(screen_width/2 + K1*ooz*x)*4 yp = INT(screen_height/2 - K1*ooz*y)*4 ' calculate luminance. ugly, but correct. L = cosphi*costheta*sinB - cosA*costheta*sinphi L = 0.7*(L - sinA*sintheta + cosB*(cosA*sintheta - costheta*sinA*sinphi)) ' L ranges from -sqrt(2) to +sqrt(2). If it's < 0, the surface ' is pointing away from us, so we won't bother trying to plot it. IF (L > 0) THEN ' box xp,yp,3,3,1,rgb(L*255,L*255,L*255) FOR n = 0 TO 15 IF L*15 > n THEN PIXEL xp+(n\4),yp+(n MOD 4),RGB(WHITE) ELSE 'pixel xp+(n\4),yp+(n mod 4),rgb(black) ENDIF NEXT n ENDIF NEXT NEXT END SUB render_frame(1,1) DO:LOOP very crude dithering used. Jim VK7JH MMedit MMBasic Help |
||||
TassyJim Guru Joined: 07/08/2011 Location: AustraliaPosts: 6100 |
Last one, I promise. Runs on just about anything with ASCII art output to an attached VT terminal. ' donut ' https://www.a1k0n.net/2011/07/20/donut-math.html OPTION EXPLICIT OPTION DEFAULT INTEGER CONST theta_spacing = 0.07 CONST phi_spacing = 0.02 DIM FLOAT R1 = 1 DIM FLOAT R2 = 2 DIM FLOAT K2 = 3 CONST screen_width = 80 CONST screen_height = 36 ' Calculate K1 based on screen size: the maximum x-distance occurs ' roughly at the edge of the torus, which is at x=R1+R2, z=0. we ' want that to be displaced 3/8ths of the width of the screen, which ' is 3/4th of the way from the center to the side of the screen. ' screen_width*3/8 = K1*(R1+R2)/(K2+0) ' screen_width*K2*3/(8*(R1+R2)) = K1 DIM FLOAT K1 = screen_width*K2*2/(16*(R1+R2)) SUB render_frame(A AS FLOAT, B AS FLOAT) ' precompute sines and cosines of A and B LOCAL FLOAT cosA = COS(A), sinA = SIN(A) LOCAL FLOAT cosB = COS(B), sinB = SIN(B) LOCAL FLOAT costheta, sintheta LOCAL FLOAT cosphi , sinphi LOCAL FLOAT theta, phi LOCAL FLOAT circlex, circley, x,y, z, ooz, L LOCAL INTEGER xp, yp, n ' cls PRINT CHR$(27)+"[2J"; ' theta goes around the cross-sectional circle of A torus FOR theta=0 TO 2*PI STEP theta_spacing ' precompute sines and cosines of theta costheta = COS(theta) : sintheta = SIN(theta) ' phi goes around the center of revolution of A torus FOR phi=0 TO 2*PI STEP phi_spacing ' precompute sines and cosines of phi cosphi = COS(phi) : sinphi = SIN(phi) ' the x,y coordinate of the circle, before revolving (factored ' out of the above equations) circlex = R2 + R1*costheta circley = R1*sintheta ' final 3D (x,y,z) coordinate after rotations, directly from ' our math above x = circlex*(cosB*cosphi + sinA*sinB*sinphi) - circley*cosA*sinB y = circlex*(sinB*cosphi - sinA*cosB*sinphi) + circley*cosA*cosB z = K2 + cosA*circlex*sinphi + circley*sinA ooz = 1/z ' "one over z" ' x and y projection. note that y is negated here, because y ' goes up in 3D space but down on 2D displays. xp = INT(screen_width/2 + K1*ooz*x) yp = INT(screen_height/2 - K1*ooz*y)+5 ' calculate luminance. ugly, but correct. L = cosphi*costheta*sinB - cosA*costheta*sinphi L = 0.7*(L - sinA*sintheta + cosB*(cosA*sintheta - costheta*sinA*sinphi)) ' L ranges from -sqrt(2) to +sqrt(2). If it's < 0, the surface ' is pointing away from us, so we won't bother trying to plot it. IF L > 0 THEN PRINT CHR$(27)+"["+STR$(yp)+";"+STR$(xp)+"H"+MID$(".,-~:;=!*#$@@@@",L*11+1,1); ENDIF NEXT NEXT END SUB render_frame(1,1) PRINT CHR$(27)+"[1;1H" DO:LOOP $$@@@@@@@@$ $$$$$$$$$@@@@@$ $$$$$$$$$$$$$$$@$s $###$$*****!!$$$$$$s #####**!!!!!!!!!$$$$$ ####**!!!!=!===;;==#### ####**!!!====;;;;;;;;#### ****!!!!===;;;;::::::;*** *****!!!===;;;:~~~~~~~~*!** *!!!!!!===;;::~~~-----~~!=! *!!!!!====;;::~~--,,...,-=;= *!!!!!===;;;:~~-,.. ..-~;;= !!=!!===;;;:~~-,, ..-~:; !==!===;;;::~--,. .--~; !======;;;::~--. -,-: =;;====;;;:~~-,. .-.,~ =;;===;;;::~~-, .,-~..~ =;:==;;;:::~--,. ~:::;;.~ =;::=;;;:::~~-,. !!==;;. ;:~=;;;:::~~-,,,- ###*!=.. ;~~-;;;::::~~---~=*@@$#!;.- ;:~-;;;;::::~~~~;!#@@$#!.. :~-,;;;:::::~::=!#$$#!:. ~-,,;:::::::;;=!###!:.. -,.:::::::;;;=!!!=:.. -,.::::::;;;===;-.. ,,.:::::::;::-.. -...~~~~~~..,. .....,.. Looks better on a black background. Jim VK7JH MMedit MMBasic Help |
||||
Amnesie Guru Joined: 30/06/2020 Location: GermanyPosts: 396 |
Just tried it on the PicoVGA, really cool! I think the dithering is kind of interesting... Greetings Daniel |
||||
Martin H. Guru Joined: 04/06/2022 Location: GermanyPosts: 1114 |
I the ASCII Version 'no comment |
||||
Print this page |