#define GLM_ENABLE_EXPERIMENTAL #include #include #include #include #include "api_lua.hpp" template inline T angle(glm::vec<2, T> vec) { auto val = std::atan2(vec.y, vec.x); if (val < 0.0) { return val + glm::two_pi(); } return val; } template class Op> static int l_binop(lua::State* L) { uint argc = lua::check_argc(L, 2, 3); auto a = lua::tovec(L, 1); if (lua::isnumber(L, 2)) { // scalar second operand overload auto b = lua::tonumber(L, 2); Op op; if (argc == 2) { lua::createtable(L, n, 0); for (uint i = 0; i < n; i++) { lua::pushnumber(L, op(a[i], b)); lua::rawseti(L, i + 1); } return 1; } else { return lua::setvec(L, 3, op(a, glm::vec(b))); } } else { auto b = lua::tovec(L, 2); Op op; if (argc == 2) { lua::createtable(L, n, 0); for (uint i = 0; i < n; i++) { lua::pushnumber(L, op(a[i], b[i])); lua::rawseti(L, i + 1); } return 1; } else { return lua::setvec(L, 3, op(a, b)); } } } template (*func)(const glm::vec&)> static int l_unaryop(lua::State* L) { uint argc = lua::check_argc(L, 1, 2); auto vec = func(lua::tovec(L, 1)); switch (argc) { case 1: lua::createtable(L, n, 0); for (uint i = 0; i < n; i++) { lua::pushnumber(L, vec[i]); lua::rawseti(L, i + 1); } return 1; case 2: return lua::setvec(L, 2, vec); } return 0; } template &)> static int l_scalar_op(lua::State* L) { lua::check_argc(L, 1); auto vec = lua::tovec(L, 1); return lua::pushnumber(L, func(vec)); } template static int l_pow(lua::State* L) { uint argc = lua::check_argc(L, 2, 3); auto a = lua::tovec(L, 1); if (lua::isnumber(L, 2)) { auto b = lua::tonumber(L, 2); if (argc == 2) { lua::createtable(L, n, 0); for (uint i = 0; i < n; i++) { lua::pushnumber(L, pow(a[i], b)); lua::rawseti(L, i + 1); } return 1; } else { return lua::setvec(L, 3, pow(a, glm::vec(b))); } } else { auto b = lua::tovec(L, 2); if (argc == 2) { lua::createtable(L, n, 0); for (uint i = 0; i < n; i++) { lua::pushnumber(L, pow(a[i], b[i])); lua::rawseti(L, i + 1); } return 1; } else { return lua::setvec(L, 3, pow(a, b)); } } } template static int l_dot(lua::State* L) { lua::check_argc(L, 2); const auto& a = lua::tovec(L, 1); const auto& b = lua::tovec(L, 2); return lua::pushnumber(L, glm::dot(a, b)); } template static int l_inverse(lua::State* L) { uint argc = lua::check_argc(L, 1, 2); auto vec = lua::tovec(L, 1); switch (argc) { case 1: lua::createtable(L, n, 0); for (uint i = 0; i < n; i++) { lua::pushnumber(L, (-1) * vec[i]); lua::rawseti(L, i + 1); } return 1; case 2: return lua::setvec(L, 2, -vec); } return 0; } static int l_spherical_rand(lua::State* L) { uint argc = lua::check_argc(L, 1, 2); switch (argc) { case 1: return lua::pushvec3(L, glm::sphericalRand(lua::tonumber(L, 1))); case 2: return lua::setvec( L, 2, glm::sphericalRand(static_cast(lua::tonumber(L, 1))) ); } return 0; } static int l_vec2_angle(lua::State* L) { uint argc = lua::check_argc(L, 1, 2); if (argc == 1) { return lua::pushnumber(L, glm::degrees(angle(lua::tovec2(L, 1)))); } else { return lua::pushnumber( L, glm::degrees( angle(glm::vec2(lua::tonumber(L, 1), lua::tonumber(L, 2))) ) ); } } template static int l_tostring(lua::State* L) { lua::check_argc(L, 1); auto vec = lua::tovec(L, 1); std::stringstream ss; ss << "vec" << std::to_string(n) << "{"; for (int i = 0; i < n; i++) { if (i > 0) { ss << ", "; } ss << vec[i]; } ss << "}"; return lua::pushstring(L, ss.str()); } const luaL_Reg vec2lib[] = { {"add", lua::wrap>}, {"sub", lua::wrap>}, {"mul", lua::wrap>}, {"div", lua::wrap>}, {"normalize", lua::wrap>}, {"length", lua::wrap>}, {"tostring", lua::wrap>}, {"abs", lua::wrap>}, {"round", lua::wrap>}, {"inverse", lua::wrap>}, {"pow", lua::wrap>}, {"dot", lua::wrap>}, {"angle", lua::wrap}, {NULL, NULL}}; const luaL_Reg vec3lib[] = { {"add", lua::wrap>}, {"sub", lua::wrap>}, {"mul", lua::wrap>}, {"div", lua::wrap>}, {"normalize", lua::wrap>}, {"length", lua::wrap>}, {"tostring", lua::wrap>}, {"abs", lua::wrap>}, {"round", lua::wrap>}, {"inverse", lua::wrap>}, {"pow", lua::wrap>}, {"dot", lua::wrap>}, {"spherical_rand", lua::wrap}, {NULL, NULL}}; const luaL_Reg vec4lib[] = { {"add", lua::wrap>}, {"sub", lua::wrap>}, {"mul", lua::wrap>}, {"div", lua::wrap>}, {"normalize", lua::wrap>}, {"length", lua::wrap>}, {"tostring", lua::wrap>}, {"abs", lua::wrap>}, {"round", lua::wrap>}, {"inverse", lua::wrap>}, {"pow", lua::wrap>}, {"dot", lua::wrap>}, {NULL, NULL}};