TkLua offers the possibility of creating an OpenGL canvas (both for Unix and Windows platforms). Once created, we can use the OpenGL library to draw image on it. All OpenGL functions are bound to Lua by the OpenGL-Lua library. So, we can create complex image programming solely in Lua. Of course, the OpenGL canvas can also be accessed from C/C++ code.
The general form to create an OpenGL canvas is:
var = tkglcanvas{width = ...,
height = ...,
attrib = ...,
...
}
width and height represent the dimension, in pixel, of the canvas. attrib represents the attributes used to open the window. It follows the same convention of the parameter attribList used by the glXChooseVisual function of the OpenGL library (it is also valid for the Windows plataform). The default is assumed to be:
attrib = {GLX_RGBA,GLX_DOUBLEBUFFER}
After creating the canvas, we must define a reshape method to be called by the TkLua library whenever is necessary to redraw the canvas. This method expects to receive two parameter: the current canvas width and height. There are also two very useful canvas method that can be called by the programmer:
A complete example using an OpenGL canvas is (try it!):
drawarea = tkglcanvas{width=400, height=400}
move = tkbutton{"move";
activebackground=tkcolor(0,255,0),
command="tkidle(spinDisplay)"
}
stop = tkbutton{"stop";
activebackground=tkcolor(255,0,0),
command="tkidle(nil)"
}
quit = tkbutton{"quit";
command="tkexit()"
}
control = tkframe{move,stop,quit,{fill="x",expand=1,side="left"}}
mainwin = tkmain{drawarea,{columnspan=3},control,{expand=1,fill="x",sticky="we"}}
mainwin:show()
mainwin:title("TkLua: using OpenGL canvas")
-- reshape method
function drawarea:reshape (width,height)
self:makecurrent()
glLight(GL_LIGHT0,GL_POSITION,{0,0,50})
glLightModel(GL_LIGHT_MODEL_AMBIENT,{0.4,0.4,0.4,1.0})
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60.0,width/height,-10,10)
gluLookAt(0,10,-25,0,0,0,0,1,0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity ()
-- define material
glMaterial(GL_FRONT_AND_BACK, GL_AMBIENT,{1.0,1.0,0.0,1.0})
glMaterial(GL_FRONT_AND_BACK, GL_SPECULAR,{1.0,1.0,1.0,1.0});
glMaterial(GL_FRONT,GL_SHININESS,{50})
display(self)
end
spin = 0.0 -- rotate angle
function display (canvas)
if not canvas.quadric then
canvas.quadric = gluNewQuadric()
gluQuadricOrientation(canvas.quadric,GLU_OUTSIDE)
end
canvas:makecurrent()
glClear(GL_COLOR_BUFFER_BIT)
glPushMatrix()
glRotate(spin,0.0,0.0,1.0)
-- display cylinder
glRotate(20,1.0,0.0,0.0)
gluCylinder(canvas.quadric,10,5,20,36,36)
glPopMatrix()
canvas:swapbuffers()
end
-- do animation
function spinDisplay ()
display(drawarea)
spin = spin + 2.0
if spin > 360.0 then
spin = spin - 360.0
end
end
There are a few C functions available to access the canvas from C/C++ code. These functions are:
Specify a reshape callback written in C. It must be passed the name of the Lua global variable that holds the canvas and the reshape function.
Given the Lua global variable that holds the canvas, this function returns a handle to that variable.
Given the canvas handle, it makes the corresponding graphical context current.
Given the canvas handle, it exchanges front and back buffers (needed when using double buffers).
Given the canvas handle, it returns the current canvas width (in pixel).
Given the canvas handle, it returns the current canvas height (in pixel).