You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
325 lines
8.4 KiB
C
325 lines
8.4 KiB
C
/* The MIT License (MIT)
|
|
*
|
|
* Copyright (c) 2021 Stefano Trettel
|
|
*
|
|
* Software repository: MoonCCD, https://github.com/stetre/moonccd
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
* copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*/
|
|
|
|
#include "internal.h"
|
|
|
|
#define GLMATH_COMPAT (tovec3 != LUA_NOREF)
|
|
/* References to the MoonGLMATH functions used to convert pushed values to glmath objects. */
|
|
static int tovec3 = LUA_NOREF;
|
|
static int toquat = LUA_NOREF;
|
|
|
|
int isglmathcompat(void)
|
|
{
|
|
return GLMATH_COMPAT;
|
|
}
|
|
|
|
int glmathcompat(lua_State *L, int on)
|
|
{
|
|
if (on)
|
|
{
|
|
if (GLMATH_COMPAT)
|
|
return 0; /* already enabled */
|
|
if (luaL_dostring(L, "return require('moonglmath').tovec3") != 0)
|
|
lua_error(L);
|
|
tovec3 = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
if (luaL_dostring(L, "return require('moonglmath').toquat") != 0)
|
|
lua_error(L);
|
|
toquat = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
}
|
|
else
|
|
{
|
|
if (!GLMATH_COMPAT)
|
|
return 0; /* already disabled */
|
|
luaL_unref(L, LUA_REGISTRYINDEX, tovec3);
|
|
tovec3 = LUA_NOREF;
|
|
luaL_unref(L, LUA_REGISTRYINDEX, toquat);
|
|
toquat = LUA_NOREF;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* vec3_t ----------------------------------------------------------*/
|
|
|
|
int testvec3(lua_State *L, int arg, vec3_t *dst)
|
|
{
|
|
int isnum;
|
|
int t = lua_type(L, arg);
|
|
switch (t)
|
|
{
|
|
case LUA_TNONE:
|
|
case LUA_TNIL:
|
|
return ERR_NOTPRESENT;
|
|
case LUA_TTABLE:
|
|
break;
|
|
default:
|
|
return ERR_TABLE;
|
|
}
|
|
#define POP \
|
|
if (!isnum) \
|
|
{ \
|
|
lua_pop(L, 1); \
|
|
return ERR_VALUE; \
|
|
} \
|
|
lua_pop(L, 1);
|
|
lua_rawgeti(L, arg, 1);
|
|
dst->v[0] = lua_tonumberx(L, -1, &isnum);
|
|
POP
|
|
lua_rawgeti(L, arg, 2);
|
|
dst->v[1] = lua_tonumberx(L, -1, &isnum);
|
|
POP
|
|
lua_rawgeti(L, arg, 3);
|
|
dst->v[2] = lua_tonumberx(L, -1, &isnum);
|
|
POP
|
|
#undef POP
|
|
return 0;
|
|
}
|
|
|
|
int optvec3(lua_State *L, int arg, vec3_t *dst)
|
|
{
|
|
int ec = testvec3(L, arg, dst);
|
|
if (ec < 0)
|
|
return argerror(L, arg, ec);
|
|
return ec;
|
|
}
|
|
|
|
int checkvec3(lua_State *L, int arg, vec3_t *dst)
|
|
{
|
|
int ec = testvec3(L, arg, dst);
|
|
if (ec)
|
|
return argerror(L, arg, ec);
|
|
return ec;
|
|
}
|
|
|
|
void pushvec3(lua_State *L, const vec3_t *val)
|
|
{
|
|
if (GLMATH_COMPAT)
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, tovec3);
|
|
lua_newtable(L);
|
|
lua_pushnumber(L, val->v[0]);
|
|
lua_rawseti(L, -2, 1);
|
|
lua_pushnumber(L, val->v[1]);
|
|
lua_rawseti(L, -2, 2);
|
|
lua_pushnumber(L, val->v[2]);
|
|
lua_rawseti(L, -2, 3);
|
|
if (GLMATH_COMPAT && lua_pcall(L, 1, 1, 0) != LUA_OK)
|
|
{
|
|
unexpected(L);
|
|
return;
|
|
}
|
|
}
|
|
|
|
vec3_t *checkvec3list(lua_State *L, int arg, int *countp, int *err)
|
|
/* Check if the value at arg is a table of vecs and returns the corresponding
|
|
* array of vec3_t, stroing the size in *countp. The array is Malloc()'d and the
|
|
* caller is in charge of Free()ing it.
|
|
* If err=NULL, raises an error on failure, otherwise returns NULL and stores
|
|
* the ERR_XXX code in *err.
|
|
*/
|
|
{
|
|
int count, i;
|
|
vec3_t *dst = NULL;
|
|
*countp = 0;
|
|
#define ERR(ec) \
|
|
do \
|
|
{ \
|
|
if (err) \
|
|
*err = (ec); \
|
|
else \
|
|
argerror(L, arg, (ec)); \
|
|
return NULL; \
|
|
} while (0)
|
|
if (lua_isnoneornil(L, arg))
|
|
ERR(ERR_NOTPRESENT);
|
|
if (lua_type(L, arg) != LUA_TTABLE)
|
|
ERR(ERR_TABLE);
|
|
|
|
count = luaL_len(L, arg);
|
|
if (count == 0)
|
|
ERR(ERR_EMPTY);
|
|
dst = MallocNoErr(L, count * sizeof(vec3_t));
|
|
if (!dst)
|
|
ERR(ERR_MEMORY);
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
lua_rawgeti(L, arg, i + 1);
|
|
if (testvec3(L, -1, &dst[i]) != 0)
|
|
{
|
|
Free(L, dst);
|
|
ERR(ERR_TYPE);
|
|
}
|
|
lua_pop(L, 1);
|
|
}
|
|
#undef ERR
|
|
*countp = count;
|
|
if (err)
|
|
*err = 0;
|
|
return dst;
|
|
}
|
|
|
|
void pushvec3list(lua_State *L, const vec3_t *vecs, int count)
|
|
{
|
|
int i;
|
|
lua_newtable(L);
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
pushvec3(L, &vecs[i]);
|
|
lua_rawseti(L, -2, i + 1);
|
|
}
|
|
}
|
|
|
|
/* quat_t ----------------------------------------------------------*/
|
|
|
|
int testquat(lua_State *L, int arg, quat_t *dst)
|
|
{
|
|
int isnum;
|
|
int t = lua_type(L, arg);
|
|
switch (t)
|
|
{
|
|
case LUA_TNONE:
|
|
case LUA_TNIL:
|
|
return ERR_NOTPRESENT;
|
|
case LUA_TTABLE:
|
|
break;
|
|
default:
|
|
return ERR_TABLE;
|
|
}
|
|
#define POP \
|
|
if (!isnum) \
|
|
{ \
|
|
lua_pop(L, 1); \
|
|
return ERR_VALUE; \
|
|
} \
|
|
lua_pop(L, 1);
|
|
lua_rawgeti(L, arg, 1);
|
|
dst->q[3] = lua_tonumberx(L, -1, &isnum);
|
|
POP // w
|
|
lua_rawgeti(L, arg, 2);
|
|
dst->q[0] = lua_tonumberx(L, -1, &isnum);
|
|
POP // x
|
|
lua_rawgeti(L, arg, 3);
|
|
dst->q[1] = lua_tonumberx(L, -1, &isnum);
|
|
POP // y
|
|
lua_rawgeti(L, arg, 4);
|
|
dst->q[2] = lua_tonumberx(L, -1, &isnum);
|
|
POP // z
|
|
#undef POP
|
|
return 0;
|
|
}
|
|
|
|
int optquat(lua_State *L, int arg, quat_t *dst)
|
|
{
|
|
int ec = testquat(L, arg, dst);
|
|
if (ec < 0)
|
|
return argerror(L, arg, ec);
|
|
return ec;
|
|
}
|
|
|
|
int checkquat(lua_State *L, int arg, quat_t *dst)
|
|
{
|
|
int ec = testquat(L, arg, dst);
|
|
if (ec)
|
|
return argerror(L, arg, ec);
|
|
return ec;
|
|
}
|
|
|
|
void pushquat(lua_State *L, const quat_t *val)
|
|
{
|
|
if (GLMATH_COMPAT)
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, toquat);
|
|
lua_newtable(L);
|
|
lua_pushnumber(L, val->q[3]);
|
|
lua_rawseti(L, -2, 1); // w
|
|
lua_pushnumber(L, val->q[0]);
|
|
lua_rawseti(L, -2, 2); // x
|
|
lua_pushnumber(L, val->q[1]);
|
|
lua_rawseti(L, -2, 3); // y
|
|
lua_pushnumber(L, val->q[2]);
|
|
lua_rawseti(L, -2, 4); // z
|
|
if (GLMATH_COMPAT && lua_pcall(L, 1, 1, 0) != LUA_OK)
|
|
{
|
|
unexpected(L);
|
|
return;
|
|
}
|
|
}
|
|
|
|
quat_t *checkquatlist(lua_State *L, int arg, int *countp, int *err)
|
|
/* Check if the value at arg is a table of vecs and returns the corresponding
|
|
* array of quat_t, stroing the size in *countp. The array is Malloc()'d and the
|
|
* caller is in charge of Free()ing it.
|
|
* If err=NULL, raises an error on failure, otherwise returns NULL and stores
|
|
* the ERR_XXX code in *err.
|
|
*/
|
|
{
|
|
int count, i;
|
|
quat_t *dst = NULL;
|
|
*countp = 0;
|
|
#define ERR(ec) \
|
|
do \
|
|
{ \
|
|
if (err) \
|
|
*err = (ec); \
|
|
else \
|
|
argerror(L, arg, (ec)); \
|
|
return NULL; \
|
|
} while (0)
|
|
if (lua_isnoneornil(L, arg))
|
|
ERR(ERR_NOTPRESENT);
|
|
if (lua_type(L, arg) != LUA_TTABLE)
|
|
ERR(ERR_TABLE);
|
|
|
|
count = luaL_len(L, arg);
|
|
if (count == 0)
|
|
ERR(ERR_EMPTY);
|
|
dst = MallocNoErr(L, count * sizeof(quat_t));
|
|
if (!dst)
|
|
ERR(ERR_MEMORY);
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
lua_rawgeti(L, arg, i + 1);
|
|
if (testquat(L, -1, &dst[i]) != 0)
|
|
{
|
|
Free(L, dst);
|
|
ERR(ERR_TYPE);
|
|
}
|
|
lua_pop(L, 1);
|
|
}
|
|
#undef ERR
|
|
*countp = count;
|
|
if (err)
|
|
*err = 0;
|
|
return dst;
|
|
}
|
|
|
|
void pushquatlist(lua_State *L, const quat_t *vecs, int count)
|
|
{
|
|
int i;
|
|
lua_newtable(L);
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
pushquat(L, &vecs[i]);
|
|
lua_rawseti(L, -2, i + 1);
|
|
}
|
|
}
|