lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hello,

I did some further experimentations with Freeglut, leaving my threads (which seem to be without issue, anyway).

Here it is:

Freeglut is used, because it allows to use "glutMainLoopEvent".

  The glutMainLoopEvent function processes a single iteration in
  the freeglut event loop.

With this function, you can keep control of your main loop without using rustic way of Glut (idle loop and so on).

So my main loop in the lua script will be something like this :

repeat
   is_quitting = gl:step()
until (is_quitting==1)


In fact, it is.
Before that, i initialize glut, and define my own display function, which will be called when it's time for repainting screen.

The whole Lua script is short:

#!/usr/bin/env lua
gl=require ("libluaglut")

z=1
function dsp()
   gl:rotz(z)
   gl:drawquad()
   z=(z+0.01) % 20
end

gl:init(dsp)

repeat
   is_quitting = gl:step()
until (is_quitting==1)

print ("the end")


But.. gl:step() is only processing glut events (doing one cycle in the glut loop).
For repainting screen, i use another function (in C DLL this time):

I defined it at freeglut's initialisation:
 glutTimerFunc (20, timer_cb, 1);

It calls:
static void timer_cb (int id_timer)
{
  glutPostRedisplay();
  glutTimerFunc (20, timer_cb, id_timer); //need to rearm each time
}

And the freeglut's display function call the "dsp" function which lie inside Lua script. How do we decide it's time to repaint the screen, if "step" function only process glut's events ? The trick is with glutTimerFunc, which sleep 20ms, and then force redisplay, and so on.

It's working in "parallel" with Lua repeat/until loop, and it doesn't seem to raise problems. In "real" program, we could drop the "glutTimerFunc" and do the glutPostRedisplay in the "step" function. But i've used the "glutTimerFunc" here for showing that it can run without disturbing Lua, which live his own life.

Here is the full C source:

/* gcc -o libluaglut.{so,c} -shared -fvisibility=hidden -fPIC -Wall -lGL -lGLU -lglut
   $$DATE$$ : mar. 19 avril 2011 (01:05:04)
*/

#include <lua.h>
#include <lauxlib.h>
#include <GL/freeglut.h>
#include <unistd.h>

int is_quitting = 0;

static int lua_drawquad (lua_State *L)
{
  (void)L;
  glBegin(GL_QUADS);
  glVertex3f(-.5,-.5,-5);
  glVertex3f(.5,-.5,-5);
  glVertex3f(.5,.5,-5);
  glVertex3f(-.5,.5,-5);
  glEnd();
  return 0;
}


static int lua_rotz (lua_State *L)
{
  int angle = lua_tointeger (L, -1);
  glRotatef(angle, 0.0, 0.0, 1.0);
  return 0;
}


static int display_cb (lua_State *L_init)
{
  static lua_State *L = 0;
  static int index_fx_disp = LUA_REFNIL;

  if (L_init) {
    L = L_init;
    index_fx_disp = luaL_ref (L, LUA_REGISTRYINDEX);
    if (index_fx_disp == LUA_REFNIL) {
      fprintf(stderr,"luaL_ref : erreur\n");
    }
  } else { // called from glut if L_init == 0
    lua_rawgeti (L, LUA_REGISTRYINDEX, index_fx_disp);
    lua_pcall(L, 0,0,0);
  }

  return 0;
}


static void display()
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glMatrixMode(GL_MODELVIEW);
  display_cb(0);
  glutSwapBuffers();
}



static void reshape(int w, int h)
{
  glViewport(0,0,w,h);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective (60., w/ (float) h, 1., 100. );
}



static void keyboard(unsigned char key, int x, int y)
{
  (void)x; (void) y;

  if (key == 27 || key == 'q') {
    is_quitting = 1;
  }

}

static void timer_cb (int id_timer)
{
  glutPostRedisplay();
  glutTimerFunc (20, timer_cb, id_timer);
}

static int lua_step (lua_State *L)
{
  glutMainLoopEvent();
  usleep(1);
  lua_pushinteger (L, is_quitting);
  return 1;
}


int lua_initglut (lua_State *L)
{
  int argc=0; char *argv[0];
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutCreateWindow("Lua and Freeglut");
  display_cb(L);
  glutDisplayFunc(display);
  glutKeyboardFunc(keyboard);
  glutReshapeFunc(reshape);
  glutTimerFunc (20, timer_cb, 1);
  return 0;
}

static const struct luaL_Reg luaglut_fx [] = {
    { "init",lua_initglut},
    { "drawquad", lua_drawquad },
    { "rotz", lua_rotz },
    { "step", lua_step },
    {NULL,NULL} //dernier element obligatoire
};

#ifdef __linux
__attribute__((visibility("default"))) int luaopen_libluaglut(lua_State *L)
#else
  __declspec(dllexport) int luaopen_libluaglut(lua_State *L)
#endif
  {
    luaL_register (L, "luaglut", luaglut_fx);
    return 1;
  }