Prokop Hapala
Prokop Hapala

Reputation: 2444

interace between C++ and Lua function with 3D vector arguments

I have C++ function (which runs some physical simulation inside my game engine) which looks like this:

void doSomePhysics( int nIters, Vec3d pos, Vec3d vel ){ /*... don't care ...*/ }

I want call this function from a lua script likes this:

doSomePhysics( 100, {1.0,-2.0,3.0}, {-8.0,7.0,-6.0} ) 

I'm trying to figure out how to make lua interface to this function.

I would like to do several general helper functions for passing 2D,3D and 4D vectors and matrices since I will heavily use them.

Here is sketch what I'm currently trying to do (But I know it is not correct):

void lua_getVec3(lua_State *L, Vec3d& vec ){
    // universal helper function to get Vec3 function argument from Lua to C++ function
    luaL_checktype(L, 1, LUA_TTABLE);
    lua_settop(L, 1);
    int a_size = lua_rawlen(L, 1);
    lua_rawgeti(L, 1, 1); vec.x = lua_tonumber(L, -1);
    lua_rawgeti(L, 2, 2); vec.y = lua_tonumber(L, -2);
    lua_rawgeti(L, 3, 3); vec.z = lua_tonumber(L, -3);
    lua_pop(L, 3);
}

int l_doSomePhysics(lua_State* L){
    // lua interface for doSomePhysics
    Vec3d pos,vel;
    int n = lua_tointeger(L, 1);
    lua_getVec3(L, pos );
    lua_getVec3(L, vel );
    doSomePhysics(n,pos,vel);
    lua_pushnumber(state, 123);
    return 1;
} 

I read several short tutorials 1 2 3 but it seems horribly complicated, confusing and error-prone ... I'm completely lost in stack indexes (what is my current position in the stack?, what is correct relative index? etc.). I'm reluctant to believe the most famous game scripting language needs sooooo much boiler-plate code and so much pain for interfacing every little function.


EDIT: With help of Vlad I was able to do it for 3D vector and matrix

void lua_getVec3(lua_State *L, int idx, Vec3d& vec){
    // universal helper function to get Vec3 function argument from Lua to C++ function
    luaL_checktype(L, idx, LUA_TTABLE);
    lua_rawgeti(L, idx, 1); vec.x = lua_tonumber(L, -1); lua_pop(L, 1);
    lua_rawgeti(L, idx, 2); vec.y = lua_tonumber(L, -1); lua_pop(L, 1);
    lua_rawgeti(L, idx, 3); vec.z = lua_tonumber(L, -1); lua_pop(L, 1);
}

void lua_getMat3(lua_State *L, int idx, Mat3d& mat){
    // universal helper function to get Mat3 function argument from Lua to C++ function
    luaL_checktype(L, idx, LUA_TTABLE);
    lua_pushinteger(L, 1); lua_gettable(L, idx); lua_getVec3(L, -1, mat.a ); lua_pop(L, 1);
    lua_pushinteger(L, 2); lua_gettable(L, idx); lua_getVec3(L, -1, mat.b ); lua_pop(L, 1);
    lua_pushinteger(L, 3); lua_gettable(L, idx); lua_getVec3(L, -1, mat.c ); lua_pop(L, 1);
}

extern "C"
int l_doSomePhysics2(lua_State* L){
    // lua interface for doSomePhysics
    Vec3d pos;
    Mat3d mat;
    int n = lua_tointeger(L, 1);
    lua_getVec3(L, 2, pos );
    lua_getMat3(L, 3, mat );
    doSomePhysics2(n,pos,mat);
    //lua_pushnumber(L, 123);
    return 3;
}

works for this lua function :

mat = {{1.1,-0.1,0.1},{-0.2,2.2,0.2},{-0.3,0.3,3.3}}
doSomePhysics2( 100, {-7.7,8.8,9.9}, mat )

Upvotes: 1

Views: 649

Answers (1)

Vlad
Vlad

Reputation: 5857

Your void lua_getVec3(lua_State *L, Vec3d& vec) is missing vital info - location of argument table on a Lua stack. Rewrite it to something like:

void lua_getVec3(lua_State *L, int idx, Vec3d& vec){
    // universal helper function to get Vec3 function argument from Lua to C++ function
    luaL_checktype(L, idx, LUA_TTABLE);
    lua_rawgeti(L, idx, 1); vec.x = lua_tonumber(L, -1);
    lua_rawgeti(L, idx, 2); vec.y = lua_tonumber(L, -1);
    lua_rawgeti(L, idx, 3); vec.z = lua_tonumber(L, -1);
    lua_pop(L, 3);
}

And call it like:

int l_doSomePhysics(lua_State* L){
    // lua interface for doSomePhysics
    Vec3d pos,vel;
    int n = lua_tointeger(L, 1);
    lua_getVec3(L, 2, pos );
    lua_getVec3(L, 3, vel);
    doSomePhysics(n,pos,vel);
    lua_pushnumber(state, 123);
    return 1;
} 

Upvotes: 1

Related Questions