-
Hi,
I prepared a code skeleton for you, Brian.
It allows you to render any 2D function, move over it and zoom in/out.
To change what is drawn, just edit buildGraphicsAs function.
Code:
uses "UI", "TBGL"
begin const
%MAIN_WIDTH = 640 ' -- Default dialog size
%MAIN_HEIGHT = 480
%timeOut = 20 ' -- Determines graphics refresh rate in milliseconds
%myCoolChart = 1 ' -- "Nickname" for geometry cache
end const
' -- ID numbers of controls
begin controlId
%lCanvas
%bZoomIn, %bZoomOut, %bClose
%hScroll, %vScroll
%myTimer
end controlId
type GraphicView
private
position as tbgl_tVector3f
cachedGraphics as long
minDistance as single
maxDistance as single
public
function _Create()
me.minDistance = 1
me.maxDistance = 140
end function
' Camera controls
function ZoomIn(zoomStep as single)
me.position.z -= zoomStep
if me.position.z < me.minDistance then me.position.z = me.minDistance
end function
function ZoomOut(zoomStep as single)
me.position.z += zoomStep
if me.position.z > me.maxDistance then me.position.z = me.maxDistance
end function
function SetZoom(z as single)
z = minmax(z, me.minDistance, me.maxDistance)
me.position.z = z
end function
function SetPosition(x as single, y as single)
me.position.x = x
me.position.y = y
end function
' Rendering controls
function SetGraphics(cachedGraphics as long)
me.cachedGraphics = cachedGraphics
end function
function UpdateScreen()
tbgl_clearFrame
tbgl_camera me.position.x, me.position.y, me.position.z, me.position.x, me.position.y, 0
tbgl_pushStateProtect %TBGL_DEPTH ' -- Disable depth tests, make draw order matter
tbgl_callList me.cachedGraphics
tbgl_popStateProtect
tbgl_drawFrame
end function
end type
dim graphView as GraphicView()
function tbMain()
dWord hDlg
dialog new pixels, 0, "Function plotting in TBGL",-1,-1, %MAIN_WIDTH, %MAIN_HEIGHT, %WS_POPUP | %WS_VISIBLE | %WS_CLIPCHILDREN | %WS_CAPTION | %WS_SYSMENU | %WS_MINIMIZEBOX | %WS_MAXIMIZEBOX | %WS_THICKFRAME To hDlg
control add Label, hDlg, %lCanvas, "", 5, 5, %MAIN_WIDTH-20, %MAIN_HEIGHT-60
control set color hDlg, %lCanvas, %BLACK, %BLACK
control set resize hDlg, %lCanvas, 1, 1, 1, 1
control add scrollbar hDlg, %hScroll, "", 5, 5+%MAIN_HEIGHT-60, %MAIN_WIDTH-20, 15, %SBS_HORZ
scrollbar_setrange(hDlg, %hScroll, -10000, 10000)
scrollbar_setpos(hDlg, %hScroll, 0)
control set resize hDlg, %hScroll, 1, 1, 0, 1
control add scrollbar hDlg, %vScroll, "", %MAIN_WIDTH-15, 5, 15, %MAIN_HEIGHT-60, %SBS_vert
scrollbar_setrange(hDlg, %vScroll, -10000, 10000)
scrollbar_setpos(hDlg, %vScroll, 0)
control set resize hDlg, %vScroll, 0, 1, 1, 1
control add button, hDlg, %bZoomIn, "Zoom in", 5, %MAIN_HEIGHT-30, 100, 25
control set resize hDlg, %bZoomIn, 1, 0, 0, 1
control add button, hDlg, %bZoomOut, "Zoom out", 105, %MAIN_HEIGHT-30, 100, 25
control set resize hDlg, %bZoomOut, 1, 0, 0, 1
control add button, hDlg, %bClose, "Close", %MAIN_WIDTH-105, %MAIN_HEIGHT-30, 100, 25
control set resize hDlg, %bClose, 0, 1, 0, 1
dialog set minsize hDlg, 320, 230
dialog show modal hDlg, call dlgCallback
end function
callback function dlgCallback()
static myCanvas as dword
static positionX, positionY as single
select case callback_message
case %WM_INITDIALOG
dialog set timer callback_handle, %myTimer, %timeOut, %NULL
control handle cbhndl, %lCanvas to myCanvas
tbgl_bindCanvas(myCanvas)
buildGraphicsAs %myCoolChart
graphView.setGraphics(%myCoolChart)
graphView.setZoom(25)
case %WM_SIZE, %WM_SIZING
tbgl_updateCanvasProportions(myCanvas)
graphView.setPosition(positionX, positionY)
if tbgl_canvasBound(myCanvas) then
graphView.UpdateScreen()
end if
case %WM_HSCROLL
positionX = HandleScrollBarEvents(cbhndl, %hScroll, LoWrd(cbwParam))
case %WM_vSCROLL
positionY = -HandleScrollBarEvents(cbhndl, %vScroll, LoWrd(cbwParam))
case %WM_TIMER
graphView.setPosition(positionX, positionY)
if tbgl_canvasBound(myCanvas) then
graphView.UpdateScreen()
end if
case %WM_CLOSE
tbgl_releaseCanvas(myCanvas)
dialog kill timer callback_handle, %myTimer
case %WM_COMMAND
select case callback_control
case %bClose : if callback_control_message = %BN_CLICKED then dialog end callback_handle
case %bZoomIn : if callback_control_message = %BN_CLICKED then graphView.zoomIn(1)
case %bZoomOut : if callback_control_message = %BN_CLICKED then graphView.zoomOut(1)
end select
end select
end function
' -- Build the graphics in this function
function buildGraphicsAs(listSlot as long)
single i
' Everything between newList/endList will get stored under listSlot
tbgl_newList listSlot
' Grid, built line by line
for i = -10000 to 10000
tbgl_line i, -10000, i, 10000
tbgl_line -10000, i, 10000, i
next
' Main axes in yellow
tbgl_pushColor 255, 255, 0
tbgl_pushLineWidth 3
tbgl_line -10000, 0, 10000, 0
tbgl_line 0, -10000, 0, 10000
tbgl_popLineWidth
tbgl_popColor
' Some function to draw
tbgl_pushColor 255, 0, 0
tbgl_pushPointSize 3
for i = -10000 to 10000 step 0.1
tbgl_point(i, sin(i/10)*2)
next
tbgl_popPointSize
tbgl_popColor
tbgl_endList
end function
' -- Helper function for scroll bar events
function HandleScrollBarEvents(hDlg as dword, scrollbarId as long, operation as dword) as long
long position
select case operation
case %SB_TOP
position = scrollBar_getRangeLow(hDlg, scrollbarId)
scrollBar_setPos(hDlg, scrollbarId, position)
case %SB_BOTTOM
position = scrollBar_getRangehi(hDlg, scrollbarId)
scrollBar_setPos(hDlg, scrollbarId, position)
case %SB_LINEUP
position = scrollBar_getpos(hDlg, scrollbarId) - 1
scrollBar_setPos(hDlg, scrollbarId, position)
case %SB_LINEDOWN
position = scrollBar_getpos(hDlg, scrollbarId) + 1
scrollBar_setPos(hDlg, scrollbarId, position)
case %SB_PAGEUP
position = scrollBar_getpos(hDlg, scrollbarId) - scrollBar_getPageSize(hDlg, scrollbarId)
scrollBar_setPos(hDlg, scrollbarId, position)
case %SB_PAGEDOWN
position = scrollBar_getpos(hDlg, scrollbarId) + scrollBar_getPageSize(hDlg, scrollbarId)
scrollBar_setPos(hDlg, scrollbarId, position)
case %SB_THUMBTRACK
position = scrollBar_getTrackPos(hDlg, scrollbarId)
scrollBar_setPos(hDlg, scrollbarId, position)
end select
return scrollbar_getpos(hDlg, scrollbarId)
end function
Petr
-
Thanks Petr , as always the example is full of hints, tips and tricks, and all in One example.
i see you have used Lists to capture and build the data list. which is suitable for plotting the data
but i don't understand the TBGL_PushStateProtect and its sister TBGL_PopStateProtect
-
Hi Primo,
PushStateProtect and PopStateProtect are functions to protect piece of graphic code from being affected by specified TBGL state.
By default, when you draw graphics primitives, TBGL uses depth testing. That allows you to draw primitives in any order and they will be sorted correctly.
However.
For edge cases, such as 2D graphics, which overlay one over each other, this can be an issue - depending on implementation and moon phase, artifacts could pop up.
That is why I recommend to disable depth testing in order to be able to paint like painter, one thing after another, in order dependent way.
Here is example to demonstrate the issue in obvious way:
Code:
uses "TBGL"
function tbMain()
double FrameRate
' -- Create and show window
dWord hWnd = tbgl_createWindowEx("Depth testing artifacts - press ESC to quit", 640, 240, 32, %tbgl_WS_WINDOWED | %tbgl_WS_CLOSEBOX)
tbgl_showWindow
' -- Resets status of all keys
tbgl_resetKeyState()
single angle
' -- Main loop
while tbgl_IsWindow(hWnd)
FrameRate = tbgl_getFrameRate
angle += 45/FrameRate
tbgl_clearFrame
tbgl_camera(0, 0, 5, 0, 0, 0)
tbgl_pushMatrix
tbgl_translate -2, 0, 0
tbgl_rotate angle, 0, 1, 0
tbgl_color 255, 255, 0
tbgl_rect(-1, -1, 1, 1)
tbgl_color 255, 0, 0
tbgl_ngon(0, 0, 1, 180)
tbgl_popMatrix
tbgl_pushStateProtect %TBGL_DEPTH
tbgl_pushMatrix
tbgl_translate 2, 0, 0
tbgl_rotate -angle, 0, 1, 0
tbgl_color 255, 255, 0
tbgl_rect(-1, -1, 1, 1)
tbgl_color 255, 0, 0
tbgl_ngon(0, 0, 1, 180)
tbgl_popMatrix
tbgl_popStateProtect
tbgl_drawFrame
' -- ESCAPE key to exit application
if tbgl_getWindowKeyState(hWnd, %VK_ESCAPE) then exit while
wend
tbgl_destroyWindow
end function
Petr