This commit is contained in:
bjorn 2019-07-16 20:22:52 -07:00 committed by Bjorn
parent 23bba1d59b
commit 122143b13a
7 changed files with 3442 additions and 2090 deletions

View File

@ -48,6 +48,7 @@ extern const luaL_Reg lovrTexture[];
extern const luaL_Reg lovrTextureData[];
extern const luaL_Reg lovrThread[];
extern const luaL_Reg lovrVec2[];
extern const luaL_Reg lovrVec4[];
extern const luaL_Reg lovrVec3[];
extern const luaL_Reg lovrWorld[];

View File

@ -15,6 +15,7 @@ int l_lovrRandomGeneratorGetSeed(lua_State* L);
int l_lovrRandomGeneratorSetSeed(lua_State* L);
int l_lovrVec2Set(lua_State* L);
int l_lovrVec3Set(lua_State* L);
int l_lovrVec4Set(lua_State* L);
int l_lovrQuatSet(lua_State* L);
int l_lovrMat4Set(lua_State* L);
@ -23,6 +24,7 @@ static LOVR_THREAD_LOCAL Pool* pool;
static const luaL_Reg* lovrVectorMetatables[] = {
[V_VEC2] = lovrVec2,
[V_VEC3] = lovrVec3,
[V_VEC4] = lovrVec4,
[V_QUAT] = lovrQuat,
[V_MAT4] = lovrMat4
};
@ -30,6 +32,7 @@ static const luaL_Reg* lovrVectorMetatables[] = {
static int lovrVectorMetatableRefs[] = {
[V_VEC2] = LUA_REFNIL,
[V_VEC3] = LUA_REFNIL,
[V_VEC4] = LUA_REFNIL,
[V_QUAT] = LUA_REFNIL,
[V_MAT4] = LUA_REFNIL
};
@ -37,6 +40,7 @@ static int lovrVectorMetatableRefs[] = {
static const char* lovrVectorTypeNames[] = {
[V_VEC2] = "vec2",
[V_VEC3] = "vec3",
[V_VEC4] = "vec4",
[V_QUAT] = "quat",
[V_MAT4] = "mat4"
};
@ -229,6 +233,12 @@ static int l_lovrMathNewVec3(lua_State* L) {
return l_lovrVec3Set(L);
}
static int l_lovrMathNewVec4(lua_State* L) {
luax_newvector(L, V_VEC4, 4);
lua_insert(L, 1);
return l_lovrVec4Set(L);
}
static int l_lovrMathNewQuat(lua_State* L) {
luax_newvector(L, V_QUAT, 4);
lua_insert(L, 1);
@ -253,6 +263,12 @@ static int l_lovrMathVec3(lua_State* L) {
return l_lovrVec3Set(L);
}
static int l_lovrMathVec4(lua_State* L) {
luax_newtempvector(L, V_VEC4);
lua_insert(L, 1);
return l_lovrVec4Set(L);
}
static int l_lovrMathQuat(lua_State* L) {
luax_newtempvector(L, V_QUAT);
lua_insert(L, 1);
@ -282,10 +298,12 @@ static const luaL_Reg lovrMath[] = {
{ "linearToGamma", l_lovrMathLinearToGamma },
{ "newVec2", l_lovrMathNewVec2 },
{ "newVec3", l_lovrMathNewVec3 },
{ "newVec4", l_lovrMathNewVec4 },
{ "newQuat", l_lovrMathNewQuat },
{ "newMat4", l_lovrMathNewMat4 },
{ "vec2", l_lovrMathVec2 },
{ "vec3", l_lovrMathVec3 },
{ "vec4", l_lovrMathVec4 },
{ "quat", l_lovrMathQuat },
{ "mat4", l_lovrMathMat4 },
{ "drain", l_lovrMathDrain },

View File

@ -433,12 +433,19 @@ static int l_lovrVec2__index(lua_State* L) {
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);
out[0] = v[swizzles[2][key[0]] - 1];
out[1] = v[swizzles[2][key[1]] - 1];
out[2] = v[swizzles[2][key[2]] - 1];
out[3] = v[swizzles[2][key[3]] - 1];
return 1;
}
}
lua_getglobal(L, "tostring");
lua_pushvalue(L, 2);
lua_call(L, 1, 1);
return luaL_error(L, "attempt to index property %q of vec2 (invalid property)", lua_tostring(L, -1));
return luaL_error(L, "attempt to index field %q of vec2 (invalid property)", lua_tostring(L, -1));
}
const luaL_Reg lovrVec2[] = {
@ -758,12 +765,19 @@ static int l_lovrVec3__index(lua_State* L) {
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);
out[0] = v[swizzles[3][key[0]] - 1];
out[1] = v[swizzles[3][key[1]] - 1];
out[2] = v[swizzles[3][key[2]] - 1];
out[3] = v[swizzles[3][key[3]] - 1];
return 1;
}
}
lua_getglobal(L, "tostring");
lua_pushvalue(L, 2);
lua_call(L, 1, 1);
return luaL_error(L, "attempt to index property %q of vec2 (invalid property)", lua_tostring(L, -1));
return luaL_error(L, "attempt to index field %q of vec3 (invalid property)", lua_tostring(L, -1));
}
const luaL_Reg lovrVec3[] = {
@ -791,6 +805,412 @@ const luaL_Reg lovrVec3[] = {
{ NULL, NULL }
};
// vec4
static int l_lovrVec4Unpack(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
lua_pushnumber(L, v[0]);
lua_pushnumber(L, v[1]);
lua_pushnumber(L, v[2]);
lua_pushnumber(L, v[3]);
return 4;
}
int l_lovrVec4Set(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
if (lua_isnoneornil(L, 2) || lua_type(L, 2) == LUA_TNUMBER) {
v[0] = luax_optfloat(L, 2, 0.f);
v[1] = luax_optfloat(L, 3, v[0]);
v[2] = luax_optfloat(L, 4, v[0]);
v[3] = luax_optfloat(L, 5, v[0]);
} else {
float* u = luax_checkvector(L, 2, V_VEC4, "vec4 or number");
v[0] = u[0];
v[1] = u[1];
v[2] = u[2];
v[3] = u[3];
}
lua_settop(L, 1);
return 1;
}
static int l_lovrVec4Add(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
if (lua_type(L, 2) == LUA_TNUMBER) {
float x = lua_tonumber(L, 2);
v[0] += x;
v[1] += x;
v[2] += x;
v[3] += x;
} else {
float* u = luax_checkvector(L, 2, V_VEC4, "vec4 or number");
v[0] += u[0];
v[1] += u[1];
v[2] += u[2];
v[3] += u[3];
}
lua_settop(L, 1);
return 1;
}
static int l_lovrVec4Sub(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
if (lua_type(L, 2) == LUA_TNUMBER) {
float x = lua_tonumber(L, 2);
v[0] -= x;
v[1] -= x;
v[2] -= x;
v[3] -= x;
} else {
float* u = luax_checkvector(L, 2, V_VEC4, "vec4 or number");
v[0] -= u[0];
v[1] -= u[1];
v[2] -= u[2];
v[3] -= u[3];
}
lua_settop(L, 1);
return 1;
}
static int l_lovrVec4Mul(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
if (lua_type(L, 2) == LUA_TNUMBER) {
float x = lua_tonumber(L, 2);
v[0] *= x;
v[1] *= x;
v[2] *= x;
v[3] *= x;
} else {
float* u = luax_checkvector(L, 2, V_VEC4, "vec4 or number");
v[0] *= u[0];
v[1] *= u[1];
v[2] *= u[2];
v[3] *= u[3];
}
lua_settop(L, 1);
return 1;
}
static int l_lovrVec4Div(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
if (lua_type(L, 2) == LUA_TNUMBER) {
float x = lua_tonumber(L, 2);
v[0] /= x;
v[1] /= x;
v[2] /= x;
v[3] /= x;
} else {
float* u = luax_checkvector(L, 2, V_VEC4, "vec4 or number");
v[0] /= u[0];
v[1] /= u[1];
v[2] /= u[2];
v[3] /= u[3];
}
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, sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]));
return 1;
}
static int l_lovrVec4Normalize(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
float length = v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3];
if (length != 0.f) {
length = 1.f / sqrtf(length);
v[0] *= length;
v[1] *= length;
v[2] *= length;
v[3] *= length;
}
lua_settop(L, 1);
return 1;
}
static int l_lovrVec4Distance(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
float* u = luax_checkvector(L, 2, V_VEC4, NULL);
float dx = v[0] - u[0];
float dy = v[1] - u[1];
float dz = v[2] - u[2];
float dw = v[3] - u[3];
lua_pushnumber(L, sqrtf(dx * dx + dy * dy + dz * dz + dw * dw));
return 1;
}
static int l_lovrVec4Dot(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
float* u = luax_checkvector(L, 2, V_VEC4, NULL);
lua_pushnumber(L, v[0] * u[0] + v[1] * u[1] + v[2] * u[2] + v[3] * u[3]);
return 1;
}
static int l_lovrVec4Lerp(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
float* u = luax_checkvector(L, 2, V_VEC4, NULL);
float t = luax_checkfloat(L, 3);
v[0] = v[0] + (u[0] - v[0]) * t;
v[1] = v[1] + (u[1] - v[1]) * t;
v[2] = v[2] + (u[2] - v[2]) * t;
v[3] = v[3] + (u[3] - v[3]) * t;
lua_settop(L, 1);
return 1;
}
static int l_lovrVec4__add(lua_State* L) {
float* out = luax_newtempvector(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);
out[0] = u[0] + x;
out[1] = u[1] + x;
out[2] = u[2] + x;
out[3] = u[3] + x;
} else if (lua_type(L, 2) == LUA_TNUMBER) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
float x = lua_tonumber(L, 2);
out[0] = v[0] + x;
out[1] = v[1] + x;
out[2] = v[2] + x;
out[3] = v[3] + x;
} else {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
float* u = luax_checkvector(L, 2, V_VEC4, "vec4 or number");
out[0] = v[0] + u[0];
out[1] = v[1] + u[1];
out[2] = v[2] + u[2];
out[3] = v[3] + u[3];
}
return 1;
}
static int l_lovrVec4__sub(lua_State* L) {
float* out = luax_newtempvector(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);
out[0] = u[0] - x;
out[1] = u[1] - x;
out[2] = u[2] - x;
out[3] = u[3] - x;
} else if (lua_type(L, 2) == LUA_TNUMBER) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
float x = lua_tonumber(L, 2);
out[0] = v[0] - x;
out[1] = v[1] - x;
out[2] = v[2] - x;
out[3] = v[3] - x;
} else {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
float* u = luax_checkvector(L, 2, V_VEC4, "vec4 or number");
out[0] = v[0] - u[0];
out[1] = v[1] - u[1];
out[2] = v[2] - u[2];
out[3] = v[3] - u[3];
}
return 1;
}
static int l_lovrVec4__mul(lua_State* L) {
float* out = luax_newtempvector(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);
out[0] = u[0] * x;
out[1] = u[1] * x;
out[2] = u[2] * x;
out[3] = u[3] * x;
} else if (lua_type(L, 2) == LUA_TNUMBER) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
float x = lua_tonumber(L, 2);
out[0] = v[0] * x;
out[1] = v[1] * x;
out[2] = v[2] * x;
out[3] = v[3] * x;
} else {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
float* u = luax_checkvector(L, 2, V_VEC4, "vec4 or number");
out[0] = v[0] * u[0];
out[1] = v[1] * u[1];
out[2] = v[2] * u[2];
out[3] = v[3] * u[3];
}
return 1;
}
static int l_lovrVec4__div(lua_State* L) {
float* out = luax_newtempvector(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);
out[0] = u[0] / x;
out[1] = u[1] / x;
out[2] = u[2] / x;
out[3] = u[3] / x;
} else if (lua_type(L, 2) == LUA_TNUMBER) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
float x = lua_tonumber(L, 2);
out[0] = v[0] / x;
out[1] = v[1] / x;
out[2] = v[2] / x;
out[3] = v[3] / x;
} else {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
float* u = luax_checkvector(L, 2, V_VEC4, "vec4 or number");
out[0] = v[0] / u[0];
out[1] = v[1] / u[1];
out[2] = v[2] / u[2];
out[3] = v[3] / u[3];
}
return 1;
}
static int l_lovrVec4__unm(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
float* out = luax_newtempvector(L, V_VEC4);
out[0] = -v[0];
out[1] = -v[1];
out[2] = -v[2];
out[3] = -v[3];
return 1;
}
static int l_lovrVec4__len(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
lua_pushnumber(L, sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]));
return 1;
}
static int l_lovrVec4__tostring(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
lua_pushfstring(L, "(%f, %f, %f, %f)", v[0], v[1], v[2], v[3]);
return 1;
}
static int l_lovrVec4__newindex(lua_State* L) {
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
if (lua_type(L, 2) == LUA_TNUMBER) {
int index = lua_tointeger(L, 2);
if (index >= 1 && index <= 4) {
float x = luax_checkfloat(L, 3);
v[index - 1] = x;
return 0;
}
} else if (lua_type(L, 2) == LUA_TSTRING) {
size_t length;
const char* str = lua_tolstring(L, 2, &length);
const unsigned char* key = (const unsigned char*) str;
if (length == 1 && swizzles[4][key[0]]) {
v[swizzles[4][key[0]] - 1] = luax_checkfloat(L, 3);
return 0;
} else if (length == 2 && swizzles[4][key[0]] && swizzles[4][key[1]]) {
float* u = luax_checkvector(L, 3, V_VEC2, NULL);
for (size_t i = 0; i < length; i++) {
v[swizzles[4][key[i]] - 1] = u[i];
}
return 0;
} else if (length == 3 && swizzles[4][key[0]] && swizzles[4][key[1]] && swizzles[4][key[2]]) {
float* u = luax_checkvector(L, 3, V_VEC3, NULL);
for (size_t i = 0; i < length; i++) {
v[swizzles[4][key[i]] - 1] = u[i];
}
return 0;
} else if (length == 4 && swizzles[4][key[0]] && swizzles[4][key[1]] && swizzles[4][key[2]] && swizzles[4][key[3]]) {
float* u = luax_checkvector(L, 3, V_VEC4, NULL);
for (size_t i = 0; i < length; i++) {
v[swizzles[4][key[i]] - 1] = u[i];
}
return 0;
}
}
lua_getglobal(L, "tostring");
lua_pushvalue(L, 2);
lua_call(L, 1, 1);
return luaL_error(L, "attempt to assign property %q of vec4 (invalid property)", lua_tostring(L, -1));
}
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);
}
}
float* v = luax_checkvector(L, 1, V_VEC4, NULL);
int type = lua_type(L, 2);
if (type == LUA_TNUMBER) {
int index = lua_tointeger(L, 2);
if (index >= 1 && index <= 4) {
lua_pushnumber(L, v[index - 1]);
return 1;
}
} else if (type == LUA_TSTRING) {
size_t length;
const char* str = lua_tolstring(L, 2, &length);
const unsigned char* key = (const unsigned char*) str;
if (length == 1 && swizzles[4][key[0]]) {
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);
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);
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);
out[0] = v[swizzles[4][key[0]] - 1];
out[1] = v[swizzles[4][key[1]] - 1];
out[2] = v[swizzles[4][key[2]] - 1];
out[3] = v[swizzles[4][key[3]] - 1];
return 1;
}
}
lua_getglobal(L, "tostring");
lua_pushvalue(L, 2);
lua_call(L, 1, 1);
return luaL_error(L, "attempt to index field %q of vec4 (invalid property)", lua_tostring(L, -1));
}
const luaL_Reg lovrVec4[] = {
{ "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 },
{ "dot", l_lovrVec4Dot },
{ "lerp", l_lovrVec4Lerp },
{ "__add", l_lovrVec4__add },
{ "__sub", l_lovrVec4__sub },
{ "__mul", l_lovrVec4__mul },
{ "__div", l_lovrVec4__div },
{ "__unm", l_lovrVec4__unm },
{ "__len", l_lovrVec4__len },
{ "__tostring", l_lovrVec4__tostring },
{ "__newindex", l_lovrVec4__newindex },
{ "__index", l_lovrVec4__index },
{ NULL, NULL }
};
// quat
static int l_lovrQuatUnpack(lua_State* L) {
@ -987,7 +1407,7 @@ static int l_lovrQuat__index(lua_State* L) {
lua_getglobal(L, "tostring");
lua_pushvalue(L, 2);
lua_call(L, 1, 1);
return luaL_error(L, "attempt to index property %q of quat (invalid property)", lua_tostring(L, -1));
return luaL_error(L, "attempt to index field %q of quat (invalid property)", lua_tostring(L, -1));
}
const luaL_Reg lovrQuat[] = {
@ -1242,7 +1662,7 @@ static int l_lovrMat4__index(lua_State* L) {
lua_getglobal(L, "tostring");
lua_pushvalue(L, 2);
lua_call(L, 1, 1);
return luaL_error(L, "attempt to index property %q of mat4 (invalid property)", lua_tostring(L, -1));
return luaL_error(L, "attempt to index field %q of mat4 (invalid property)", lua_tostring(L, -1));
}
const luaL_Reg lovrMat4[] = {

View File

@ -6,6 +6,7 @@
static const size_t vectorComponents[] = {
[V_VEC2] = 2,
[V_VEC3] = 4,
[V_VEC4] = 4,
[V_QUAT] = 4,
[V_MAT4] = 16
};

View File

@ -8,6 +8,7 @@ typedef enum {
V_NONE,
V_VEC2,
V_VEC3,
V_VEC4,
V_QUAT,
V_MAT4,
MAX_VECTOR_TYPES

View File

@ -10,12 +10,14 @@ typedef enum {
NONE,
VEC2,
VEC3,
VEC4,
QUAT,
MAT4
} VectorType;
typedef struct { uint8_t type; uint8_t generation; uint16_t index; } vec2;
typedef struct { uint8_t type; uint8_t generation; uint16_t index; } vec3;
typedef struct { uint8_t type; uint8_t generation; uint16_t index; } vec4;
typedef struct { uint8_t type; uint8_t generation; uint16_t index; } quat;
typedef struct { uint8_t type; uint8_t generation; uint16_t index; } mat4;
@ -75,18 +77,21 @@ end
local vec2_t = ffi.typeof('vec2')
local vec3_t = ffi.typeof('vec3')
local vec4_t = ffi.typeof('vec4')
local quat_t = ffi.typeof('quat')
local mat4_t = ffi.typeof('mat4')
local checkvec2 = checktype(C.VEC2, 'vec2')
local checkvec3 = checktype(C.VEC3, 'vec3')
local checkvec4 = checktype(C.VEC4, 'vec4')
local checkquat = checktype(C.QUAT, 'quat')
local checkmat4 = checktype(C.MAT4, 'mat4')
local isvec2 = istype(C.VEC2, 'vec2')
local isvec3 = istype(C.VEC3, 'vec3')
local isvec4 = istype(C.VEC4, 'vec4')
local isquat = istype(C.QUAT, 'quat')
local ismat4 = istype(C.MAT4, 'mat4')
local vec2, vec3, quat, mat4
local vec2, vec3, vec4, quat, mat4
vec2 = {
unpack = function(self)
@ -299,6 +304,11 @@ vec2 = {
if a and b and c then
return lovr_math.vec3(v[a], v[b], v[c])
end
elseif #key == 4 then
local a, b, c, d = swizzles[key:sub(1, 1)], swizzles[key:sub(2, 2)], swizzles[key:sub(3, 3)], swizzles[key:sub(4, 4)]
if a and b and c and d then
return lovr_math.vec4(v[a], v[b], v[c], v[d])
end
end
elseif key == 1 or key == 2 then
return v[key - 1]
@ -554,15 +564,295 @@ vec3 = {
if a and b and c then
return lovr_math.vec3(v[a], v[b], v[c])
end
elseif #key == 4 then
local a, b, c, d = swizzles[key:sub(1, 1)], swizzles[key:sub(2, 2)], swizzles[key:sub(3, 3)], swizzles[key:sub(4, 4)]
if a and b and c and d then
return lovr_math.vec4(v[a], v[b], v[c], v[d])
end
end
elseif type(key) == 'number' and key >= 1 and key <= 3 then
return v[key - 1]
end
error(string.format('attempt to index vec3 using %s (invalid type)', type(key)), 2)
error(string.format('attempt to index field %q of vec3 (invalid property)', type(key)), 2)
end
}
vec4 = {
unpack = function(self)
local v = checkvec4(self)
return v[0], v[1], v[2], v[3]
end,
set = function(self, x, y, z, w)
local v = checkvec4(self)
if x == nil then
v[0], v[1], v[2], v[3] = 0, 0, 0, 0
elseif type(x) == 'number' then
v[0], v[1], v[2], v[3] = x, y or x, z or x, w or x
else
local u = checkvec4(x, 1, 'vec4 or number')
v[0], v[1], v[2], v[3] = u[0], u[1], u[2], u[3]
end
return self
end,
add = function(self, x)
local v = checkvec3(self)
if type(x) == 'number' then
v[0] = v[0] + x
v[1] = v[1] + x
v[2] = v[2] + x
v[3] = v[3] + x
else
local u = checkvec4(x, 1, 'vec4 or number')
v[0] = v[0] + u[0]
v[1] = v[1] + u[1]
v[2] = v[2] + u[2]
v[3] = v[3] + u[3]
end
return self
end,
sub = function(self, x)
local v = checkvec4(self)
if type(x) == 'number' then
v[0] = v[0] - x
v[1] = v[1] - x
v[2] = v[2] - x
v[3] = v[3] - x
else
local u = checkvec4(x, 1, 'vec4 or number')
v[0] = v[0] - u[0]
v[1] = v[1] - u[1]
v[2] = v[2] - u[2]
v[3] = v[3] - u[3]
end
return self
end,
mul = function(self, x)
local v = checkvec4(self)
if type(x) == 'number' then
v[0] = v[0] * x
v[1] = v[1] * x
v[2] = v[2] * x
v[3] = v[3] * x
else
local u = checkvec4(x, 1, 'vec4 or number')
v[0] = v[0] * u[0]
v[1] = v[1] * u[1]
v[2] = v[2] * u[2]
v[3] = v[3] * u[3]
end
return self
end,
div = function(self, x)
local v = checkvec4(self)
if type(x) == 'number' then
v[0] = v[0] / x
v[1] = v[1] / x
v[2] = v[2] / x
v[3] = v[3] / x
else
local u = checkvec4(x, 1, 'vec4 or number')
v[0] = v[0] / u[0]
v[1] = v[1] / u[1]
v[2] = v[2] / u[2]
v[3] = v[3] / u[3]
end
return self
end,
length = function(self)
local v = checkvec4(self)
return math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3])
end,
normalize = function(self)
local v = checkvec4(self)
local length2 = v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]
if length2 ~= 0 then
local n = 1 / math.sqrt(length2)
v[0] = v[0] * n
v[1] = v[1] * n
v[2] = v[2] * n
v[3] = v[3] * n
end
return self
end,
distance = function(self, other)
local v = checkvec4(self)
local u = checkvec4(other, 1)
local dx = v[0] - u[0]
local dy = v[1] - u[1]
local dz = v[2] - u[2]
local dw = v[3] - u[3]
return math.sqrt(dx * dx + dy * dy + dz * dz + dw * dw)
end,
dot = function(self, other)
local v = checkvec4(self)
local u = checkvec4(other, 1)
return v[0] * u[0] + v[1] * u[1] + v[2] * u[2] + u[3] * v[3]
end,
lerp = function(self, other, t)
local v = checkvec4(self)
local u = checkvec4(other, 1)
v[0] = v[0] + (u[0] - v[0]) * t
v[1] = v[1] + (u[1] - v[1]) * t
v[2] = v[2] + (u[2] - v[2]) * t
v[3] = v[3] + (u[3] - v[3]) * t
return self
end,
__add = function(a, b)
checkvec4(a, 1)
return lovr_math.vec4(a):add(b)
end,
__sub = function(a, b)
checkvec4(a, 1)
return lovr_math.vec4(a):sub(b)
end,
__mul = function(a, b)
checkvec4(a, 1)
return lovr_math.vec4(a):mul(b)
end,
__div = function(a, b)
checkvec4(a, 1)
return lovr_math.vec4(a):div(b)
end,
__unm = function(self)
checkvec4(self)
return lovr_math.vec4(self):mul(-1)
end,
__len = function(self)
checkvec4(self)
return self:length()
end,
__tostring = function(self)
local v = checkvec4(self)
return string.format('(%f, %f, %f, %f)', v[0], v[1], v[2], v[3])
end,
__newindex = function(self, key, value)
local v = checkvec3(self)
local swizzles = {
x = 0,
y = 1,
z = 2,
w = 3,
r = 0,
g = 1,
b = 2,
a = 3,
s = 0,
t = 1,
p = 2,
q = 3
}
if type(key) == 'string' then
if #key == 1 then
local a = swizzles[key:sub(1, 1)]
if a then
v[a] = value
return
end
elseif #key == 2 then
local a, b = swizzles[key:sub(1, 1)], swizzles[key:sub(2, 2)]
if a and b then
local u = checkvec2(value, 1)
v[a], v[b] = u[0], u[1]
return
end
elseif #key == 3 then
local a, b, c = swizzles[key:sub(1, 1)], swizzles[key:sub(2, 2)], swizzles[key:sub(3, 3)]
if a and b and c then
local u = checkvec3(value, 1)
v[a], v[b], v[c] = u[0], u[1], u[2]
return
end
elseif #key == 4 then
local a, b, c, d = swizzles[key:sub(1, 1)], swizzles[key:sub(2, 2)], swizzles[key:sub(3, 3)], swizzles[key:sub(4, 4)]
if a and b and c and d then
local u = checkvec4(value, 1)
v[a], v[b], v[c], v[d] = u[0], u[1], u[2], u[3]
return
end
end
elseif type(key) == 'number' then
if key >= 1 and key <= 4 then
v[key - 1] = value
end
end
error(string.format('attempt to assign property %q of vec4 (invalid property)', key), 2)
end,
__index = function(self, key)
if vec4[key] then
return vec4[key]
end
local v = checkvec4(self)
if type(key) == 'string' then
local swizzles = {
x = 0,
y = 1,
z = 2,
w = 3,
r = 0,
g = 1,
b = 2,
a = 3,
s = 0,
t = 1,
p = 2,
q = 3
}
if #key == 1 then
local a = swizzles[key:sub(1, 1)]
if a then
return v[a]
end
elseif #key == 2 then
local a, b = swizzles[key:sub(1, 1)], swizzles[key:sub(2, 2)]
if a and b then
return lovr_math.vec2(v[a], v[b])
end
elseif #key == 3 then
local a, b, c = swizzles[key:sub(1, 1)], swizzles[key:sub(2, 2)], swizzles[key:sub(3, 3)]
if a and b and c then
return lovr_math.vec3(v[a], v[b], v[c])
end
elseif #key == 4 then
local a, b, c, d = swizzles[key:sub(1, 1)], swizzles[key:sub(2, 2)], swizzles[key:sub(3, 3)], swizzles[key:sub(4, 4)]
if a and b and c and d then
return lovr_math.vec4(v[a], v[b], v[c], v[d])
end
end
elseif type(key) == 'number' and key >= 1 and key <= 4 then
return v[key - 1]
end
error(string.format('attempt to index field %q of vec4 (invalid property)', type(key)), 2)
end
}
quat = {
unpack = function(self, raw)
local q = checkquat(self)
@ -748,7 +1038,7 @@ quat = {
return q[3]
end
error(string.format('attempt to index property %q of quat (invalid property)', key), 2)
error(string.format('attempt to index field %q of quat (invalid property)', key), 2)
end
}
@ -1062,18 +1352,20 @@ mat4 = {
return m[key - 1]
end
error(string.format('attempt to index property %q of mat4 (invalid property)', key), 2)
error(string.format('attempt to index field %q of mat4 (invalid property)', key), 2)
end
}
ffi.metatype(vec2_t, vec2)
ffi.metatype(vec3_t, vec3)
ffi.metatype(vec4_t, vec4)
ffi.metatype(quat_t, quat)
ffi.metatype(mat4_t, mat4)
local new = ffi.new
lovr_math.vec2 = function(...) return allocate(vec2_t, C.VEC2, 2):set(...) end
lovr_math.vec3 = function(...) return allocate(vec3_t, C.VEC3, 4):set(...) end
lovr_math.vec4 = function(...) return allocate(vec4_t, C.VEC4, 4):set(...) end
lovr_math.quat = function(...) return allocate(quat_t, C.QUAT, 4):set(...) end
lovr_math.mat4 = function(...) return allocate(mat4_t, C.MAT4, 16):set(...) end
lovr_math.drain = function()

File diff suppressed because it is too large Load Diff