Compare commits

...

8 Commits

Author SHA1 Message Date
Bjorn be21b145ff
Merge f9f627c710 into aa79822edb 2024-03-11 08:21:44 +01:00
bjorn aa79822edb Fix VertexIndex;
Adding an offset to VertexIndex/BaseVertex breaks those builtins for
shader code.  Instead, go back to binding the vertex buffer at an
appropriate offset.

This means we rebind the vertex buffer and makes it harder to batch
draws.  In the future we'd like to go back to binding all vertex buffers
at zero and incorporating per-draw vertex offsets, but we'll need to
adjust the VertexIndex macro to subtract that offset.
2024-03-10 10:36:13 -07:00
bjorn f9f627c710 rm unused Pool struct; 2024-01-20 16:48:03 -08:00
bjorn 072f712ef1 rm add/sub/mul/div mutating methods; 2024-01-20 16:47:54 -08:00
bjorn e0a7d442d0 Vector stack supports nesting and has error messages; 2024-01-20 16:47:54 -08:00
bjorn a30a00818b No need to check for userdata type in __index; 2024-01-20 16:47:54 -08:00
bjorn c7d4801ba2 lovr.math.push/lovr.math.pop experiment; 2024-01-20 16:47:54 -08:00
bjorn cc426d0453 Experimental vector changes;
- Removes temporary vectors.  All vectors are permanent now.  The
  temporary constructors still exist for compatibility, but they create
  permanent vectors.  Also removes lovr.math.drain.
- All vector methods (except :set) return new vectors instead of
  mutating.  This makes some methods vestigial/weird, like
  :add/sub/mul/div and matrix "initializers" like
  :identity/:fov/:perspective/:ortho/:lookAt/:target/:reflect.
2024-01-20 16:47:54 -08:00
14 changed files with 307 additions and 585 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

@ -373,6 +373,7 @@ typedef struct {
uint64_t hash;
uint32_t start;
uint32_t baseVertex;
uint32_t vertexBufferOffset;
gpu_buffer* vertexBuffer;
gpu_buffer* indexBuffer;
} CachedShape;
@ -479,6 +480,7 @@ typedef struct {
gpu_buffer* vertexBuffer;
gpu_buffer* indexBuffer;
gpu_buffer* uniformBuffer;
uint32_t vertexBufferOffset;
uint32_t uniformOffset;
union {
struct {
@ -1388,6 +1390,7 @@ static void recordRenderPass(Pass* pass, gpu_stream* stream) {
gpu_bundle* bundle = NULL;
Material* material = NULL;
gpu_buffer* vertexBuffer = NULL;
uint32_t vertexBufferOffset = 0;
gpu_buffer* indexBuffer = NULL;
gpu_buffer* uniformBuffer = NULL;
uint32_t uniformOffset = 0;
@ -1440,9 +1443,10 @@ static void recordRenderPass(Pass* pass, gpu_stream* stream) {
uniformOffset = draw->uniformOffset;
}
if (draw->vertexBuffer && draw->vertexBuffer != vertexBuffer) {
gpu_bind_vertex_buffers(stream, &draw->vertexBuffer, NULL, 0, 1);
if (draw->vertexBuffer && (draw->vertexBuffer != vertexBuffer || draw->vertexBufferOffset != vertexBufferOffset)) {
gpu_bind_vertex_buffers(stream, &draw->vertexBuffer, &draw->vertexBufferOffset, 0, 1);
vertexBuffer = draw->vertexBuffer;
vertexBufferOffset = draw->vertexBufferOffset;
}
if (draw->indexBuffer && draw->indexBuffer != indexBuffer) {
@ -1451,8 +1455,8 @@ static void recordRenderPass(Pass* pass, gpu_stream* stream) {
indexBuffer = draw->indexBuffer;
}
uint32_t drawId = i & 0xff;
gpu_push_constants(stream, draw->shader->gpu, &drawId, sizeof(drawId));
uint32_t DrawID = i & 0xff;
gpu_push_constants(stream, draw->shader->gpu, &DrawID, sizeof(DrawID));
if (draw->flags & DRAW_INDIRECT) {
if (draw->indexBuffer) {
@ -6017,6 +6021,7 @@ static void lovrPassResolveVertices(Pass* pass, DrawInfo* info, Draw* draw) {
draw->indexBuffer = cached->indexBuffer;
draw->start = cached->start;
draw->baseVertex = cached->baseVertex;
draw->vertexBufferOffset = cached->vertexBufferOffset;
*info->vertex.pointer = NULL;
*info->index.pointer = NULL;
return;
@ -6028,24 +6033,17 @@ static void lovrPassResolveVertices(Pass* pass, DrawInfo* info, Draw* draw) {
BufferView view = lovrPassGetBuffer(pass, info->vertex.count * stride, stride);
*info->vertex.pointer = view.pointer;
draw->vertexBuffer = view.buffer;
if (info->index.buffer || info->index.count > 0) {
draw->baseVertex = view.offset / stride;
} else {
draw->start = view.offset / stride;
}
draw->vertexBufferOffset = view.offset;
} else if (info->vertex.buffer) {
Buffer* buffer = info->vertex.buffer;
uint32_t stride = buffer->info.format->stride;
lovrCheck(stride <= state.limits.vertexBufferStride, "Vertex buffer stride exceeds vertexBufferStride limit");
trackBuffer(pass, buffer, GPU_PHASE_INPUT_VERTEX, GPU_CACHE_VERTEX);
draw->vertexBuffer = buffer->gpu;
if (info->index.buffer || info->index.count > 0) {
draw->baseVertex += buffer->base / stride;
} else {
draw->start += buffer->base / stride;
}
draw->vertexBufferOffset = buffer->base;
} else {
draw->vertexBuffer = state.defaultBuffer->gpu;
draw->vertexBufferOffset = state.defaultBuffer->base;
}
if (!info->index.buffer && info->index.count > 0) {
@ -6068,6 +6066,7 @@ static void lovrPassResolveVertices(Pass* pass, DrawInfo* info, Draw* draw) {
cached->indexBuffer = draw->indexBuffer;
cached->start = draw->start;
cached->baseVertex = draw->baseVertex;
cached->vertexBufferOffset = draw->vertexBufferOffset;
}
}

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 {