qb64.com/samples/torus-demo/
( this version was probably converted to brand new QB64 so I did not managed to run it as is )
Now it works in LB/LBB/(even JB if change API call with commented-out filled triangle sub by Andy Amaya)


It was rather complex conversion (long program), and I used Notepad++/LBB/JB/LB
I used LBB to spot erroneous lines and convert it one-by-one
- because it just selected next errorand stop there
(while JB made error message without particular line to fix)
I used JB to actually debug stuff (because I am used to it)
I used LB to put fast API call (polygon) instead of slow filling triangle by lines
Then I run it in LBB and found black rectangles all over the colored tiles
Happened to be (topic in LBB help section on Troubleshooting)
that LBB needs some wait statements to "reconcile" API-drawn graphics
(or so I got)
So I changed busy loop to Timer/Wait, now program works on both LB and LBB.
'from qb64.com/samples/torus-demo/
'conversion to JB by tsh73
'March 2024
'-----------------------------------------------------------------------------------------------------
' TORUS
' This program draws a Torus figure. The program accepts user input
' to specify various TORUS parameters. It checks the current system
' configuration and takes appropriate action to set the best possible
' initial mode.
'-----------------------------------------------------------------------------------------------------
global FALSE, TRUE
global C.RNDM, C.START, C.CONTINUE
global VGA', MCGA, EGA256, EGA64, MONO, HERC, CGA
global BACK$
BACK$ = "black"
'BACK$ = "darkblue"
'Sub TorusDefine
global TOR.Thick, TOR.Bord$, TOR.Panel, TOR.Sect, TOR.XDegree, TOR.YDegree, TOR.Delay
'Sub SetConfig
global VC.Colors, VC.Atribs, VC.XPix, VC.YPix, VC.TCOL, VC.TROW, VC.Scrn
global QuitRequested, Pi
'Sub TileDraw
Global T.x1,T.x2,T.x3,T.x4,T.y1,T.y2,T.y3,T.y4,T.z1,T.xc,T.yc,T.TColor
'Sub TorusCalc
'indices for columns in T(tile, column)
Global Ix1, Ix2, Ix3, Ix4, Iy1, Iy2, Iy3, Iy4, Iz1, Ixc, Iyc, ITColor
Dim T(10, 12) 'to be redimmed
Ix1=1:Ix2=2:Ix3=3:Ix4=4:Iy1=5:Iy2=6:Iy3=7:Iy4=8:Iz1=9:Ixc=10:Iyc=11:ITColor=12
'Sub TorusColor
global Max
'Sub TorusRotate , to preserve between calls
global FirstClr
Pi=acs(-1)
' General purpose constants
FALSE = 0: TRUE = Not( FALSE)
BACK = 0
TROW = 24: TCOL = 60
' Rotation flags
C.RNDM = -1: C.START = 0: C.CONTINUE = 1
' Constants for best Available screen mode
VGA = 12 'set on this
' MCGA = 13
' EGA256 = 9
' EGA64 = 8
' MONO = 10
' HERC = 3
' CGA = 1
' User-defined type for tiles - an array of these make a torus
' used array T(numTiles, 12) instead, with colNumbers Ix1, Ix2, ..., ITColor
' Type Tile
' x1 As Single
' x2 As Single
' x3 As Single
' x4 As Single
' y1 As Single
' y2 As Single
' y3 As Single
' y4 As Single
' z1 As Single
' xc As Single
' yc As Single
' TColor As Integer
' End Type
' User-defined type to hold information about the mode
' Type Config
' Scrn As Integer
' Colors As Integer
' Atribs As Integer
' XPix As Integer
' YPix As Integer
' TCOL As Integer
' TROW As Integer
' End Type
'''Dim VC As Config
'only single instance
'used global vars VC.Scrn etc instead
' User-defined type to hold information about current Torus
' Type TORUS
' Panel As Integer
' Sect As Integer
' Thick As Single
' XDegree As Integer
' YDegree As Integer
' Bord As String * 3
' Delay As Single
' End Type
''Dim TOR As TORUS, Max As Integer
'only single instance
'used global vars TORUS.Panel etc instead
' A palette of colors to paint with
Dim Pal(300) 'As Long
'added to use with JB
Dim Pal$(300)
Dim Colr$(300)
STRUCT PolyPoints,_
x1 as long,_
y1 as long,_
x2 as long,_
y2 as long,_
x3 as long,_
y3 as long,_
x4 as long,_
y4 as long
' The code of the module-level program begins here
' Initialize defaults
TOR.Thick = 3: TOR.Bord$ = "YES"
TOR.Panel = 8: TOR.Sect = 14
TOR.XDegree = 60: TOR.YDegree = 165
' Get best configuration and set initial graphics mode to it
'just set for VGA for now
VC.Scrn = VGA
Do While TRUE ' Loop forever (exit is from within a SUB)
' Get Torus definition from user
call TorusDefine
' Dynamically dimension arrays
Tmp = TOR.Panel
Max = TOR.Panel * TOR.Sect
' Array for indexes
ReDim Index(Max - 1)
' Array for tiles
ReDim T(Max - 1, 12) ''As Tile
' Initialize array of indexes
For Til = 0 To Max - 1
Index(Til) = Til
Next
' Calculate the points of each tile on the torus
call Message "Calculating"
call TorusCalc '' T(max, 12), and arrays are global in JB
' Sort the tiles by their "distance" from the screen
call Message "Sorting"
call TorusSort 0, Max - 1
'open corresponding gr window
' ajust for borders
desiredWidth = VC.XPix+1
desiredHeight = VC.YPix+1
gosub [ajustWindow]
UpperLeftX=int((DisplayWidth-WindowWidth)/2)
UpperLeftY=int((DisplayHeight-WindowHeight)/2)
open "Torus" for graphics_nsb_nf as #gr
#gr, "trapclose [quit]"
#gr, "down; fill ";BACK$
#gr, "flush"
' Mix a palette of colors
call SetPalette
' Color each tile in the torus.
call TorusColor
' Set logical window with variable thickness
' Center is 0, up and right are positive, down and left are negative
''Window (-(TOR.Thick + 1), -(TOR.Thick + 1))-(TOR.Thick + 1, TOR.Thick + 1)
global width, minX, maxX, height, minY, maxY
width=VC.XPix+1
minX=0-(TOR.Thick + 1)
maxX=TOR.Thick + 1
height=VC.YPix+1
minY=0-(TOR.Thick + 1)
maxY=TOR.Thick + 1
global hdc
h=hwnd(#gr) 'window handle
'get device context for window:
calldll #user32, "GetDC",_
h as ulong,_ 'window handle
hdc as ulong 'returns handle to device context
' Draw and paint the tiles, the farthest first and nearest last
call Message "Drawing"
call TorusDraw
' Rotate the torus by rotating the color palette
Do While 1''InKey$ = ""
SCAN
'call Delay TOR.Delay
'if QuitRequested then [quit]
timer TOR.Delay*1000, [waitABit]
wait
[waitABit]
timer 0
#gr, "discard"
call TorusRotate C.CONTINUE
call Message "Drawing"
call TorusDraw
Loop
Loop
[quit]
calldll #user32, "ReleaseDC",_
h as ulong,_ 'window handle
hdc as ulong,_ 'device context
ret as long
timer 0
close #gr
end
' ============================ CountTiles ==============================
' Displays number of the tiles currently being calculated or sorted.
' ======================================================================
'
Sub CountTiles T1, T2
Print "Tile "; Using (" ###", T1); Using (" ###", T2)
End Sub
' ============================ DegToRad ================================
' Convert degrees to radians, since BASIC trigonometric functions
' require radians.
' ======================================================================
'
Function DegToRad (Degrees)
DegToRad = (Degrees * 2 * Pi) / 360
End Function
' ============================= Message ================================
' Displays a status message followed by blinking dots.
' ======================================================================
'
Sub Message Text$
Print "-";
print time$();".";time$("ms") mod 1000;
print "-------------------------"
'Print "-22:17:30.421-------------------------"
Print Text$
Print "--------------------------------------"
End Sub
' ============================ SetConfig ===============================
' Sets the correct values for each field of the VC variable. They
' vary depending on Mode and on the current configuration.
' ======================================================================
'
Sub SetConfig mode 'use VGA for now
'Case 12 ' 16-color very high-res graphics for VGA
VC.Colors = 216
VC.Atribs = 16
VC.XPix = 639
VC.YPix = 479
'VC.XPix = 319
'VC.YPix = 239
VC.TCOL = 80
VC.TROW = 30
VC.Scrn = mode
End Sub
' ============================ SetPalette ==============================
' Mixes palette colors in an array.
' ======================================================================
'
Sub SetPalette
VC.Colors = TOR.Sect 'this makes each section to have same color
' VC.Colors = TOR.Sect*2
' VC.Colors = TOR.Sect*TOR.Panel '==Max == number of tiles
' VC.Colors = Max
' VC.Colors =256
for i = 0 to VC.Colors-1
Colr$(i)=rainbow$(i/VC.Colors)
next
' Assign colors
call TorusRotate C.RNDM
' print "--- SetPalette -----"
' print "VC.Colors",VC.Colors
' print "Index", Index
' for i = 0 to VC.Colors-1
' print i, Colr$(i)
' next
' print "--- //SetPalette ---"
End Sub
' ============================ TileDraw ================================
' Draw and optionally paint a tile. Tiles are painted if there are
' more than two atributes and if the inside of the tile can be found.
' ======================================================================
'
Sub TileDraw
'copyToGlobT is called before
'fill the tile - as 2 triangles
activeColr=(T.TColor+FirstClr) mod VC.Colors
'print "activeColr ",activeColr, Colr$(activeColr)
'LB way - API call
#gr "backcolor ";Colr$(activeColr)
nCount=4 'number of x,y pairs in STRUCT
PolyPoints.x1.struct = sx(T.x1)
PolyPoints.y1.struct = sy(T.y1)
PolyPoints.x2.struct = sx(T.x2)
PolyPoints.y2.struct = sy(T.y2)
PolyPoints.x3.struct = sx(T.x3)
PolyPoints.y3.struct = sy(T.y3)
PolyPoints.x4.struct = sx(T.x4)
PolyPoints.y4.struct = sy(T.y4)
calldll #gdi32, "Polygon",_
hdc as ulong,_ 'device context of window or control
PolyPoints as struct,_'array of points
nCount as long,_ 'number of x,y pairs in array
result as long
''''JB way
' #gr "color ";Colr$(activeColr)
' call fillTriangle "#gr",sx(T.x1),sy(T.y1),sx(T.x2),sy(T.y2),sx(T.x3),sy(T.y3)
''paint over possible diagonal line
' #gr "size 2"
' #gr "line ";sx(T.x1);" ";sy(T.y1);" ";sx(T.x3);" ";sy(T.y3)
' #gr "size 1"
' call fillTriangle "#gr",sx(T.x1),sy(T.y1),sx(T.x4),sy(T.y4),sx(T.x3),sy(T.y3)
' A border drawn with the background color looks like a border.
' One drawn with the tile color doesn't look like a border.
If TOR.Bord$ = "YES" Then
Border$ = BACK$
Else
Border$ = Colr$(activeColr)
End If
' Redraw with the final border
' Line (T.x1, T.y1)-(T.x2, T.y2), Border
' Line -(T.x3, T.y3), Border
' Line -(T.x4, T.y4), Border
' Line -(T.x1, T.y1), Border
#gr "color ";Border$
#gr "line ";sx(T.x1);" ";sy(T.y1);" ";sx(T.x2);" ";sy(T.y2)
#gr "goto ";sx(T.x3);" ";sy(T.y3)
#gr "goto ";sx(T.x4);" ";sy(T.y4)
#gr "goto ";sx(T.x1);" ";sy(T.y1)
End Sub
' =========================== TorusCalc ================================
' Calculates the x and y coordinates for each tile.
' ======================================================================
'
Sub TorusCalc ''(T() As Tile) Static 'now use T(tile, column)
' Calculate sine and cosine of the angles of rotation
XRot = DegToRad(TOR.XDegree)
YRot = DegToRad(TOR.YDegree)
CXRot = Cos(XRot)
SXRot = Sin(XRot)
CYRot = Cos(YRot)
SYRot = Sin(YRot)
' Calculate the angle to increment between one tile and the next.
XInc = 2 * Pi / TOR.Sect
YInc = 2 * Pi / TOR.Panel
' First calculate the first point, which will be used as a reference
' for future points. This point must be calculated separately because
' it is both the beginning and the end of the center seam.
FirstY = (TOR.Thick + 1) * CYRot
' Starting point is x1 of 0 section, 0 panel last 0
T(0,Ix1) = FirstY ' +------+------+
' Also x2 of tile on last section, 0 panel ' | | | last
T(TOR.Sect - 1,Ix2) = FirstY ' | x3|x4 |
' Also x3 of last section, last panel ' +------+------+
T(Max - 1,Ix3) = FirstY ' | x2|x1 | 0
' Also x4 of 0 section, last panel ' | | |
T(Max - TOR.Sect,Ix4) = FirstY ' +------+------+
' A similar pattern is used for assigning all points of Torus
' Starting Y point is 0 (center)
T(0,Iy1) = 0
T(TOR.Sect - 1,Iy2) = 0
T(Max - 1,Iy3) = 0
T(Max - TOR.Sect,Iy4) = 0
' Only one z coordinate is used in sort, so other three can be ignored
T(0,Iz1) = 0-(TOR.Thick + 1) * SYRot
' Starting at first point, work around the center seam of the Torus.
' Assign points for each section. The seam must be calculated separately
' because it is both beginning and of each section.
For XSect = 1 To TOR.Sect - 1
' X, Y, and Z elements of equation
sx = (TOR.Thick + 1) * Cos(XSect * XInc)
sy = (TOR.Thick + 1) * Sin(XSect * XInc) * CXRot
sz = (TOR.Thick + 1) * Sin(XSect * XInc) * SXRot
ssx = (sz * SYRot) + (sx * CYRot)
T(XSect,Ix1) = ssx
T(XSect - 1,Ix2) = ssx
T(Max - TOR.Sect + XSect - 1,Ix3) = ssx
T(Max - TOR.Sect + XSect,Ix4) = ssx
T(XSect,Iy1) = sy
T(XSect - 1,Iy2) = sy
T(Max - TOR.Sect + XSect - 1,Iy3) = sy
T(Max - TOR.Sect + XSect,Iy4) = sy
T(XSect,Iz1) = (sz * CYRot) - (sx * SYRot)
Next
' Now start at the first seam between panel and assign points for
' each section of each panel. The outer loop assigns the initial
' point for the panel. This point must be calculated separately
' since it is both the beginning and the end of the seam of panels.
For YPanel = 1 To TOR.Panel - 1
' X, Y, and Z elements of equation
sx = TOR.Thick + Cos(YPanel * YInc)
sy = 0-Sin(YPanel * YInc) * SXRot
sz = Sin(YPanel * YInc) * CXRot
ssx = (sz * SYRot) + (sx * CYRot)
' Assign X points for each panel
' Current ring, current side
T(TOR.Sect * YPanel,Ix1) = ssx
' Current ring minus 1, next side
T(TOR.Sect * (YPanel + 1) - 1,Ix2) = ssx
' Current ring minus 1, previous side
T(TOR.Sect * YPanel - 1,Ix3) = ssx
' Current ring, previous side
T(TOR.Sect * (YPanel - 1),Ix4) = ssx
' Assign Y points for each panel
T(TOR.Sect * YPanel,Iy1) = sy
T(TOR.Sect * (YPanel + 1) - 1,Iy2) = sy
T(TOR.Sect * YPanel - 1,Iy3) = sy
T(TOR.Sect * (YPanel - 1),Iy4) = sy
' Z point for each panel
T(TOR.Sect * YPanel,Iz1) = (sz * CYRot) - (sx * SYRot)
' The inner loop assigns points for each ring (except the first)
' on the current side.
For XSect = 1 To TOR.Sect - 1
' Display section and panel
call CountTiles XSect, YPanel
ty = (TOR.Thick + Cos(YPanel * YInc)) * Sin(XSect * XInc)
tz = Sin(YPanel * YInc)
sx = (TOR.Thick + Cos(YPanel * YInc)) * Cos(XSect * XInc)
sy = ty * CXRot - tz * SXRot
sz = ty * SXRot + tz * CXRot
ssx = (sz * SYRot) + (sx * CYRot)
T(TOR.Sect * YPanel + XSect,Ix1) = ssx
T(TOR.Sect * YPanel + XSect - 1,Ix2) = ssx
T(TOR.Sect * (YPanel - 1) + XSect - 1,Ix3) = ssx
T(TOR.Sect * (YPanel - 1) + XSect,Ix4) = ssx
T(TOR.Sect * YPanel + XSect,Iy1) = sy
T(TOR.Sect * YPanel + XSect - 1,Iy2) = sy
T(TOR.Sect * (YPanel - 1) + XSect - 1,Iy3) = sy
T(TOR.Sect * (YPanel - 1) + XSect,Iy4) = sy
T(TOR.Sect * YPanel + XSect,Iz1) = (sz * CYRot) - (sx * SYRot)
Next
Next
' Erase message
call CountTiles -1, -1
End Sub
' =========================== TorusColor ===============================
' Assigns color atributes to each tile.
' ======================================================================
'
Sub TorusColor
' Cycle through each attribute until all tiles are done
For Til = 0 To Max - 1
T(Til,ITColor) = Til mod VC.Colors
print "Colr",Til, T(Til,ITColor)
Next
End Sub
' ============================ TorusDefine =============================
' Define the attributes of a Torus based on information from the
' user, the video configuration, and the current screen mode.
' ======================================================================
'
Sub TorusDefine 'LB window to setup params
WindowWidth = 328
WindowHeight = 260
UpperLeftX=int((DisplayWidth-WindowWidth)/2)
UpperLeftY=int((DisplayHeight-WindowHeight)/2)
statictext #main.statictext1, "Thickness", 22, 16, 144, 20
textbox #main.txtThick, 190, 11, 100, 25
statictext #main.statictext3, "Panels per Section", 22, 41, 144, 20
textbox #main.txt.Panel, 190, 36, 100, 25
statictext #main.statictext5, "Sections per Torus", 22, 66, 144, 20
textbox #main.txt.Sect, 190, 61, 100, 25
statictext #main.statictext7, "Tilt around Horizontal Axis", 22, 91, 144, 20
textbox #main.txtXDegree, 190, 86, 100, 25
statictext #main.statictext9, "Tilt around Vertical Axis", 22, 116, 144, 20
textbox #main.txtYDegree, 190, 111, 100, 25
statictext #main.statictext11, "Tile Border", 22, 141, 144, 20
textbox #main.txtBord, 190, 136, 100, 25
statictext #main.statictext13, "Screen Mode", 22, 166, 144, 20
statictext #main.lblScrn, "12 (640x480)", 190, 166, 144, 20
button #main.button16, "Start", [btnStartClick], UL, 22, 191, 122, 25
button #main.button17, "Quit", [btnQuitClick], UL, 174, 191, 122, 25
open "Torus" for window_nf as #main
print #main, "trapclose [quit.main]"
print #main, "font ms_sans_serif 10"
#main.txtThick TOR.Thick
#main.txt.Panel TOR.Panel
#main.txt.Sect TOR.Sect
#main.txtXDegree TOR.XDegree
#main.txtYDegree TOR.YDegree
#main.txtBord TOR.Bord$
' #main.lblScrn VC.Scrn
#main.button16, "!setfocus"
wait
[quit.main]
Close #main
END
[btnStartClick]
'get data and return
errList$=chr$(13)
#main.txtThick "!contents? TOR.Thick" '1, 9
errList$=errList$+chkRange$("TOR.Thick", TOR.Thick, 1, 9)
#main.txt.Panel "!contents? TOR.Panel" '6, 20
errList$=errList$+chkRange$("TOR.Panel", TOR.Panel, 6, 20)
#main.txt.Sect "!contents? TOR.Sect" '6, 20
errList$=errList$+chkRange$("TOR.Sect", TOR.Sect, 6, 20)
#main.txtXDegree "!contents? TOR.XDegree" '0, 345, by 15deg
errList$=errList$+chkRange$("TOR.XDegree", TOR.XDegree, 0, 345)
#main.txtYDegree "!contents? TOR.YDegree" '0, 345, by 15deg
errList$=errList$+chkRange$("TOR.YDegree", TOR.YDegree, 0, 345)
#main.txtBord "!contents? TOR.Bord$" 'YES NO
if (TOR.Bord$<>"YES") and (TOR.Bord$<>"NO") then
errList$=errList$+"TOR.Bord$ value (";TOR.Bord$;") should be YES or NO"
end if
if trim$(errList$)<>"" then
notice "Errors found: ";errList$
wait
end if
Close #main
call SetConfig VC.Scrn
' Set different delays depending on mode
'Case Else
TOR.Delay = 1 '.05 'drawing torus take lots of time
' Get new random seed for this torus
' JB uses new random each run
exit sub
wait
[btnQuitClick] 'Perform action for the button named 'button17'
goto [quit.main]
end sub
' =========================== TorusDraw ================================
' Draws each tile of the torus starting with the farthest and working
' to the closest. Thus nearer tiles overwrite farther tiles to give
' a three-dimensional effect. Notice that the index of the tile being
' drawn is actually the index of an array of indexes. This is because
' the array of tiles is not sorted, but the parallel array of indexes
' is. See TorusSort for an explanation of how indexes are sorted.
' ======================================================================
'
Sub TorusDraw
For Til = 0 To Max - 1
call copyToGlobT Til 'T(Index(Til)) - >T.*
'print "Tile ",Til,
call TileDraw ''T(Index(Til))
Next
End Sub
' =========================== TorusRotate ==============================
' Rotates the Torus. This can be done more successfully in some modes
' than in others. There are three methods:
'
' 1. Rotate the palette colors assigned to each attribute
' 2. Draw, erase, and redraw the torus (two-color modes)
' 3. Rotate between two palettes (CGA and MCGA screen 1)
'
' Note that for EGA and VGA screen 2, methods 1 and 2 are both used.
' ======================================================================
'
Sub TorusRotate First
' Argument determines whether to start at next color, first color,
' or random color
Select Case First
Case C.RNDM
FirstClr = Int(Rnd(0) * VC.Colors)
Case C.START
FirstClr = 0
Case Else
FirstClr = (FirstClr+1) mod VC.Colors
End Select
End Sub
' ============================ TorusSort ===============================
' Sorts the tiles of the Torus according to their Z axis (distance
' from the "front" of the screen). When the tiles are drawn, the
' farthest will be drawn first, and nearer tiles will overwrite them
' to give a three-dimensional effect.
'
' To make sorting as fast as possible, the Quick Sort algorithm is
' used. Also, the array of tiles is not actually sorted. Instead a
' parallel array of tile indexes is sorted. This complicates things,
' but makes the sort much faster, since two-byte integers are swapped
' instead of 46-byte Tile variables.
' ======================================================================
'
Sub TorusSort Low, High
'basically, qsort of indices T(Index(i),Iz1)
If Low < High Then
' If only one, compare and swap if necessary
' The SUB procedure only stops recursing when it reaches this point
If High - Low = 1 Then
If T(Index(Low),Iz1) > T(Index(High),Iz1) Then
call CountTiles High, Low
call swapIndex Low,High
End If
Else
' If more than one, separate into two random groups
RandIndex = Int(Rnd * (High - Low + 1)) + Low
call CountTiles High, Low
call swapIndex High, RandIndex
Partition = T(Index(High),Iz1)
' Sort one group
Do
i = Low: j = High
' Find the largest
Do While (i < j) And (T(Index(i),Iz1) <= Partition)
i = i + 1
Loop
' Find the smallest
Do While (j > i) And (T(Index(j),Iz1) >= Partition)
j = j - 1
Loop
' Swap them if necessary
If i < j Then
call CountTiles High, Low
call swapIndex i, j
End If
Loop While i < j
' Now get the other group and recursively sort it
call CountTiles High, Low
call swapIndex i, High
If (i - Low) < (High - i) Then
call TorusSort Low, i - 1
call TorusSort i + 1, High
Else
call TorusSort i + 1, High
call TorusSort Low, i - 1
End If
End If
End If
End Sub
'- aux funcs by tsh73, for TileDraw ------------------------------
'should be global
'Global T.x1,T.x2,T.x3,T.x4,T.y1,T.y2,T.y3,T.y4,T.z1,T.xc,T.yc,T.TColor
sub copyToGlobT Til
T.x1=T(Index(Til), Ix1)
T.x2=T(Index(Til), Ix2)
T.x3=T(Index(Til), Ix3)
T.x4=T(Index(Til), Ix4)
T.y1=T(Index(Til), Iy1)
T.y2=T(Index(Til), Iy2)
T.y3=T(Index(Til), Iy3)
T.y4=T(Index(Til), Iy4)
T.z1=T(Index(Til), Iz1)
T.xc=T(Index(Til), Ixc)
T.yc=T(Index(Til), Iyc)
T.TColor=T(Index(Til), ITColor)
end sub
'- aux func by Tsh73, for new Sub TorusDefine -------------------
function chkRange$(varName$, varVal, mn, mx)
if (varVal < mn) or (varVal > mx) then
chkRange$=varName$;" value (";varVal;") is out of range [";mn;", ";mx;"]"+chr$(13)
end if
end function
sub Delay sec 'now after pause you can check if QuitRequested
t=time$("ms")
while time$("ms")<t+sec*1000
scan
wend
exit sub
[quit]
QuitRequested=1
end sub
sub swapIndex idx1, idx2
tmp=Index(idx1):Index(idx1)=Index(idx2):Index(idx2)=tmp
end sub
'conversions (logical coords to screen)
function sx(x)
'screen X. Depends on width, minX, maxX
sx = int((x- minX)/(maxX-minX) * width)
end function
function sy(y)
'screen Y. Depends on height, minY, maxY. Upside down.
sy = int((1-(y- minY)/(maxY-minY)) * height)
end function
'- Fast Filled Triangle sub by Andy Amaya ------------
Sub fillTriangle h$,x1, y1, x2, y2, x3, y3
'triangle coordinates must be ordered: where x1 < x2 < x3
If x2 < x1 Then x = x2 : y = y2 : x2 = x1 : y2 = y1 : x1 = x : y1 = y
'swap x1, y1, with x3, y3
If x3 < x1 Then x = x3 : y = y3 : x3 = x1 : y3 = y1 : x1 = x : y1 = y
'swap x2, y2 with x3, y3
If x3 < x2 Then x = x3 : y = y3 : x3 = x2 : y3 = y2 : x2 = x : y2 = y
If x1 <> x3 Then slope1 = (y3-y1)/(x3-x1)
'draw the first half of the triangle
length = x2 - x1
If length <> 0 Then
slope2 = (y2-y1)/(x2-x1)
For x = 0 To length
'if X is not integer, using INT on then will improve timing
#h$ "Line ";int(x+x1);" ";int(x*slope1+y1);" ";int(x+x1);" ";int(x*slope2+y1)
'#h$ "Line ";x+x1;" ";int(x*slope1+y1);" ";x+x1;" ";int(x*slope2+y1)
Next
End If
'draw the second half of the triangle
y = length*slope1+y1 : length = x3-x2
If length <> 0 Then
slope3 = (y3-y2)/(x3-x2)
For x = 0 To length
#h$ "Line ";int(x+x2);" ";int(x*slope1+y);" ";int(x+x2);" ";int(x*slope3+y2)
'#h$ "Line ";x+x2;" ";int(x*slope1+y);" ";x+x2;" ";int(x*slope3+y2)
Next
End If
End Sub
'---------------------------------------------
' 0..1 into red-green-blue-red continuous colors
function rainbow$(x)
hi = int((x*6) mod 6)+ 5*(x<0) 'fixed to 0..5
f = (x*6) mod 1 + (x<0) 'frac, 0..1
q = (1-f)
select case hi
case 0
r = 1: g = f: b = 0
case 1
r = q: g = 1: b = 0
case 2
r = 0: g = 1: b = f
case 3
r = 0: g = q: b = 1
case 4
r = f: g = 0: b = 1
case 5
r = 1: g = 0: b = q
end select
R = int(r*255)
G = int(g*255)
B = int(b*255)
rainbow$= R;" ";G;" ";B
end function
[ajustWindow]
UpperLeftX = 20
UpperLeftY = 20
WindowWidth = 200 '100 seems to be too much - works different
WindowHeight = 100
open "Ajusting..." for graphics_nsb_nf as #gr
' graphics
' graphics_nsb
' graphics_nsb_nf
#gr, "home ; down ; posxy x y"
'x, y give us width, height
width = 2*x : height = 2*y
close #gr
slackX = 200-width
slackY = 100-height
WindowWidth = desiredWidth + slackX
WindowHeight = desiredHeight + slackY
return