Squirrel

The programming language
Welcome to Squirrel Sign in | Join | Help
in Search

Adapting GLUT binding from luabind examples

Last post 08-12-2008, 5:23 AM by fagiano. 2 replies.
Sort Posts: Previous Next
  •  08-10-2008, 1:12 AM 2682

    Adapting GLUT binding from luabind examples

    Hey all! First post, and I need some help finding my way around this new animal.

    I'm using SqPlus to perform the binding. This is my first foray into the language, and this particular API, so there is probably a lot wrong with it. I will ask about the parts that are unclear to me, and request that you point out what you can, while answering. Both code and script are listed after the questions.

    1. The luabind version worked by passing a script function to a C++ function callback as an argument. This way, GLUT's callbacks could store, and then call that script function from C++ code. Is there a way to implement something similar in sqlplus?
    2. Does sqlplus have a problem with functions prefixed with __stdcall ? This was a problem in luabind, when I was using it.

    Thanks for any help you can provide. I look forward to being active here. ;)

    ----------------- C++ --------------------

    /////////////////////////////////////////
    ///      "read_text.cpp"
    ////////////////////////////////////////
    #ifndef __TEXTFILE_HPP__
    #define __TEXTFILE_HPP__

    #include <cstdlib>
    #include <iostream>
    #include <fstream>

    using namespace std;


    // Read the full resultStrings of a text file in as a string
    wchar_t* readTextFile( const char* fileName )
    {
        ifstream file;
        size_t   fileLength;
        char*    stringBuffer;
        wchar_t* resultString;


        if (fileName != NULL)
        {
            file.open(fileName, ios::binary);

            if (file.is_open())
            {
                // Determine length of file
                file.seekg(0, ios::end);
                fileLength = file.tellg();
                file.seekg(0, ios::beg);

                // If not empty, read all resultStrings
                if (fileLength > 0)
                {
                    // make enough room for '\0' char at end
                    stringBuffer = new char[fileLength + 1];
                    file.read(stringBuffer, fileLength);
                    stringBuffer[fileLength] = '\0';
                   
                    resultString = new wchar_t[fileLength + 1];
                    mbstowcs(resultString, stringBuffer, fileLength + 1);

                    // Free char C-String
                    delete[] stringBuffer;
                    stringBuffer = NULL;
                }

                file.close();
            }
        }

        // return wchar_t c-string
        return resultString;
    }

    #endif // __TEXTFILE_HPP__

    /////////////////////////////////////////
    ///      "main.cpp"
    ////////////////////////////////////////
    #include <cstdio>
    #include <cstdarg>

    #include <sqplus.h>

    #include <GL/glut.h>

    #include "read_text.hpp"

    using namespace SqPlus;


    struct gl_constants {};
    struct glu_constants {};
    struct glut_constants {};


    SquirrelFunction<void> displayFunc;

    void displayFuncCallback()
    {
        displayFunc();
    }

    void setDisplayFunc(SquirrelFunction<void>& fun)
    {
        glutDisplayFunc(&displayFuncCallback);
        displayFunc = fun;
    }


    SquirrelFunction<void> idleFunc;

    void idleFuncCallback()
    {
        idleFunc();
    }

    void setIdlefunc(SquirrelFunction<void>& fun)
    {
        glutIdleFunc(&idleFuncCallback);
        idleFunc = fun;
    }


    SquirrelFunction<void> reshapeFunc;

    void reshapeFuncCallback(int w, int h)
    {
        reshapeFunc(w, h);
    }

    void setReshapeFunc(SquirrelFunction<void>& fun)
    {
        glutReshapeFunc(&reshapeFuncCallback);
        reshapeFunc = fun;
    }


    SquirrelFunction<void> keyboardFunc;

    void keyboardFuncCallback(unsigned char key, int x, int y)
    {
        keyboardFunc(key, x, y);
    }

    void setKeyboardFunc(SquirrelFunction<void>& fun)
    {
        glutKeyboardFunc(&keyboardFuncCallback);
        keyboardFunc = fun;
    }


    SquirrelFunction<void> mouseFunc;

    void mouseFuncCallback(int button, int state, int x, int y)
    {
        mouseFunc(button, state, x, y);
    }

    void setMouseFunc(SquirrelFunction<void>& fun)
    {
        glutMouseFunc(mouseFuncCallback);
        mouseFunc = fun;
    }



    void bindGLUT()
    {
        //RegisterGlobal(&glutInitWindowSize,     _T("glutInitWindowSize"));

         // OpenGL
        SQClassDef<gl_constants>(_T("gl"))
            .enumInt(GL_COLOR_BUFFER_BIT, _T("COLOR_BUFFER_BIT"))
            .enumInt(GL_DEPTH_BUFFER_BIT, _T("DEPTH_BUFFER_BIT"))
            .enumInt(GL_TRIANGLES,        _T("TRIANGLES"))
            .enumInt(GL_MODELVIEW,        _T("MODELVIEW"))
            .enumInt(GL_PROJECTION,       _T("PROJECTION"))

            .staticFunc(&glClear, _T("Clear"))

            .staticFunc(&glBegin, _T("Begin"))
            .staticFunc(&glEnd,   _T("End"))

            .staticFunc(&glVertex3f, _T("Vertex3f"))
            .staticFunc(&glColor3f,  _T("Color3f"))
            .staticFunc(&glColor4f,  _T("Color4f"))

            .staticFunc(&glMatrixMode, _T("MatrixMode"))
            .staticFunc(&glPushMatrix, _T("PushMatrix"))
            .staticFunc(&glPopMatrix,  _T("PopMatrix"))

            .staticFunc(&glLoadIdentity, _T("LoadIdentity"))
            .staticFunc(&glTranslatef,   _T("Translatef"))
            .staticFunc(&glRotatef,      _T("Rotatef"))
            .staticFunc(&glViewport,     _T("glViewport"));

        // GLU
        SQClassDef<glu_constants>(_T("glu"))
            .staticFunc(&gluPerspective, _T("Perspective"));

        // GLUT
        SQClassDef<glut_constants>(_T("glut"))
            .enumInt(GLUT_RGB,           _T("RGB"))
            .enumInt(GLUT_RGBA,          _T("RGBA"))
            .enumInt(GLUT_INDEX,         _T("INDEX"))
            .enumInt(GLUT_SINGLE,        _T("SINGLE"))
            .enumInt(GLUT_DOUBLE,        _T("DOUBLE"))
            .enumInt(GLUT_DEPTH,         _T("DEPTH"))
            .enumInt(GLUT_STENCIL,       _T("STENCIL"))
            .enumInt(GLUT_LEFT_BUTTON,   _T("LEFT_BUTTON"))
            .enumInt(GLUT_MIDDLE_BUTTON, _T("MIDDLE_BUTTON"))
            .enumInt(GLUT_RIGHT_BUTTON,  _T("RIGHT_BUTTON"))
            .enumInt(GLUT_UP,            _T("UP"))
            .enumInt(GLUT_DOWN,          _T("DOWN"))
            .enumInt(GLUT_ELAPSED_TIME,  _T("ELAPSED_TIME"))

            .staticFunc(&glutInitWindowSize,     _T("InitWindowSize"))
            .staticFunc(&glutInitWindowPosition, _T("InitWindowPosition"))
            .staticFunc(&glutInitDisplayMode,    _T("InitDisplayMode"))
           
            .staticFunc(&glutCreateWindow,  _T("CreateWindow"))
            .staticFunc(&glutDestroyWindow, _T("DestroyWindow"))
            .staticFunc(&glutFullScreen,    _T("FullScreen"))

            // PAY special attention HERE!
            // These are the weird ones that require fiddling around up top
            .staticFunc(&setDisplayFunc,  _T("DisplayFunc"))
            .staticFunc(&setKeyboardFunc, _T("KeyboardFunc"))
            .staticFunc(&setReshapeFunc,  _T("ReshapeFunc"))
            .staticFunc(&setIdlefunc,     _T("IdleFunc"))

            .staticFunc(&glutMainLoop,    _T("MainLoop"))
            .staticFunc(&glutSwapBuffers, _T("SwapBuffers"))
            .staticFunc(&glutGet,         _T("Get"))

            .staticFunc(&glutSolidSphere, _T("SolidSphere"))
            .staticFunc(&glutWireSphere,  _T("WireSphere"))
            .staticFunc(&glutWireTeapot,  _T("WireTeapot"))
            .staticFunc(&glutSolidTeapot, _T("SolidTeapot"));
    }

    int main(int argc, char* argv[])
    {
        SquirrelVM::Init();

        bindGLUT();

        glutInit (&argc, argv);


        wchar_t* code = readTextFile("../Data/glut.nut");

        SquirrelObject glutScript = SquirrelVM::CompileBuffer(code);

        if (code != NULL)
        {
            delete code;
            code = NULL;
        }

        try
        {
            SquirrelVM::RunScript(glutScript);
        }
        catch (SquirrelError & e)
        {
            scprintf(_T("Error: %s, %s\n"), e.desc, _T("Squirrel::glutScript"));
        }

        SquirrelVM::Shutdown();

        return 0;
    }

    ----------------- Squirrel script --------------------
    /////////////////////////////////////////
    ///      "glut.nut"
    ////////////////////////////////////////
    quit = false

    function resizeFunc(w, h)
    {
        local ratio = w / h

        print('====== resize')

        gl::MatrixMode(gl::PROJECTION)
        gl::LoadIdentity()

        gl::Viewport(0, 0, w, h)

        glu::Perspective(45, ratio, 1, 1000)

        gl::MatrixMode(gl::MODELVIEW)
        gl::LoadIdentity()
    }

    angle = 0
    angle2 = 0
    previousTime = 0

    function displayFunc()
    {
        if (quit)
            return

        local curTime = glut::Get(glut::ELAPSED_TIME)
        local delta = (curTime - previousTime) / 1000
        previousTime = curTime

        gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT)

        gl::PushMatrix()

        gl::Translatef(0, 0, -5)
        gl::Rotatef(angle, 0, 1, 0)
        gl::Rotatef(angle2, 0, 0, 1)
        gl::Color3f(1,0,0)
    //    glut::WireSphere(0.75, 10, 10)
        glut::SolidTeapot(0.75)
    //    gl::Color3f(1, 1, 1)
    //    glut::WireTeapot(0.75)

        gl::PopMatrix()

        angle = angle + 200 * delta
        angle2 = angle2 + 170 * delta

        frames = frames + 1

        /* FIX
        if (math.mod(frames, 100) == 0)
        {
            local fps = frames * 1000 / (glut::Get(glut::ELAPSED_TIME) - startTime);
            print('fps: ' + fps + ' time: ' + glut::Get(glut::ELAPSED_TIME) + ' frames: ' + frames)
        }
        */

        glut::SwapBuffers()
    }

    function keyboardFunc(key, x, y)
    {
        print('keyboard' + key)
        if (key == 27)
        {
            glut::DestroyWindow(window)
            quit = true
        }
    }

    glut::InitWindowSize(600, 600)
    glut::InitWindowPosition(0, 0)
    glut::InitDisplayMode(glut::RGB | glut::DOUBLE | glut::DEPTH)
    window = glut::CreateWindow("Squirrel, glut-bindings")
    glut::DisplayFunc(displayFunc)
    glut::IdleFunc(displayFunc)
    glut::KeyboardFunc(keyboardFunc)
    glut::ReshapeFunc(resizeFunc)

    resizeFunc(600,600)

    startTime = glut::Get(glut::ELAPSED_TIME)
    frames = 0

    glut::MainLoop()


    -~ Amateur game dev ~-
    Current goal: Find best way to write my math library
  •  08-12-2008, 4:13 AM 2694 in reply to 2682

    Re: Adapting GLUT binding from luabind examples

    Hello,

    > The luabind version worked by passing a script function to a C++ function callback as an
    > argument. This way, GLUT's callbacks could store, and then call that script function from
    > C++ code. Is there a way to implement something similar in sqlplus?

    You're looking at binding a C++ function to an arbitrary script function and use as callback. Given that you'd need some state to select which script function to run, it's a bit difficult (At least if you're using script coroutines. A stack with script function IDs is not strictly reliable when there is possibility of swapping coroutine). If you're callback never yields, it would be safe.

    One can also use an interface class with a callback function.

    > Does sqlplus have a problem with functions prefixed with __stdcall ? This was a problem in
    > luabind, when I was using it.

    SqPlus must be aware of __stdcall, if you don't get it into you're binding declaration, in each step, it won't work right. I added code to handle __cdecl member function calls correctly in SqPlus (search for __cdecl). You'd have to do someting similar for __stdcall. They are never member functions, so it should only touch global function bindings.


    Regards
    // ATS.


  •  08-12-2008, 5:23 AM 2696 in reply to 2694

    Re: Adapting GLUT binding from luabind examples

    glut's callbacks are global, why not just keep a global array of squirrel functions C++ side? one per callback, then having a C++ stub calling the respective squirrel func.

    Alberto

View as RSS news feed in XML
Powered by Community Server, by Telligent Systems