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 };