diff --git a/Pluto.vcxproj b/Pluto.vcxproj index f44eecd23d..673d085d58 100644 --- a/Pluto.vcxproj +++ b/Pluto.vcxproj @@ -472,6 +472,7 @@ + diff --git a/src/linit.cpp b/src/linit.cpp index b0e9d211c8..d8e64177a2 100644 --- a/src/linit.cpp +++ b/src/linit.cpp @@ -104,189 +104,6 @@ end function instanceof(a, b) return a instanceof b end - -package.preload["Vector3"] = function() - local Vector3 - class Vector3 - __name = "Vector3" - - function __construct(x, y, z) - if x ~= nil and y == nil and z == nil then - -- (a) -> (a, a, a) - self.x = x - self.y = x - self.z = x - else - -- (a, b) -> (a, b, 0) - -- (a, b, c) -> (a, b, c) - self.x = x ?? 0 - self.y = y ?? 0 - self.z = z ?? 0 - end - end - - function __add(b) - if b instanceof Vector3 then - return new Vector3(self.x + b.x, self.y + b.y, self.z + b.z) - end - return new Vector3(self.x + b, self.y + b, self.z + b) - end - - function __sub(b) - if b instanceof Vector3 then - return new Vector3(self.x - b.x, self.y - b.y, self.z - b.z) - end - return new Vector3(self.x - b, self.y - b, self.z - b) - end - - function __mul(b) - if b instanceof Vector3 then - return new Vector3(self.x * b.x, self.y * b.y, self.z * b.z) - end - return new Vector3(self.x * b, self.y * b, self.z * b) - end - - function __div(b) - if b instanceof Vector3 then - return new Vector3(self.x / b.x, self.y / b.y, self.z / b.z) - end - return new Vector3(self.x / b, self.y / b, self.z / b) - end - - function __eq(b) - return self.x == b.x and self.y == b.y and self.z == b.z - end - - function __len() - return self:magnitude() - end - - function __tostring() - return $"Vector3({self.x}, {self.y}, {self.z})" - end - - function magnitude() - local accum = 0 - for self as axis do - accum += axis^2 - end - return math.sqrt(accum) - end - - function distance(b) - return (self - b):magnitude() - end - - function sum() - local accum = 0 - for self as axis do - accum += axis - end - return accum - end - - function min() - local min = math.huge - for self as axis do - if min > axis then - min = axis - end - end - return min - end - - function max() - local max = 0 - for self as axis do - if max < axis then - max = axis - end - end - return max - end - - function dot(b) - return (self * b):sum() - end - - function crossproduct(b) - return new Vector3( - self.y * b.z - self.z * b.y, - self.z * b.x - self.x * b.z, - self.x * b.y - self.y * b.x - ) - end - - function abs() - return new Vector3(math.abs(self.x), math.abs(self.y), math.abs(self.z)) - end - - function normalised() - return self / self:magnitude() - end - - function normalized() - return self / self:magnitude() - end - - function torot(up) - if up == "y" then - local yaw = math.deg(math.atan(self.x, self.z)) * -1 - local pitch = math.deg(math.asin(self.y / self:magnitude())) - return new Vector3( - math.isnan(pitch) ? 0 : pitch, - yaw, - 0 - ) - elseif up == "z" then - local yaw = math.deg(math.atan(self.x, self.y)) * -1 - local pitch = math.deg(math.asin(self.z / self:magnitude())) - return new Vector3( - math.isnan(pitch) ? 0 : pitch, - 0, - yaw - ) - else - error("Expected \"y\" or \"z\" for 'up' parameter") - end - end - - function lookat(up) - local dir = (b - self) - return dir:torot(up) - end - - function todir(up) - if up == "y" then - local yaw_radians = math.rad(self.z) - local pitch_radians = math.rad(self.x) * -1 - return new Vector3( - math.cos(pitch_radians) * math.sin(yaw_radians) * -1, - math.sin(pitch_radians) * -1, - math.cos(pitch_radians) * math.cos(yaw_radians) - ) - elseif up == "z" then - local yaw_radians = math.rad(self.z) - local pitch_radians = math.rad(self.x) * -1 - return new Vector3( - math.cos(pitch_radians) * math.sin(yaw_radians) * -1, - math.cos(pitch_radians) * math.cos(yaw_radians), - math.sin(pitch_radians) * -1 - ) - else - error("Expected \"y\" or \"z\" for 'up' parameter") - end - end - end - - setmetatable(Vector3, { - function __call(x, y, z) - return new Vector3(x, y, z) - end - }) - - return Vector3 -end )EOC"; luaL_loadbuffer(L, startup_code, strlen(startup_code), "Pluto Standard Library"); lua_call(L, 0, 0); diff --git a/src/lualib.h b/src/lualib.h index bef5b8586e..c074cab760 100644 --- a/src/lualib.h +++ b/src/lualib.h @@ -50,6 +50,7 @@ namespace Pluto { extern const PreloadedLibrary preloaded_base64; #endif extern const PreloadedLibrary preloaded_assert; + extern const PreloadedLibrary preloaded_Vector3; inline const PreloadedLibrary* const all_preloaded[] = { &preloaded_crypto, @@ -59,6 +60,7 @@ namespace Pluto { &preloaded_base64, #endif &preloaded_assert, + &preloaded_Vector3, }; } @@ -69,6 +71,7 @@ LUAMOD_API int (luaopen_base32) (lua_State *L); LUAMOD_API int (luaopen_base64) (lua_State *L); #endif LUAMOD_API int (luaopen_assert) (lua_State *L); +LUAMOD_API int (luaopen_Vector3) (lua_State *L); /* open all previous libraries */ LUALIB_API void (luaL_openlibs) (lua_State *L); diff --git a/src/lvector3lib.cpp b/src/lvector3lib.cpp new file mode 100644 index 0000000000..e94282be2c --- /dev/null +++ b/src/lvector3lib.cpp @@ -0,0 +1,196 @@ +#include + +#define LUA_LIB +#include "lualib.h" + +static const luaL_Reg funcs[] = { + {nullptr, nullptr} +}; + +LUAMOD_API int luaopen_Vector3(lua_State* L) { + const auto code = R"EOC(local Vector3 + class Vector3 + __name = "Vector3" + + function __construct(x, y, z) + if x ~= nil and y == nil and z == nil then + -- (a) -> (a, a, a) + self.x = x + self.y = x + self.z = x + else + -- (a, b) -> (a, b, 0) + -- (a, b, c) -> (a, b, c) + self.x = x ?? 0 + self.y = y ?? 0 + self.z = z ?? 0 + end + end + + function __add(b) + if b instanceof Vector3 then + return new Vector3(self.x + b.x, self.y + b.y, self.z + b.z) + end + return new Vector3(self.x + b, self.y + b, self.z + b) + end + + function __sub(b) + if b instanceof Vector3 then + return new Vector3(self.x - b.x, self.y - b.y, self.z - b.z) + end + return new Vector3(self.x - b, self.y - b, self.z - b) + end + + function __mul(b) + if b instanceof Vector3 then + return new Vector3(self.x * b.x, self.y * b.y, self.z * b.z) + end + return new Vector3(self.x * b, self.y * b, self.z * b) + end + + function __div(b) + if b instanceof Vector3 then + return new Vector3(self.x / b.x, self.y / b.y, self.z / b.z) + end + return new Vector3(self.x / b, self.y / b, self.z / b) + end + + function __eq(b) + return self.x == b.x and self.y == b.y and self.z == b.z + end + + function __len() + return self:magnitude() + end + + function __tostring() + return $"Vector3({self.x}, {self.y}, {self.z})" + end + + function magnitude() + local accum = 0 + for self as axis do + accum += axis^2 + end + return math.sqrt(accum) + end + + function distance(b) + return (self - b):magnitude() + end + + function sum() + local accum = 0 + for self as axis do + accum += axis + end + return accum + end + + function min() + local min = math.huge + for self as axis do + if min > axis then + min = axis + end + end + return min + end + + function max() + local max = 0 + for self as axis do + if max < axis then + max = axis + end + end + return max + end + + function dot(b) + return (self * b):sum() + end + + function crossproduct(b) + return new Vector3( + self.y * b.z - self.z * b.y, + self.z * b.x - self.x * b.z, + self.x * b.y - self.y * b.x + ) + end + + function abs() + return new Vector3(math.abs(self.x), math.abs(self.y), math.abs(self.z)) + end + + function normalised() + return self / self:magnitude() + end + + function normalized() + return self / self:magnitude() + end + + function torot(up) + if up == "y" then + local yaw = math.deg(math.atan(self.x, self.z)) * -1 + local pitch = math.deg(math.asin(self.y / self:magnitude())) + return new Vector3( + math.isnan(pitch) ? 0 : pitch, + yaw, + 0 + ) + elseif up == "z" then + local yaw = math.deg(math.atan(self.x, self.y)) * -1 + local pitch = math.deg(math.asin(self.z / self:magnitude())) + return new Vector3( + math.isnan(pitch) ? 0 : pitch, + 0, + yaw + ) + else + error("Expected \"y\" or \"z\" for 'up' parameter") + end + end + + function lookat(up) + local dir = (b - self) + return dir:torot(up) + end + + function todir(up) + if up == "y" then + local yaw_radians = math.rad(self.z) + local pitch_radians = math.rad(self.x) * -1 + return new Vector3( + math.cos(pitch_radians) * math.sin(yaw_radians) * -1, + math.sin(pitch_radians) * -1, + math.cos(pitch_radians) * math.cos(yaw_radians) + ) + elseif up == "z" then + local yaw_radians = math.rad(self.z) + local pitch_radians = math.rad(self.x) * -1 + return new Vector3( + math.cos(pitch_radians) * math.sin(yaw_radians) * -1, + math.cos(pitch_radians) * math.cos(yaw_radians), + math.sin(pitch_radians) * -1 + ) + else + error("Expected \"y\" or \"z\" for 'up' parameter") + end + end +end + +setmetatable(Vector3, { + function __call(x, y, z) + return new Vector3(x, y, z) + end +}) + +return Vector3)EOC"; + luaL_loadbuffer(L, code, strlen(code), "pluto:assert"); + lua_call(L, 0, 1); + return 1; +} + +const Pluto::PreloadedLibrary Pluto::preloaded_Vector3{ "Vector3", funcs, &luaopen_Vector3 };