How to send arrays/ matrices to Lua?

Started by
10 comments, last by Wyrframe 15 years, 4 months ago
Well I need to push a matrix on to the stack in lua and I can't seem to find a command to do that. I tried pushing each value in the array on to the stack like this:

int lua_Translate(lua_State *L)
{
	D3DXMATRIX Matrix;
	D3DXMatrixTranslation( &Matrix, (float)lua_tonumber(L, 1), (float)lua_tonumber(L, 2), (float)lua_tonumber(L, 3) );
	lua_pushnumber(L, (float)Matrix._11);
	lua_pushnumber(L, (float)Matrix._12);
	lua_pushnumber(L, (float)Matrix._13);
	lua_pushnumber(L, (float)Matrix._14);
	lua_pushnumber(L, (float)Matrix._21);
	lua_pushnumber(L, (float)Matrix._22);
	lua_pushnumber(L, (float)Matrix._23);
	lua_pushnumber(L, (float)Matrix._24);
	lua_pushnumber(L, (float)Matrix._31);
	lua_pushnumber(L, (float)Matrix._32);
	lua_pushnumber(L, (float)Matrix._33);
	lua_pushnumber(L, (float)Matrix._34);
	lua_pushnumber(L, (float)Matrix._41);
	lua_pushnumber(L, (float)Matrix._42);
	lua_pushnumber(L, (float)Matrix._43);
	lua_pushnumber(L, (float)Matrix._44);
	return 1;
}

I thought I could then read it with something like this:

D3DXMATRIX Matrix;
Matrix._11 = (float)lua_tonumber(L,1);
Matrix._12 = (float)lua_tonumber(L,2);
Matrix._13 = (float)lua_tonumber(L,3);
Matrix._14 = (float)lua_tonumber(L,4);
Matrix._21 = (float)lua_tonumber(L,1);
Matrix._22 = (float)lua_tonumber(L,2);
Matrix._23 = (float)lua_tonumber(L,3);
Matrix._24 = (float)lua_tonumber(L,4);
Matrix._31 = (float)lua_tonumber(L,1);
Matrix._32 = (float)lua_tonumber(L,2);
Matrix._33 = (float)lua_tonumber(L,3);
Matrix._34 = (float)lua_tonumber(L,4);
Matrix._41 = (float)lua_tonumber(L,1);
Matrix._42 = (float)lua_tonumber(L,2);
Matrix._43 = (float)lua_tonumber(L,3);
Matrix._44 = (float)lua_tonumber(L,4);

But apparently you can only push one value at a time, so how do I do that? And yes I know about pushing the pointer but if I do that when I multiply the matrix it will still keep the two matrices I multiplied in memory so after I do that a few times I think I would get an overflow.
Remember Codeka is my alternate account, just remember that!
Advertisement
User defined types. Follow the -> links.

Basically, you push the pointer to matrix structure.
Quote:Original post by Antheus
User defined types. Follow the -> links.

Basically, you push the pointer to matrix structure.


I'm confused, I understand kinda what it's talking about but I don't understand how to push user data. I see there is a command to read it:

D3DXMATRIX Matrix = (D3DXMATRIX)lua_touserdata(L, 1);

But I fail to understand how to push it, I would think there would be a command that would work something like this:

void lua_pushuserdata (lua_State *L, void *userdata, int size);

I don't understand how lua_newuserdata works, I've read about it but for some reason I can't understand how I would use that to push my matrix?
Remember Codeka is my alternate account, just remember that!
One of following chapters mentions light user data.

User defined types are covered well in one of GPG books, the tutorial just mentions that light user data should be used with meta tables. There's probably other articles on google.

Custom types are basically objects, so they need to be described in a way for Lua to manipulate them. You don't really want to push D3D types directly, but pass them to Lua via some managed pointer.

There's also several libraries which provide slightly more convenient access to Lua.
Quote:Original post by Antheus
One of following chapters mentions light user data.

User defined types are covered well in one of GPG books, the tutorial just mentions that light user data should be used with meta tables. There's probably other articles on google.

Custom types are basically objects, so they need to be described in a way for Lua to manipulate them. You don't really want to push D3D types directly, but pass them to Lua via some managed pointer.

There's also several libraries which provide slightly more convenient access to Lua.


I'm racking my brains trying to understand, is there anyway you can show me a code example of what I need to do?

[Edited by - CodaKiller on December 7, 2008 9:48:03 PM]
Remember Codeka is my alternate account, just remember that!
Have u tried using some of the automated binding libraries for Lua ? Like toLua, Mluabind or Luabind, etc.. They pretty much automate the process of binding your objects to Lua. There might be more overhead than implementing raw Lua functions and pushing/poping userdata yourself, but you'll never know until you profile it.

-ddn
Quote:Original post by ddn3
Have u tried using some of the automated binding libraries for Lua ? Like toLua, Mluabind or Luabind, etc.. They pretty much automate the process of binding your objects to Lua. There might be more overhead than implementing raw Lua functions and pushing/poping userdata yourself, but you'll never know until you profile it.

-ddn


Well my engine is over 5000 lines of code and it has so many raw lua functions that it would take a really long time to change them all.
Remember Codeka is my alternate account, just remember that!
This is pretty much one of the last things I needed to do before it was done...
Remember Codeka is my alternate account, just remember that!
Ok I'm tired of this, I'll send $10 through Paypal to the first person who can give me a function that can push a D3DXMATRIX and then show me how to read it back out like lua_tonumber but gets the matrix instead of a number.
Remember Codeka is my alternate account, just remember that!
int method_index2_set(lua_State *L) {    D3DXMATRIX *m;    float* cells;    float v;    int i, j;    lua_getfield(L, 1, "i");    i = (int)lua_tonumber(L, -1) - 1;    j = (int)lua_tonumber(L, 2) - 1;    v = lua_tonumber(L, 3);        if ( i >= 0 && j >= 0 && i < 4 && j < 4 )    {        lua_getfield(L, 1, "matrix");        m = luaL_checkudata(L, -1, "D3DXMATRIXForLua");        cells = (float*)m;        cells[j*4 + i] = v;    }    return 0;}int method_index2_get(lua_State *L) {    D3DXMATRIX *m;    int i, j;    lua_getfield(L, 1, "i");    i = (int)lua_tonumber(L, -1) - 1;    j = (int)lua_tonumber(L, 2) - 1;    if ( i < 0 || j < 0 || i > 3 || j > 3 )        return 0;        lua_getfield(L, 1, "matrix");    m = luaL_checkudata(L, -1, "D3DXMATRIXForLua");    float* cells = (float*)m;    lua_pushnumber(cells[j*4 + i]);    return 1;}int method_index1(lua_State *L) {    lua_createtable(L, 0, 2);    lua_pushvalue(L, 2);    lua_setfield(L, -2, "i");    lua_pushvalue(L, 1);    lua_setfield(L, -2, "matrix");    if ( luaL_newmetatable(L, "D3DXMATRIXIndexedOnce") ) {        lua_pushcfunction(L, method_index2_get);        lua_setfield(L, -2, "__index");        lua_pushcfunction(L, method_index2_set);        lua_setfield(L, -2, "__newindex");    }    lua_setmetatable(L, -2);    return 1;}void luaMakeMatrix(lua_State *L, D3DXMATRIX** handle){    *handle = (D3DXMATRIX*)lua_newuserdata(L, sizeof(D3DXMATRIX));    if ( luaL_newmetatable(L, "D3DXMATRIXForLua") ) {        // Add any other methods you want; I've made indexing for you.        lua_pushcfunction(L, method_index1);        lua_setfield(L, -2, "__index");    }    lua_setmetatable(L, -2);}void luaGetMatrix(lua_State *L, D3DXMATRIX** handle, int pos){    // Throws a Lua error if given stack position is not a D3DXMATRIX.    *handle = luaL_checkudata(L, pos, "D3DXMATRIXForLua");}


C usage:
// Create a new matrix, pushing it on the stack and filling a pointer to// the newly-allocated and garbage-collected-for-you-by-lua matrix.D3DXMATRIX* matrix;luaMakeMatrix(L, &matrix);matrix->_11 = matrix->_12 = matrix->_13 = matrix->_14 = 0;// Fill a pointer with the matrix on the lua stack; in this case,// where the matrix is passed as argument 2 to this C implementation// of a lua-protocol function.void befoozle(lua_State *L){  D3DXMATRIX* m;  luaGetMatrix(L, &matrix, 2);  m->_13 = -m->_13;  lua_pushnumber(L, m->_33);  return 1;}


Lua usage:
function frobnicate(matrix)  matrix[3][1] = 8  return matrix[2][0]end


Untested, and I've assumed, possibly incorrectly, that the float[16] equivalent to a D3DXMATRIX goes [_11, _21, _31, _41, _12, _22, _32... _43, _44]. Just swap i and j in the setter and getter to fix that.

Paypal transfer not required.
RIP GameDev.net: launched 2 unusably-broken forum engines in as many years, and now has ceased operating as a forum at all, happy to remain naught but an advertising platform with an attached social media presense, headed by a staff who by their own admission have no idea what their userbase wants or expects.Here's to the good times; shame they exist in the past.

This topic is closed to new replies.

Advertisement