This commit is contained in:
Bjorn 2024-03-10 05:38:20 -06:00 committed by GitHub
commit 9237514a1e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 294 additions and 571 deletions

View File

@ -177,7 +177,6 @@ function lovr.run()
lovr.graphics.present()
end
if lovr.headset then lovr.headset.submit() end
if lovr.math then lovr.math.drain() end
end
end
@ -273,8 +272,6 @@ function lovr.errhand(message)
lovr.graphics.present()
end
end
lovr.math.drain()
end
end

View File

@ -494,13 +494,13 @@ void luax_optcolor(lua_State* L, int index, float color[4]) {
break;
case LUA_TUSERDATA:
case LUA_TLIGHTUSERDATA: {
VectorType type;
float* v = luax_tovector(L, index, &type);
if (type == V_VEC3) {
int vectorType;
float* v = luax_tovector(L, index, &vectorType);
if (vectorType == V_VEC3) {
memcpy(color, v, 3 * sizeof(float));
color[3] = 1.f;
break;
} else if (type == V_VEC4) {
} else if (vectorType == V_VEC4) {
memcpy(color, v, 4 * sizeof(float));
break;
}

View File

@ -177,10 +177,19 @@ struct ColoredString* luax_checkcoloredstrings(lua_State* L, int index, uint32_t
#endif
#ifndef LOVR_DISABLE_MATH
#include "math/math.h" // TODO
float* luax_tovector(lua_State* L, int index, VectorType* type);
float* luax_checkvector(lua_State* L, int index, VectorType type, const char* expected);
float* luax_newtempvector(lua_State* L, VectorType type);
enum {
V_NONE,
V_VEC2,
V_VEC3,
V_VEC4,
V_QUAT,
V_MAT4,
MAX_VECTOR_TYPES
};
float* luax_tovector(lua_State* L, int index, int* type);
float* luax_checkvector(lua_State* L, int index, int type, const char* expected);
float* luax_newvector(lua_State* L, int type);
int luax_readvec2(lua_State* L, int index, float* v, const char* expected);
int luax_readvec3(lua_State* L, int index, float* v, const char* expected);
int luax_readvec4(lua_State* L, int index, float* v, const char* expected);

View File

@ -87,10 +87,10 @@ void luax_checkvariant(lua_State* L, int index, Variant* variant) {
/* fallthrough */
case LUA_TLIGHTUSERDATA: {
VectorType type;
float* v = luax_tovector(L, index, &type);
int vtype;
float* v = luax_tovector(L, index, &vtype);
if (v) {
if (type == V_MAT4) {
if (vtype == V_MAT4) {
variant->type = TYPE_MATRIX;
variant->value.matrix.data = malloc(16 * sizeof(float));
lovrAssert(variant->value.matrix.data, "Out of memory");
@ -98,8 +98,9 @@ void luax_checkvariant(lua_State* L, int index, Variant* variant) {
break;
} else {
variant->type = TYPE_VECTOR;
variant->value.vector.type = type;
memcpy(variant->value.vector.data, v, (type == V_VEC2 ? 2 : 4) * sizeof(float));
variant->value.vector.type = vtype;
size_t components = vtype == V_VEC2 ? 2 : (vtype == V_VEC3 ? 3 : 4);
memcpy(variant->value.vector.data, v, components * sizeof(float));
break;
}
} else if (lua_type(L, index) == LUA_TLIGHTUSERDATA) {
@ -125,8 +126,8 @@ int luax_pushvariant(lua_State* L, Variant* variant) {
case TYPE_MINISTRING: lua_pushlstring(L, variant->value.ministring.data, variant->value.ministring.length); return 1;
case TYPE_POINTER: lua_pushlightuserdata(L, variant->value.pointer); return 1;
case TYPE_OBJECT: _luax_pushtype(L, variant->value.object.type, hash64(variant->value.object.type, strlen(variant->value.object.type)), variant->value.object.pointer); return 1;
case TYPE_VECTOR: memcpy(luax_newtempvector(L, variant->value.vector.type), variant->value.vector.data, (variant->value.vector.type == V_VEC2 ? 2 : 4) * sizeof(float)); return 1;
case TYPE_MATRIX: memcpy(luax_newtempvector(L, V_MAT4), variant->value.vector.data, 16 * sizeof(float)); return 1;
case TYPE_VECTOR: memcpy(luax_newvector(L, variant->value.vector.type), variant->value.vector.data, (variant->value.vector.type == V_VEC2 ? 2 : 4) * sizeof(float)); return 1;
case TYPE_MATRIX: memcpy(luax_newvector(L, V_MAT4), variant->value.vector.data, 16 * sizeof(float)); return 1;
default: return 0;
}
}

View File

@ -111,7 +111,7 @@ void luax_checkfieldv(lua_State* L, int index, int type, void* data) {
DataPointer p = { .raw = data };
uint32_t n = typeComponents[type];
lovrCheck(n > 1, "Expected number for scalar data type, got vector");
VectorType vectorType;
int vectorType;
float* v = luax_tovector(L, index, &vectorType);
lovrCheck(v, "Expected vector, got non-vector userdata");
if (n >= TYPE_MAT2 && n <= TYPE_MAT4) {

View File

@ -198,10 +198,10 @@ static int l_lovrModelSetNodeTransform(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
uint32_t node = luax_checknodeindex(L, 2, lovrModelGetInfo(model)->data);
int index = 3;
VectorType type;
int vtype;
float position[3], scale[3], rotation[4];
float* m = luax_tovector(L, index, &type);
if (m && type == V_MAT4) {
float* m = luax_tovector(L, index, &vtype);
if (m && vtype == V_MAT4) {
mat4_getPosition(m, position);
mat4_getScale(m, scale);
mat4_getOrientation(m, rotation);

View File

@ -258,9 +258,9 @@ static int l_lovrPassGetViewPose(lua_State* L) {
static int l_lovrPassSetViewPose(lua_State* L) {
Pass* pass = luax_checktype(L, 1, Pass);
uint32_t view = luaL_checkinteger(L, 2) - 1;
VectorType type;
float* p = luax_tovector(L, 3, &type);
if (p && type == V_MAT4) {
int vtype;
float* p = luax_tovector(L, 3, &vtype);
if (p && vtype == V_MAT4) {
float matrix[16];
mat4_init(matrix, p);
bool inverted = lua_toboolean(L, 4);
@ -870,7 +870,7 @@ static int l_lovrPassSphere(lua_State* L) {
static bool luax_checkendpoints(lua_State* L, int index, float transform[16], bool center) {
float *v, *u;
VectorType t1, t2;
int t1, t2;
if ((v = luax_tovector(L, index + 0, &t1)) == NULL || t1 != V_VEC3) return false;
if ((u = luax_tovector(L, index + 1, &t2)) == NULL || t2 != V_VEC3) return false;
float radius = luax_optfloat(L, index + 2, 1.);

View File

@ -31,36 +31,38 @@ extern const luaL_Reg lovrVec4[];
extern const luaL_Reg lovrQuat[];
extern const luaL_Reg lovrMat4[];
static LOVR_THREAD_LOCAL Pool* pool;
#define VECTOR_STACK_MAX 16
static struct { const char* name; lua_CFunction constructor, indexer; const luaL_Reg* api; int metaref; } lovrVectorInfo[] = {
[V_VEC2] = { "vec2", l_lovrMathVec2, l_lovrVec2__metaindex, lovrVec2, LUA_REFNIL },
[V_VEC3] = { "vec3", l_lovrMathVec3, l_lovrVec3__metaindex, lovrVec3, LUA_REFNIL },
[V_VEC4] = { "vec4", l_lovrMathVec4, l_lovrVec4__metaindex, lovrVec4, LUA_REFNIL },
[V_QUAT] = { "quat", l_lovrMathQuat, l_lovrQuat__metaindex, lovrQuat, LUA_REFNIL },
[V_MAT4] = { "mat4", l_lovrMathMat4, l_lovrMat4__metaindex, lovrMat4, LUA_REFNIL }
typedef struct {
size_t components;
const char* name;
lua_CFunction metacall;
lua_CFunction metaindex;
const luaL_Reg* api;
int metatableRef;
int poolRef;
int poolCursor;
int stackPointers[VECTOR_STACK_MAX];
} VectorInfo;
static uint32_t stackIndex;
static VectorInfo lovrVectorInfo[] = {
[V_VEC2] = { 2, "vec2", l_lovrMathVec2, l_lovrVec2__metaindex, lovrVec2, LUA_REFNIL, LUA_REFNIL, 1, { 0 } },
[V_VEC3] = { 3, "vec3", l_lovrMathVec3, l_lovrVec3__metaindex, lovrVec3, LUA_REFNIL, LUA_REFNIL, 1, { 0 } },
[V_VEC4] = { 4, "vec4", l_lovrMathVec4, l_lovrVec4__metaindex, lovrVec4, LUA_REFNIL, LUA_REFNIL, 1, { 0 } },
[V_QUAT] = { 4, "quat", l_lovrMathQuat, l_lovrQuat__metaindex, lovrQuat, LUA_REFNIL, LUA_REFNIL, 1, { 0 } },
[V_MAT4] = { 16, "mat4", l_lovrMathMat4, l_lovrMat4__metaindex, lovrMat4, LUA_REFNIL, LUA_REFNIL, 1, { 0 } }
};
static void luax_destroypool(void) {
lovrRelease(pool, lovrPoolDestroy);
}
float* luax_tovector(lua_State* L, int index, VectorType* type) {
float* luax_tovector(lua_State* L, int index, int* type) {
void* p = lua_touserdata(L, index);
if (p) {
if (lua_type(L, index) == LUA_TLIGHTUSERDATA) {
Vector v = { .pointer = p };
if (v.handle.type > V_NONE && v.handle.type < MAX_VECTOR_TYPES) {
if (type) *type = v.handle.type;
return lovrPoolResolve(pool, v);
}
} else {
VectorType* t = p;
if (*t > V_NONE && *t < MAX_VECTOR_TYPES) {
if (type) *type = *t;
return (float*) (t + 1);
}
int* t = p;
if (*t > V_NONE && *t < MAX_VECTOR_TYPES) {
if (type) *type = *t;
return (float*) (t + 1);
}
}
@ -68,26 +70,38 @@ float* luax_tovector(lua_State* L, int index, VectorType* type) {
return NULL;
}
float* luax_checkvector(lua_State* L, int index, VectorType type, const char* expected) {
VectorType t;
float* luax_checkvector(lua_State* L, int index, int type, const char* expected) {
int t;
float* p = luax_tovector(L, index, &t);
if (!p || t != type) luax_typeerror(L, index, expected ? expected : lovrVectorInfo[type].name);
return p;
}
static float* luax_newvector(lua_State* L, VectorType type, size_t components) {
VectorType* p = lua_newuserdata(L, sizeof(VectorType) + components * sizeof(float));
*p = type;
lua_rawgeti(L, LUA_REGISTRYINDEX, lovrVectorInfo[type].metaref);
lua_setmetatable(L, -2);
return (float*) (p + 1);
}
float* luax_newvector(lua_State* L, int type) {
if (stackIndex > 0) {
lua_rawgeti(L, LUA_REGISTRYINDEX, lovrVectorInfo[type].poolRef);
lua_rawgeti(L, -1, lovrVectorInfo[type].poolCursor);
if (!lua_isnil(L, -1)) {
lua_remove(L, -2);
lovrVectorInfo[type].poolCursor++;
return (float*) ((char*) lua_topointer(L, -1) + sizeof(int));
} else {
lua_pop(L, 1);
}
}
float* luax_newtempvector(lua_State* L, VectorType type) {
float* data;
Vector vector = lovrPoolAllocate(pool, type, &data);
lua_pushlightuserdata(L, vector.pointer);
return data;
void* p = lua_newuserdata(L, sizeof(int) + lovrVectorInfo[type].components * sizeof(float));
*((int*) p) = type;
lua_rawgeti(L, LUA_REGISTRYINDEX, lovrVectorInfo[type].metatableRef);
lua_setmetatable(L, -2);
if (stackIndex > 0) {
lua_pushvalue(L, -1);
lua_rawseti(L, -3, lovrVectorInfo[type].poolCursor++);
lua_remove(L, -2);
}
return (float*) ((char*) p + sizeof(int));
}
static int l_lovrMathNewCurve(lua_State* L) {
@ -213,67 +227,78 @@ static int l_lovrMathLinearToGamma(lua_State* L) {
}
static int l_lovrMathNewVec2(lua_State* L) {
luax_newvector(L, V_VEC2, 2);
luax_newvector(L, V_VEC2);
lua_insert(L, 1);
return l_lovrVec2Set(L);
}
static int l_lovrMathNewVec3(lua_State* L) {
luax_newvector(L, V_VEC3, 4);
luax_newvector(L, V_VEC3);
lua_insert(L, 1);
return l_lovrVec3Set(L);
}
static int l_lovrMathNewVec4(lua_State* L) {
luax_newvector(L, V_VEC4, 4);
luax_newvector(L, V_VEC4);
lua_insert(L, 1);
return l_lovrVec4Set(L);
}
static int l_lovrMathNewQuat(lua_State* L) {
luax_newvector(L, V_QUAT, 4);
luax_newvector(L, V_QUAT);
lua_insert(L, 1);
return l_lovrQuatSet(L);
}
static int l_lovrMathNewMat4(lua_State* L) {
luax_newvector(L, V_MAT4, 16);
luax_newvector(L, V_MAT4);
lua_insert(L, 1);
return l_lovrMat4Set(L);
}
static int l_lovrMathVec2(lua_State* L) {
luax_newtempvector(L, V_VEC2);
luax_newvector(L, V_VEC2);
lua_replace(L, 1);
return l_lovrVec2Set(L);
}
static int l_lovrMathVec3(lua_State* L) {
luax_newtempvector(L, V_VEC3);
luax_newvector(L, V_VEC3);
lua_replace(L, 1);
return l_lovrVec3Set(L);
}
static int l_lovrMathVec4(lua_State* L) {
luax_newtempvector(L, V_VEC4);
luax_newvector(L, V_VEC4);
lua_replace(L, 1);
return l_lovrVec4Set(L);
}
static int l_lovrMathQuat(lua_State* L) {
luax_newtempvector(L, V_QUAT);
luax_newvector(L, V_QUAT);
lua_replace(L, 1);
return l_lovrQuatSet(L);
}
static int l_lovrMathMat4(lua_State* L) {
luax_newtempvector(L, V_MAT4);
luax_newvector(L, V_MAT4);
lua_replace(L, 1);
return l_lovrMat4Set(L);
}
static int l_lovrMathDrain(lua_State* L) {
lovrPoolDrain(pool);
static int l_lovrMathPush(lua_State* L) {
for (int i = V_VEC2; i <= V_MAT4; i++) {
lovrVectorInfo[i].stackPointers[stackIndex] = lovrVectorInfo[i].poolCursor;
}
lovrAssert(++stackIndex < VECTOR_STACK_MAX, "Vector stack overflow (more pushes than pops?)");
return 0;
}
static int l_lovrMathPop(lua_State* L) {
lovrAssert(--stackIndex >= 0, "Vector stack underflow (more pops than pushes?)");
for (int i = V_VEC2; i <= V_MAT4; i++) {
lovrVectorInfo[i].poolCursor = lovrVectorInfo[i].stackPointers[stackIndex];
}
return 0;
}
@ -292,71 +317,24 @@ static const luaL_Reg lovrMath[] = {
{ "newVec4", l_lovrMathNewVec4 },
{ "newQuat", l_lovrMathNewQuat },
{ "newMat4", l_lovrMathNewMat4 },
{ "drain", l_lovrMathDrain },
{ "push", l_lovrMathPush },
{ "pop", l_lovrMathPop },
{ NULL, NULL }
};
static int l_lovrLightUserdata__index(lua_State* L) {
VectorType type;
if (!luax_tovector(L, 1, &type)) {
return 0;
}
lua_rawgeti(L, LUA_REGISTRYINDEX, lovrVectorInfo[type].metaref);
lua_pushvalue(L, 2);
lua_rawget(L, -2);
if (lua_isnil(L, -1)) {
lua_pop(L, 1);
lua_pushliteral(L, "__index");
lua_rawget(L, -2);
if (!lua_isnil(L, -1)) {
lua_pushvalue(L, 1);
lua_pushvalue(L, 2);
lua_call(L, 2, 1);
return 1;
} else {
return 0;
}
}
return 1;
}
static int l_lovrLightUserdataOp(lua_State* L) {
VectorType type;
if (!luax_tovector(L, lua_islightuserdata(L, 1) ? 1 : 2, &type)) {
lua_pushliteral(L, "__tostring");
if (lua_rawequal(L, -1, lua_upvalueindex(1))) {
lua_pop(L, 1);
lua_pushfstring(L, "%s: %p", lua_typename(L, lua_type(L, 1)), lua_topointer(L, 1));
return 1;
}
lua_pop(L, 1);
return luaL_error(L, "Unsupported lightuserdata operator %q", lua_tostring(L, lua_upvalueindex(1)));
}
lua_rawgeti(L, LUA_REGISTRYINDEX, lovrVectorInfo[type].metaref);
lua_pushvalue(L, lua_upvalueindex(1));
lua_gettable(L, -2);
lua_pushvalue(L, 1);
lua_pushvalue(L, 2);
lua_pushvalue(L, 3);
lua_call(L, 3, 1);
return 1;
}
int luaopen_lovr_math(lua_State* L) {
lua_newtable(L);
luax_register(L, lovrMath);
luax_registertype(L, Curve);
luax_registertype(L, RandomGenerator);
for (size_t i = V_NONE + 1; i < MAX_VECTOR_TYPES; i++) {
for (int i = V_NONE + 1; i < MAX_VECTOR_TYPES; i++) {
lua_newtable(L);
lua_newtable(L);
lua_pushcfunction(L, lovrVectorInfo[i].constructor);
lua_pushcfunction(L, lovrVectorInfo[i].metacall);
lua_setfield(L, -2, "__call");
lua_pushcfunction(L, lovrVectorInfo[i].indexer);
lua_pushcfunction(L, lovrVectorInfo[i].metaindex);
lua_setfield(L, -2, "__index");
lua_setmetatable(L, -2);
@ -369,31 +347,24 @@ int luaopen_lovr_math(lua_State* L) {
lua_settable(L, -4);
luax_register(L, lovrVectorInfo[i].api);
lovrVectorInfo[i].metaref = luaL_ref(L, LUA_REGISTRYINDEX);
}
lovrVectorInfo[i].metatableRef = luaL_ref(L, LUA_REGISTRYINDEX);
// Global lightuserdata metatable
lua_pushlightuserdata(L, NULL);
lua_newtable(L);
lua_pushcfunction(L, l_lovrLightUserdata__index);
lua_setfield(L, -2, "__index");
const char* ops[] = { "__add", "__sub", "__mul", "__div", "__unm", "__len", "__tostring", "__newindex" };
for (size_t i = 0; i < COUNTOF(ops); i++) {
lua_pushstring(L, ops[i]);
lua_pushcclosure(L, l_lovrLightUserdataOp, 1);
lua_setfield(L, -2, ops[i]);
// pool
lua_newtable(L);
// __mode = v
lua_newtable(L);
lua_pushliteral(L, "v");
lua_setfield(L, -2, "__mode");
lua_setmetatable(L, -2);
lovrVectorInfo[i].poolRef = luaL_ref(L, LUA_REGISTRYINDEX);
}
lua_setmetatable(L, -2);
lua_pop(L, 1);
// Module
lovrMathInit();
luax_atexit(L, lovrMathDestroy);
// Each Lua state gets its own thread-local Pool
pool = lovrPoolCreate();
luax_atexit(L, luax_destroypool);
// Globals
luax_pushconf(L);
if (lua_istable(L, -1)) {
@ -401,7 +372,7 @@ int luaopen_lovr_math(lua_State* L) {
if (lua_istable(L, -1)) {
lua_getfield(L, -1, "globals");
if (lua_toboolean(L, -1)) {
for (size_t i = V_NONE + 1; i < MAX_VECTOR_TYPES; i++) {
for (int i = V_NONE + 1; i < MAX_VECTOR_TYPES; i++) {
lua_getfield(L, -4, lovrVectorInfo[i].name);
lua_setglobal(L, lovrVectorInfo[i].name);

View File

@ -1,4 +1,5 @@
#include "api.h"
#include "math/math.h"
#include "util.h"
static int l_lovrCurveEvaluate(lua_State* L) {

View File

@ -1,4 +1,5 @@
#include "api.h"
#include "math/math.h"
#include "util.h"
#include <math.h>

View File

@ -113,7 +113,7 @@ int luax_readscale(lua_State* L, int index, vec3 v, int components, const char*
}
return index;
default: {
VectorType type;
int type;
float* u = luax_tovector(L, index++, &type);
if (type == V_VEC2) {
v[0] = u[0];
@ -159,7 +159,7 @@ int luax_readmat4(lua_State* L, int index, mat4 m, int scaleComponents) {
case LUA_TLIGHTUSERDATA:
case LUA_TUSERDATA:
default: {
VectorType type;
int type;
float* p = luax_tovector(L, index, &type);
if (type == V_MAT4) {
mat4_init(m, p);
@ -209,42 +209,6 @@ int l_lovrVec2Set(lua_State* L) {
return 1;
}
static int l_lovrVec2Add(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC2, NULL);
float u[2];
luax_readvec2(L, 2, u, NULL);
vec2_add(v, u);
lua_settop(L, 1);
return 1;
}
static int l_lovrVec2Sub(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC2, NULL);
float u[2];
luax_readvec2(L, 2, u, NULL);
vec2_sub(v, u);
lua_settop(L, 1);
return 1;
}
static int l_lovrVec2Mul(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC2, NULL);
float u[2];
luax_readvec2(L, 2, u, NULL);
vec2_mul(v, u);
lua_settop(L, 1);
return 1;
}
static int l_lovrVec2Div(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC2, NULL);
float u[2];
luax_readvec2(L, 2, u, NULL);
vec2_div(v, u);
lua_settop(L, 1);
return 1;
}
static int l_lovrVec2Length(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC2, NULL);
lua_pushnumber(L, vec2_length(v));
@ -253,8 +217,8 @@ static int l_lovrVec2Length(lua_State* L) {
static int l_lovrVec2Normalize(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC2, NULL);
vec2_normalize(v);
lua_settop(L, 1);
float* out = luax_newvector(L, V_VEC2);
vec2_normalize(vec2_init(out, v));
return 1;
}
@ -279,8 +243,8 @@ static int l_lovrVec2Lerp(lua_State* L) {
float u[2];
int index = luax_readvec2(L, 2, u, NULL);
float t = luax_checkfloat(L, index);
vec2_lerp(v, u, t);
lua_settop(L, 1);
float* out = luax_newvector(L, V_VEC2);
vec2_lerp(vec2_init(out, v), u, t);
return 1;
}
@ -293,7 +257,7 @@ static int l_lovrVec2Angle(lua_State* L) {
}
static int l_lovrVec2__add(lua_State* L) {
float* out = luax_newtempvector(L, V_VEC2);
float* out = luax_newvector(L, V_VEC2);
if (lua_type(L, 1) == LUA_TNUMBER) {
float x = lua_tonumber(L, 1);
float* u = luax_checkvector(L, 2, V_VEC2, NULL);
@ -313,7 +277,7 @@ static int l_lovrVec2__add(lua_State* L) {
}
static int l_lovrVec2__sub(lua_State* L) {
float* out = luax_newtempvector(L, V_VEC2);
float* out = luax_newvector(L, V_VEC2);
if (lua_type(L, 1) == LUA_TNUMBER) {
float x = lua_tonumber(L, 1);
float* u = luax_checkvector(L, 2, V_VEC2, NULL);
@ -333,7 +297,7 @@ static int l_lovrVec2__sub(lua_State* L) {
}
static int l_lovrVec2__mul(lua_State* L) {
float* out = luax_newtempvector(L, V_VEC2);
float* out = luax_newvector(L, V_VEC2);
if (lua_type(L, 1) == LUA_TNUMBER) {
float x = lua_tonumber(L, 1);
float* u = luax_checkvector(L, 2, V_VEC2, NULL);
@ -353,7 +317,7 @@ static int l_lovrVec2__mul(lua_State* L) {
}
static int l_lovrVec2__div(lua_State* L) {
float* out = luax_newtempvector(L, V_VEC2);
float* out = luax_newvector(L, V_VEC2);
if (lua_type(L, 1) == LUA_TNUMBER) {
float x = lua_tonumber(L, 1);
float* u = luax_checkvector(L, 2, V_VEC2, NULL);
@ -374,7 +338,7 @@ static int l_lovrVec2__div(lua_State* L) {
static int l_lovrVec2__unm(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC2, NULL);
float* out = luax_newtempvector(L, V_VEC2);
float* out = luax_newvector(L, V_VEC2);
vec2_scale(vec2_init(out, v), -1.f);
return 1;
}
@ -423,15 +387,13 @@ static int l_lovrVec2__newindex(lua_State* L) {
}
static int l_lovrVec2__index(lua_State* L) {
if (lua_type(L, 1) == LUA_TUSERDATA) {
lua_getmetatable(L, 1);
lua_pushvalue(L, 2);
lua_rawget(L, -2);
if (!lua_isnil(L, -1)) {
return 1;
} else {
lua_pop(L, 2);
}
lua_getmetatable(L, 1);
lua_pushvalue(L, 2);
lua_rawget(L, -2);
if (!lua_isnil(L, -1)) {
return 1;
} else {
lua_pop(L, 2);
}
float* v = luax_checkvector(L, 1, V_VEC2, NULL);
@ -451,18 +413,18 @@ static int l_lovrVec2__index(lua_State* L) {
lua_pushnumber(L, v[swizzles[2][key[0]] - 1]);
return 1;
} else if (length == 2 && swizzles[2][key[0]] && swizzles[2][key[1]]) {
float* out = luax_newtempvector(L, V_VEC2);
float* out = luax_newvector(L, V_VEC2);
out[0] = v[swizzles[2][key[0]] - 1];
out[1] = v[swizzles[2][key[1]] - 1];
return 1;
} else if (length == 3 && swizzles[2][key[0]] && swizzles[2][key[1]] && swizzles[2][key[2]]) {
float* out = luax_newtempvector(L, V_VEC3);
float* out = luax_newvector(L, V_VEC3);
out[0] = v[swizzles[2][key[0]] - 1];
out[1] = v[swizzles[2][key[1]] - 1];
out[2] = v[swizzles[2][key[2]] - 1];
return 1;
} else if (length == 4 && swizzles[2][key[0]] && swizzles[2][key[1]] && swizzles[2][key[2]] && swizzles[2][key[3]]) {
float* out = luax_newtempvector(L, V_VEC4);
float* out = luax_newvector(L, V_VEC4);
out[0] = v[swizzles[2][key[0]] - 1];
out[1] = v[swizzles[2][key[1]] - 1];
out[2] = v[swizzles[2][key[2]] - 1];
@ -491,7 +453,7 @@ int l_lovrVec2__metaindex(lua_State* L) {
for (uint32_t i = 0; i < COUNTOF(properties); i++) {
if (length == properties[i].name.length && !memcmp(key, properties[i].name.string, length)) {
float* v = luax_newtempvector(L, V_VEC2);
float* v = luax_newvector(L, V_VEC2);
v[0] = properties[i].x;
v[1] = properties[i].y;
return 1;
@ -506,10 +468,6 @@ const luaL_Reg lovrVec2[] = {
{ "equals", l_lovrVec2Equals },
{ "unpack", l_lovrVec2Unpack },
{ "set", l_lovrVec2Set },
{ "add", l_lovrVec2Add },
{ "sub", l_lovrVec2Sub },
{ "mul", l_lovrVec2Mul },
{ "div", l_lovrVec2Div },
{ "length", l_lovrVec2Length },
{ "normalize", l_lovrVec2Normalize },
{ "distance", l_lovrVec2Distance },
@ -556,7 +514,7 @@ int l_lovrVec3Set(lua_State* L) {
float x = luax_optfloat(L, 2, 0.f);
vec3_set(v, x, luax_optfloat(L, 3, x), luax_optfloat(L, 4, x));
} else {
VectorType t;
int t;
float* p = luax_tovector(L, 2, &t);
if (p && t == V_VEC3) {
vec3_init(v, p);
@ -572,42 +530,6 @@ int l_lovrVec3Set(lua_State* L) {
return 1;
}
static int l_lovrVec3Add(lua_State* L) {
vec3 v = luax_checkvector(L, 1, V_VEC3, NULL);
float u[3];
luax_readvec3(L, 2, u, NULL);
vec3_add(v, u);
lua_settop(L, 1);
return 1;
}
static int l_lovrVec3Sub(lua_State* L) {
vec3 v = luax_checkvector(L, 1, V_VEC3, NULL);
float u[3];
luax_readvec3(L, 2, u, NULL);
vec3_sub(v, u);
lua_settop(L, 1);
return 1;
}
static int l_lovrVec3Mul(lua_State* L) {
vec3 v = luax_checkvector(L, 1, V_VEC3, NULL);
float u[3];
luax_readvec3(L, 2, u, NULL);
vec3_mul(v, u);
lua_settop(L, 1);
return 1;
}
static int l_lovrVec3Div(lua_State* L) {
vec3 v = luax_checkvector(L, 1, V_VEC3, NULL);
float u[3];
luax_readvec3(L, 2, u, NULL);
vec3_div(v, u);
lua_settop(L, 1);
return 1;
}
static int l_lovrVec3Length(lua_State* L) {
vec3 v = luax_checkvector(L, 1, V_VEC3, NULL);
lua_pushnumber(L, vec3_length(v));
@ -616,8 +538,8 @@ static int l_lovrVec3Length(lua_State* L) {
static int l_lovrVec3Normalize(lua_State* L) {
vec3 v = luax_checkvector(L, 1, V_VEC3, NULL);
vec3_normalize(v);
lua_settop(L, 1);
float* out = luax_newvector(L, V_VEC3);
vec3_normalize(vec3_init(out, v));
return 1;
}
@ -641,8 +563,8 @@ static int l_lovrVec3Cross(lua_State* L) {
vec3 v = luax_checkvector(L, 1, V_VEC3, NULL);
float u[3];
luax_readvec3(L, 2, u, NULL);
vec3_cross(v, u);
lua_settop(L, 1);
float* out = luax_newvector(L, V_VEC3);
vec3_cross(vec3_init(out, v), u);
return 1;
}
@ -651,8 +573,8 @@ static int l_lovrVec3Lerp(lua_State* L) {
float u[3];
int index = luax_readvec3(L, 2, u, NULL);
float t = luax_checkfloat(L, index);
vec3_lerp(v, u, t);
lua_settop(L, 1);
float* out = luax_newvector(L, V_VEC3);
vec3_lerp(vec3_init(out, v), u, t);
return 1;
}
@ -668,8 +590,8 @@ static int l_lovrVec3Transform(lua_State* L) {
vec3 v = luax_checkvector(L, 1, V_VEC3, NULL);
float m[16];
luax_readmat4(L, 2, m, 1);
mat4_mulPoint(m, v);
lua_settop(L, 1);
float* out = luax_newvector(L, V_VEC3);
mat4_mulPoint(m, vec3_init(out, v));
return 1;
}
@ -677,13 +599,13 @@ static int l_lovrVec3Rotate(lua_State* L) {
vec3 v = luax_checkvector(L, 1, V_VEC3, NULL);
float q[4];
luax_readquat(L, 2, q, NULL);
quat_rotate(q, v);
lua_settop(L, 1);
float* out = luax_newvector(L, V_VEC3);
quat_rotate(q, vec3_init(out, v));
return 1;
}
static int l_lovrVec3__add(lua_State* L) {
vec3 out = luax_newtempvector(L, V_VEC3);
vec3 out = luax_newvector(L, V_VEC3);
if (lua_type(L, 1) == LUA_TNUMBER) {
float x = luax_tofloat(L, 1);
vec3 v = luax_checkvector(L, 2, V_VEC3, NULL);
@ -705,7 +627,7 @@ static int l_lovrVec3__add(lua_State* L) {
}
static int l_lovrVec3__sub(lua_State* L) {
vec3 out = luax_newtempvector(L, V_VEC3);
vec3 out = luax_newvector(L, V_VEC3);
if (lua_type(L, 1) == LUA_TNUMBER) {
float x = luax_tofloat(L, 1);
vec3 v = luax_checkvector(L, 2, V_VEC3, NULL);
@ -727,7 +649,7 @@ static int l_lovrVec3__sub(lua_State* L) {
}
static int l_lovrVec3__mul(lua_State* L) {
vec3 out = luax_newtempvector(L, V_VEC3);
vec3 out = luax_newvector(L, V_VEC3);
if (lua_type(L, 1) == LUA_TNUMBER) {
vec3 v = luax_checkvector(L, 2, V_VEC3, NULL);
vec3_scale(vec3_init(out, v), luax_tofloat(L, 1));
@ -743,7 +665,7 @@ static int l_lovrVec3__mul(lua_State* L) {
}
static int l_lovrVec3__div(lua_State* L) {
vec3 out = luax_newtempvector(L, V_VEC3);
vec3 out = luax_newvector(L, V_VEC3);
if (lua_type(L, 1) == LUA_TNUMBER) {
vec3 v = luax_checkvector(L, 2, V_VEC3, NULL);
vec3_scale(vec3_init(out, v), 1.f / luax_tofloat(L, 1));
@ -760,7 +682,7 @@ static int l_lovrVec3__div(lua_State* L) {
static int l_lovrVec3__unm(lua_State* L) {
vec3 v = luax_checkvector(L, 1, V_VEC3, NULL);
vec3 out = luax_newtempvector(L, V_VEC3);
vec3 out = luax_newvector(L, V_VEC3);
vec3_scale(vec3_init(out, v), -1.f);
return 1;
}
@ -815,15 +737,13 @@ static int l_lovrVec3__newindex(lua_State* L) {
}
static int l_lovrVec3__index(lua_State* L) {
if (lua_type(L, 1) == LUA_TUSERDATA) {
lua_getmetatable(L, 1);
lua_pushvalue(L, 2);
lua_rawget(L, -2);
if (!lua_isnil(L, -1)) {
return 1;
} else {
lua_pop(L, 2);
}
lua_getmetatable(L, 1);
lua_pushvalue(L, 2);
lua_rawget(L, -2);
if (!lua_isnil(L, -1)) {
return 1;
} else {
lua_pop(L, 2);
}
float* v = luax_checkvector(L, 1, V_VEC3, NULL);
@ -843,18 +763,18 @@ static int l_lovrVec3__index(lua_State* L) {
lua_pushnumber(L, v[swizzles[3][key[0]] - 1]);
return 1;
} else if (length == 2 && swizzles[3][key[0]] && swizzles[3][key[1]]) {
float* out = luax_newtempvector(L, V_VEC2);
float* out = luax_newvector(L, V_VEC2);
out[0] = v[swizzles[3][key[0]] - 1];
out[1] = v[swizzles[3][key[1]] - 1];
return 1;
} else if (length == 3 && swizzles[3][key[0]] && swizzles[3][key[1]] && swizzles[3][key[2]]) {
float* out = luax_newtempvector(L, V_VEC3);
float* out = luax_newvector(L, V_VEC3);
out[0] = v[swizzles[3][key[0]] - 1];
out[1] = v[swizzles[3][key[1]] - 1];
out[2] = v[swizzles[3][key[2]] - 1];
return 1;
} else if (length == 4 && swizzles[3][key[0]] && swizzles[3][key[1]] && swizzles[3][key[2]] && swizzles[3][key[3]]) {
float* out = luax_newtempvector(L, V_VEC4);
float* out = luax_newvector(L, V_VEC4);
out[0] = v[swizzles[3][key[0]] - 1];
out[1] = v[swizzles[3][key[1]] - 1];
out[2] = v[swizzles[3][key[2]] - 1];
@ -889,7 +809,7 @@ int l_lovrVec3__metaindex(lua_State* L) {
for (uint32_t i = 0; i < COUNTOF(properties); i++) {
if (length == properties[i].name.length && !memcmp(key, properties[i].name.string, length)) {
float* v = luax_newtempvector(L, V_VEC3);
float* v = luax_newvector(L, V_VEC3);
vec3_set(v, properties[i].x, properties[i].y, properties[i].z);
return 1;
}
@ -903,10 +823,6 @@ const luaL_Reg lovrVec3[] = {
{ "equals", l_lovrVec3Equals },
{ "unpack", l_lovrVec3Unpack },
{ "set", l_lovrVec3Set },
{ "add", l_lovrVec3Add },
{ "sub", l_lovrVec3Sub },
{ "mul", l_lovrVec3Mul },
{ "div", l_lovrVec3Div },
{ "length", l_lovrVec3Length },
{ "normalize", l_lovrVec3Normalize },
{ "distance", l_lovrVec3Distance },
@ -960,42 +876,6 @@ int l_lovrVec4Set(lua_State* L) {
return 1;
}
static int l_lovrVec4Add(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
float u[4];
luax_readvec4(L, 2, u, NULL);
vec4_add(v, u);
lua_settop(L, 1);
return 1;
}
static int l_lovrVec4Sub(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
float u[4];
luax_readvec4(L, 2, u, NULL);
vec4_sub(v, u);
lua_settop(L, 1);
return 1;
}
static int l_lovrVec4Mul(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
float u[4];
luax_readvec4(L, 2, u, NULL);
vec4_mul(v, u);
lua_settop(L, 1);
return 1;
}
static int l_lovrVec4Div(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
float u[4];
luax_readvec4(L, 2, u, NULL);
vec4_div(v, u);
lua_settop(L, 1);
return 1;
}
static int l_lovrVec4Length(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
lua_pushnumber(L, vec4_length(v));
@ -1004,7 +884,8 @@ static int l_lovrVec4Length(lua_State* L) {
static int l_lovrVec4Normalize(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
vec4_normalize(v);
float* out = luax_newvector(L, V_VEC4);
vec4_normalize(vec4_init(out, v));
lua_settop(L, 1);
return 1;
}
@ -1030,8 +911,8 @@ static int l_lovrVec4Lerp(lua_State* L) {
float u[4];
int index = luax_readvec4(L, 2, u, NULL);
float t = luax_checkfloat(L, index);
vec4_lerp(v, u, t);
lua_settop(L, 1);
float* out = luax_newvector(L, V_VEC4);
vec4_lerp(vec4_init(out, v), u, t);
return 1;
}
@ -1047,13 +928,13 @@ static int l_lovrVec4Transform(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
float m[16];
luax_readmat4(L, 2, m, 1);
mat4_mulVec4(m, v);
lua_settop(L, 1);
float* out = luax_newvector(L, V_VEC4);
mat4_mulVec4(m, vec4_init(out, v));
return 1;
}
static int l_lovrVec4__add(lua_State* L) {
float* out = luax_newtempvector(L, V_VEC4);
float* out = luax_newvector(L, V_VEC4);
if (lua_type(L, 1) == LUA_TNUMBER) {
float x = lua_tonumber(L, 1);
float* u = luax_checkvector(L, 2, V_VEC4, NULL);
@ -1077,7 +958,7 @@ static int l_lovrVec4__add(lua_State* L) {
}
static int l_lovrVec4__sub(lua_State* L) {
float* out = luax_newtempvector(L, V_VEC4);
float* out = luax_newvector(L, V_VEC4);
if (lua_type(L, 1) == LUA_TNUMBER) {
float x = lua_tonumber(L, 1);
float* u = luax_checkvector(L, 2, V_VEC4, NULL);
@ -1101,7 +982,7 @@ static int l_lovrVec4__sub(lua_State* L) {
}
static int l_lovrVec4__mul(lua_State* L) {
float* out = luax_newtempvector(L, V_VEC4);
float* out = luax_newvector(L, V_VEC4);
if (lua_type(L, 1) == LUA_TNUMBER) {
float x = lua_tonumber(L, 1);
float* u = luax_checkvector(L, 2, V_VEC4, NULL);
@ -1125,7 +1006,7 @@ static int l_lovrVec4__mul(lua_State* L) {
}
static int l_lovrVec4__div(lua_State* L) {
float* out = luax_newtempvector(L, V_VEC4);
float* out = luax_newvector(L, V_VEC4);
if (lua_type(L, 1) == LUA_TNUMBER) {
float x = lua_tonumber(L, 1);
float* u = luax_checkvector(L, 2, V_VEC4, NULL);
@ -1150,7 +1031,7 @@ static int l_lovrVec4__div(lua_State* L) {
static int l_lovrVec4__unm(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
float* out = luax_newtempvector(L, V_VEC4);
float* out = luax_newvector(L, V_VEC4);
vec4_scale(vec4_init(out, v), -1.f);
return 1;
}
@ -1211,15 +1092,13 @@ static int l_lovrVec4__newindex(lua_State* L) {
}
static int l_lovrVec4__index(lua_State* L) {
if (lua_type(L, 1) == LUA_TUSERDATA) {
lua_getmetatable(L, 1);
lua_pushvalue(L, 2);
lua_rawget(L, -2);
if (!lua_isnil(L, -1)) {
return 1;
} else {
lua_pop(L, 2);
}
lua_getmetatable(L, 1);
lua_pushvalue(L, 2);
lua_rawget(L, -2);
if (!lua_isnil(L, -1)) {
return 1;
} else {
lua_pop(L, 2);
}
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
@ -1239,18 +1118,18 @@ static int l_lovrVec4__index(lua_State* L) {
lua_pushnumber(L, v[swizzles[4][key[0]] - 1]);
return 1;
} else if (length == 2 && swizzles[4][key[0]] && swizzles[4][key[1]]) {
float* out = luax_newtempvector(L, V_VEC2);
float* out = luax_newvector(L, V_VEC2);
out[0] = v[swizzles[4][key[0]] - 1];
out[1] = v[swizzles[4][key[1]] - 1];
return 1;
} else if (length == 3 && swizzles[4][key[0]] && swizzles[4][key[1]] && swizzles[4][key[2]]) {
float* out = luax_newtempvector(L, V_VEC3);
float* out = luax_newvector(L, V_VEC3);
out[0] = v[swizzles[4][key[0]] - 1];
out[1] = v[swizzles[4][key[1]] - 1];
out[2] = v[swizzles[4][key[2]] - 1];
return 1;
} else if (length == 4 && swizzles[4][key[0]] && swizzles[4][key[1]] && swizzles[4][key[2]] && swizzles[4][key[3]]) {
float* out = luax_newtempvector(L, V_VEC4);
float* out = luax_newvector(L, V_VEC4);
out[0] = v[swizzles[4][key[0]] - 1];
out[1] = v[swizzles[4][key[1]] - 1];
out[2] = v[swizzles[4][key[2]] - 1];
@ -1279,7 +1158,7 @@ int l_lovrVec4__metaindex(lua_State* L) {
for (uint32_t i = 0; i < COUNTOF(properties); i++) {
if (length == properties[i].name.length && !memcmp(key, properties[i].name.string, length)) {
float* v = luax_newtempvector(L, V_VEC4);
float* v = luax_newvector(L, V_VEC4);
v[0] = properties[i].x;
v[1] = properties[i].y;
v[2] = properties[i].z;
@ -1296,10 +1175,6 @@ const luaL_Reg lovrVec4[] = {
{ "equals", l_lovrVec4Equals },
{ "unpack", l_lovrVec4Unpack },
{ "set", l_lovrVec4Set },
{ "add", l_lovrVec4Add },
{ "sub", l_lovrVec4Sub },
{ "mul", l_lovrVec4Mul },
{ "div", l_lovrVec4Div },
{ "length", l_lovrVec4Length },
{ "normalize", l_lovrVec4Normalize },
{ "distance", l_lovrVec4Distance },
@ -1370,7 +1245,7 @@ int l_lovrQuatSet(lua_State* L) {
quat_fromAngleAxis(q, x, y, z, w);
}
} else {
VectorType type;
int type;
float* p = luax_tovector(L, 2, &type);
if (!p) return luax_typeerror(L, 2, "vec3, quat, or number");
@ -1394,29 +1269,6 @@ int l_lovrQuatSet(lua_State* L) {
return 1;
}
static int l_lovrQuatMul(lua_State* L) {
quat q = luax_checkvector(L, 1, V_QUAT, NULL);
VectorType type;
float* r = luax_tovector(L, 2, &type);
if (r && type == V_VEC3) {
vec3 v = luax_newtempvector(L, V_VEC3);
quat_rotate(q, vec3_init(v, r));
} else if (r && type == V_QUAT) {
quat_mul(q, q, r);
lua_settop(L, 1);
} else if (lua_type(L, 2) == LUA_TNUMBER) {
lua_settop(L, 4);
vec3 v = luax_newtempvector(L, V_VEC3);
v[0] = luax_tofloat(L, 2);
v[1] = luax_checkfloat(L, 3);
v[2] = luax_checkfloat(L, 4);
quat_rotate(q, v);
} else {
return luax_typeerror(L, 2, "number, vec3, or quat");
}
return 1;
}
static int l_lovrQuatLength(lua_State* L) {
quat q = luax_checkvector(L, 1, V_QUAT, NULL);
lua_pushnumber(L, quat_length(q));
@ -1425,22 +1277,22 @@ static int l_lovrQuatLength(lua_State* L) {
static int l_lovrQuatNormalize(lua_State* L) {
quat q = luax_checkvector(L, 1, V_QUAT, NULL);
quat_normalize(q);
lua_settop(L, 1);
float* out = luax_newvector(L, V_QUAT);
quat_normalize(quat_init(out, q));
return 1;
}
static int l_lovrQuatDirection(lua_State* L) {
quat q = luax_checkvector(L, 1, V_QUAT, NULL);
vec3 v = luax_newtempvector(L, V_VEC3);
vec3 v = luax_newvector(L, V_VEC3);
quat_getDirection(q, v);
return 1;
}
static int l_lovrQuatConjugate(lua_State* L) {
quat q = luax_checkvector(L, 1, V_QUAT, NULL);
quat_conjugate(q);
lua_settop(L, 1);
float* out = luax_newvector(L, V_QUAT);
quat_conjugate(quat_init(out, q));
return 1;
}
@ -1448,8 +1300,8 @@ static int l_lovrQuatSlerp(lua_State* L) {
quat q = luax_checkvector(L, 1, V_QUAT, NULL);
quat r = luax_checkvector(L, 2, V_QUAT, NULL);
float t = luax_checkfloat(L, 3);
quat_slerp(q, r, t);
lua_settop(L, 1);
float* out = luax_newvector(L, V_QUAT);
quat_slerp(quat_init(out, q), r, t);
return 1;
}
@ -1475,14 +1327,14 @@ static int l_lovrQuatSetEuler(lua_State* L) {
static int l_lovrQuat__mul(lua_State* L) {
quat q = luax_checkvector(L, 1, V_QUAT, NULL);
VectorType type;
int type;
float* r = luax_tovector(L, 2, &type);
if (!r) return luax_typeerror(L, 2, "quat or vec3");
if (type == V_VEC3) {
vec3 out = luax_newtempvector(L, V_VEC3);
vec3 out = luax_newvector(L, V_VEC3);
quat_rotate(q, vec3_init(out, r));
} else {
quat out = luax_newtempvector(L, V_QUAT);
quat out = luax_newvector(L, V_QUAT);
quat_mul(out, q, r);
}
return 1;
@ -1526,15 +1378,13 @@ static int l_lovrQuat__newindex(lua_State* L) {
}
static int l_lovrQuat__index(lua_State* L) {
if (lua_type(L, 1) == LUA_TUSERDATA) {
lua_getmetatable(L, 1);
lua_pushvalue(L, 2);
lua_rawget(L, -2);
if (!lua_isnil(L, -1)) {
return 1;
} else {
lua_pop(L, 2);
}
lua_getmetatable(L, 1);
lua_pushvalue(L, 2);
lua_rawget(L, -2);
if (!lua_isnil(L, -1)) {
return 1;
} else {
lua_pop(L, 2);
}
float* q = luax_checkvector(L, 1, V_QUAT, NULL);
@ -1574,7 +1424,7 @@ int l_lovrQuat__metaindex(lua_State* L) {
for (uint32_t i = 0; i < COUNTOF(properties); i++) {
if (length == properties[i].name.length && !memcmp(key, properties[i].name.string, length)) {
float* q = luax_newtempvector(L, V_QUAT);
float* q = luax_newvector(L, V_QUAT);
quat_set(q, properties[i].x, properties[i].y, properties[i].z, properties[i].w);
return 1;
}
@ -1588,7 +1438,6 @@ const luaL_Reg lovrQuat[] = {
{ "equals", l_lovrQuatEquals },
{ "unpack", l_lovrQuatUnpack },
{ "set", l_lovrQuatSet },
{ "mul", l_lovrQuatMul },
{ "length", l_lovrQuatLength },
{ "normalize", l_lovrQuatNormalize },
{ "direction", l_lovrQuatDirection },
@ -1714,7 +1563,7 @@ int l_lovrMat4Set(lua_State* L) {
*m++ = luax_checkfloat(L, i);
}
} else {
VectorType vectorType;
int vectorType;
float* n = luax_tovector(L, 2, &vectorType);
if (vectorType == V_MAT4) {
mat4_init(m, n);
@ -1764,74 +1613,50 @@ int l_lovrMat4Set(lua_State* L) {
return 1;
}
static int l_lovrMat4Mul(lua_State* L) {
mat4 m = luax_checkvector(L, 1, V_MAT4, NULL);
VectorType type;
float* n = luax_tovector(L, 2, &type);
if (n && type == V_MAT4) {
mat4_mul(m, n);
lua_settop(L, 1);
} else if (n && type == V_VEC3) {
vec3 v = luax_newtempvector(L, V_VEC3);
mat4_mulPoint(m, vec3_init(v, n));
} else if (n && type == V_VEC4) {
vec4 v = luax_newtempvector(L, V_VEC4);
mat4_mulVec4(m, vec4_init(v, n));
} else if (lua_type(L, 2) == LUA_TNUMBER) {
lua_settop(L, 4);
vec3 v = luax_newtempvector(L, V_VEC3);
v[0] = luax_tofloat(L, 2);
v[1] = luax_checkfloat(L, 3);
v[2] = luax_checkfloat(L, 4);
mat4_mulPoint(m, v);
} else {
return luax_typeerror(L, 2, "mat4, vec3, vec4, or number");
}
return 1;
}
static int l_lovrMat4Identity(lua_State* L) {
mat4 m = luax_checkvector(L, 1, V_MAT4, NULL);
mat4_identity(m);
lua_settop(L, 1);
return 1;
}
static int l_lovrMat4Invert(lua_State* L) {
mat4 m = luax_checkvector(L, 1, V_MAT4, NULL);
mat4_invert(m);
lua_settop(L, 1);
float* out = luax_newvector(L, V_MAT4);
mat4_invert(mat4_init(out, m));
return 1;
}
static int l_lovrMat4Transpose(lua_State* L) {
mat4 m = luax_checkvector(L, 1, V_MAT4, NULL);
mat4_transpose(m);
lua_settop(L, 1);
float* out = luax_newvector(L, V_MAT4);
mat4_transpose(mat4_init(out, m));
return 1;
}
static int l_lovrMat4Translate(lua_State* L) {
mat4 m = luax_checkvector(L, 1, V_MAT4, NULL);
if (lua_type(L, 2) == LUA_TNUMBER) {
mat4_translate(m, luax_checkfloat(L, 2), luax_checkfloat(L, 3), luax_checkfloat(L, 4));
float x = luax_checkfloat(L, 2);
float y = luax_checkfloat(L, 3);
float z = luax_checkfloat(L, 4);
float* out = luax_newvector(L, V_MAT4);
mat4_translate(mat4_init(out, m), x, y, z);
} else {
float* v = luax_checkvector(L, 2, V_VEC3, "vec3 or number");
mat4_translate(m, v[0], v[1], v[2]);
float* out = luax_newvector(L, V_MAT4);
mat4_translate(mat4_init(out, m), v[0], v[1], v[2]);
}
lua_settop(L, 1);
return 1;
}
static int l_lovrMat4Rotate(lua_State* L) {
mat4 m = luax_checkvector(L, 1, V_MAT4, NULL);
if (lua_type(L, 2) == LUA_TNUMBER) {
mat4_rotate(m, luax_checkfloat(L, 2), luax_optfloat(L, 3, 0.f), luax_optfloat(L, 4, 1.f), luax_optfloat(L, 5, 0.f));
float angle = luax_checkfloat(L, 2);
float ax = luax_optfloat(L, 3, 0.f);
float ay = luax_optfloat(L, 4, 1.f);
float az = luax_optfloat(L, 5, 0.f);
float* out = luax_newvector(L, V_MAT4);
mat4_rotate(mat4_init(out, m), angle, ax, ay, az);
} else {
float* q = luax_checkvector(L, 2, V_QUAT, "quat or number");
mat4_rotateQuat(m, q);
float* out = luax_newvector(L, V_MAT4);
mat4_rotateQuat(mat4_init(out, m), q);
}
lua_settop(L, 1);
return 1;
}
@ -1839,23 +1664,27 @@ static int l_lovrMat4Scale(lua_State* L) {
mat4 m = luax_checkvector(L, 1, V_MAT4, NULL);
if (lua_type(L, 2) == LUA_TNUMBER) {
float x = luax_checkfloat(L, 2);
mat4_scale(m, x, luax_optfloat(L, 3, x), luax_optfloat(L, 4, x));
float y = luax_optfloat(L, 3, x);
float z = luax_optfloat(L, 4, x);
float* out = luax_newvector(L, V_MAT4);
mat4_scale(mat4_init(out, m), x, y, z);
} else {
float* s = luax_checkvector(L, 2, V_VEC3, "vec3 or number");
mat4_scale(m, s[0], s[1], s[2]);
float* out = luax_newvector(L, V_MAT4);
mat4_scale(mat4_init(out, m), s[0], s[1], s[2]);
}
lua_settop(L, 1);
return 1;
}
static int l_lovrMat4Orthographic(lua_State* L) {
mat4 m = luax_checkvector(L, 1, V_MAT4, NULL);
luax_checkvector(L, 1, V_MAT4, NULL);
if (lua_gettop(L) <= 5) {
float width = luax_checkfloat(L, 2);
float height = luax_checkfloat(L, 3);
float n = luax_optfloat(L, 4, -1.f);
float f = luax_optfloat(L, 5, 1.f);
mat4_orthographic(m, 0.f, width, 0.f, height, n, f);
float* out = luax_newvector(L, V_MAT4);
mat4_orthographic(out, 0.f, width, 0.f, height, n, f);
} else {
float left = luax_checkfloat(L, 2);
float right = luax_checkfloat(L, 3);
@ -1863,79 +1692,80 @@ static int l_lovrMat4Orthographic(lua_State* L) {
float top = luax_checkfloat(L, 5);
float n = luax_checkfloat(L, 6);
float f = luax_checkfloat(L, 7);
mat4_orthographic(m, left, right, bottom, top, n, f);
float* out = luax_newvector(L, V_MAT4);
mat4_orthographic(out, left, right, bottom, top, n, f);
}
lua_settop(L, 1);
return 1;
}
static int l_lovrMat4Perspective(lua_State* L) {
mat4 m = luax_checkvector(L, 1, V_MAT4, NULL);
luax_checkvector(L, 1, V_MAT4, NULL);
float fovy = luax_checkfloat(L, 2);
float aspect = luax_checkfloat(L, 3);
float n = luax_checkfloat(L, 4);
float f = luax_optfloat(L, 5, 0.);
mat4_perspective(m, fovy, aspect, n, f);
lua_settop(L, 1);
float* out = luax_newvector(L, V_MAT4);
mat4_perspective(out, fovy, aspect, n, f);
return 1;
}
static int l_lovrMat4Fov(lua_State* L) {
mat4 m = luax_checkvector(L, 1, V_MAT4, NULL);
luax_checkvector(L, 1, V_MAT4, NULL);
float left = luax_checkfloat(L, 2);
float right = luax_checkfloat(L, 3);
float up = luax_checkfloat(L, 4);
float down = luax_checkfloat(L, 5);
float n = luax_checkfloat(L, 6);
float f = luax_optfloat(L, 7, 0.);
mat4_fov(m, left, right, up, down, n, f);
float* out = luax_newvector(L, V_MAT4);
mat4_fov(out, left, right, up, down, n, f);
lua_settop(L, 1);
return 1;
}
static int l_lovrMat4LookAt(lua_State* L) {
mat4 m = luax_checkvector(L, 1, V_MAT4, NULL);
luax_checkvector(L, 1, V_MAT4, NULL);
vec3 from = luax_checkvector(L, 2, V_VEC3, NULL);
vec3 to = luax_checkvector(L, 3, V_VEC3, NULL);
vec3 up = lua_isnoneornil(L, 4) ? (float[3]) { 0.f, 1.f, 0.f } : luax_checkvector(L, 4, V_VEC3, NULL);
mat4_lookAt(m, from, to, up);
lua_settop(L, 1);
float* out = luax_newvector(L, V_MAT4);
mat4_lookAt(out, from, to, up);
return 1;
}
static int l_lovrMat4Target(lua_State* L) {
mat4 m = luax_checkvector(L, 1, V_MAT4, NULL);
luax_checkvector(L, 1, V_MAT4, NULL);
vec3 from = luax_checkvector(L, 2, V_VEC3, NULL);
vec3 to = luax_checkvector(L, 3, V_VEC3, NULL);
vec3 up = lua_isnoneornil(L, 4) ? (float[3]) { 0.f, 1.f, 0.f } : luax_checkvector(L, 4, V_VEC3, NULL);
mat4_target(m, from, to, up);
lua_settop(L, 1);
float* out = luax_newvector(L, V_MAT4);
mat4_target(out, from, to, up);
return 1;
}
static int l_lovrMat4Reflect(lua_State* L) {
mat4 m = luax_checkvector(L, 1, V_MAT4, NULL);
luax_checkvector(L, 1, V_MAT4, NULL);
vec3 position = luax_checkvector(L, 2, V_VEC3, NULL);
vec3 normal = luax_checkvector(L, 3, V_VEC3, NULL);
mat4_reflect(m, position, normal);
lua_settop(L, 1);
float* out = luax_newvector(L, V_MAT4);
mat4_reflect(out, position, normal);
return 1;
}
static int l_lovrMat4__mul(lua_State* L) {
mat4 m = luax_checkvector(L, 1, V_MAT4, NULL);
VectorType type;
int type;
float* n = luax_tovector(L, 2, &type);
if (!n || (type == V_VEC2 || type == V_QUAT)) return luax_typeerror(L, 2, "mat4, vec3, or vec4");
if (type == V_MAT4) {
mat4 out = luax_newtempvector(L, V_MAT4);
mat4 out = luax_newvector(L, V_MAT4);
mat4_mul(mat4_init(out, m), n);
} else if (type == V_VEC3) {
vec3 out = luax_newtempvector(L, V_VEC3);
vec3 out = luax_newvector(L, V_VEC3);
vec3_init(out, n);
mat4_mulPoint(m, out);
} else if (type == V_VEC4) {
float* out = luax_newtempvector(L, V_VEC4);
float* out = luax_newvector(L, V_VEC4);
memcpy(out, n, 4 * sizeof(float));
mat4_mulVec4(m, out);
} else {
@ -1971,15 +1801,13 @@ static int l_lovrMat4__newindex(lua_State* L) {
}
static int l_lovrMat4__index(lua_State* L) {
if (lua_type(L, 1) == LUA_TUSERDATA) {
lua_getmetatable(L, 1);
lua_pushvalue(L, 2);
lua_rawget(L, -2);
if (!lua_isnil(L, -1)) {
return 1;
} else {
lua_pop(L, 2);
}
lua_getmetatable(L, 1);
lua_pushvalue(L, 2);
lua_rawget(L, -2);
if (!lua_isnil(L, -1)) {
return 1;
} else {
lua_pop(L, 2);
}
float* m = luax_checkvector(L, 1, V_MAT4, NULL);
@ -1997,7 +1825,26 @@ static int l_lovrMat4__index(lua_State* L) {
}
int l_lovrMat4__metaindex(lua_State* L) {
return 0; // No properties currently, 'identity' is already taken
if (lua_type(L, 2) != LUA_TSTRING) {
return 0;
}
size_t length;
const char* key = lua_tolstring(L, 2, &length);
static struct { StringEntry name; float m[16]; } properties[] = {
{ ENTRY("identity"), MAT4_IDENTITY }
};
for (uint32_t i = 0; i < COUNTOF(properties); i++) {
if (length == properties[i].name.length && !memcmp(key, properties[i].name.string, length)) {
float* m = luax_newvector(L, V_MAT4);
mat4_set(m, properties[i].m);
return 1;
}
}
return 0;
}
const luaL_Reg lovrMat4[] = {
@ -2009,8 +1856,6 @@ const luaL_Reg lovrMat4[] = {
{ "getScale", l_lovrMat4GetScale },
{ "getPose", l_lovrMat4GetPose },
{ "set", l_lovrMat4Set },
{ "mul", l_lovrMat4Mul },
{ "identity", l_lovrMat4Identity },
{ "invert", l_lovrMat4Invert },
{ "transpose", l_lovrMat4Transpose },
{ "translate", l_lovrMat4Translate },

View File

@ -16,14 +16,6 @@ struct Curve {
arr_t(float) points;
};
struct Pool {
uint32_t ref;
float* data;
uint32_t count;
uint32_t cursor;
uint32_t generation;
};
struct RandomGenerator {
uint32_t ref;
Seed seed;
@ -216,70 +208,6 @@ void lovrCurveRemovePoint(Curve* curve, size_t index) {
arr_splice(&curve->points, index * 4, 4);
}
// Pool
static const size_t vectorComponents[] = {
[V_VEC2] = 2,
[V_VEC3] = 4,
[V_VEC4] = 4,
[V_QUAT] = 4,
[V_MAT4] = 16
};
Pool* lovrPoolCreate(void) {
Pool* pool = calloc(1, sizeof(Pool));
lovrAssert(pool, "Out of memory");
pool->ref = 1;
pool->data = os_vm_init((1 << 24) * sizeof(float));
lovrPoolGrow(pool, 1 << 12);
return pool;
}
void lovrPoolDestroy(void* ref) {
Pool* pool = ref;
os_vm_free(pool->data, (1 << 24) * sizeof(float));
free(pool);
}
void lovrPoolGrow(Pool* pool, size_t count) {
lovrAssert(count <= (1 << 24), "Temporary vector space exhausted. Try using lovr.math.drain to drain the vector pool periodically.");
pool->count = (uint32_t) count; // Assert guarantees safe
bool result = os_vm_commit(pool->data, count * sizeof(float));
lovrAssert(result, "Out of memory");
}
Vector lovrPoolAllocate(Pool* pool, VectorType type, float** data) {
lovrCheck(pool, "The math module must be initialized to create vectors");
size_t count = vectorComponents[type];
if (pool->cursor + count > pool->count) {
lovrPoolGrow(pool, pool->count * 2);
}
Vector v = {
.handle = {
.type = type,
.generation = pool->generation,
.index = pool->cursor
}
};
*data = pool->data + pool->cursor;
pool->cursor += (uint32_t) count; // Cast safe because vectorComponents members are known
return v;
}
float* lovrPoolResolve(Pool* pool, Vector vector) {
lovrAssert(vector.handle.generation == pool->generation, "Attempt to use a temporary vector from a previous frame");
return pool->data + vector.handle.index;
}
void lovrPoolDrain(Pool* pool) {
pool->cursor = 0;
pool->generation = (pool->generation + 1) & 0xf;
}
// RandomGenerator (compatible with LÖVE's)
// Thomas Wang's 64-bit integer hashing function:

View File

@ -5,7 +5,6 @@
#pragma once
typedef struct Curve Curve;
typedef struct Pool Pool;
typedef struct RandomGenerator RandomGenerator;
bool lovrMathInit(void);
@ -31,35 +30,6 @@ void lovrCurveSetPoint(Curve* curve, size_t index, float* point);
void lovrCurveAddPoint(Curve* curve, float* point, size_t index);
void lovrCurveRemovePoint(Curve* curve, size_t index);
// Pool
typedef enum {
V_NONE,
V_VEC2,
V_VEC3,
V_VEC4,
V_QUAT,
V_MAT4,
MAX_VECTOR_TYPES
} VectorType;
typedef union {
void* pointer;
struct {
unsigned type : 4;
unsigned generation : 4;
unsigned index : 24;
unsigned padding : 32;
} handle;
} Vector;
Pool* lovrPoolCreate(void);
void lovrPoolDestroy(void* ref);
void lovrPoolGrow(Pool* pool, size_t count);
Vector lovrPoolAllocate(Pool* pool, VectorType type, float** data);
float* lovrPoolResolve(Pool* pool, Vector vector);
void lovrPoolDrain(Pool* pool);
// RandomGenerator
typedef union {