diff --git a/res/modules/vectors.lua b/res/modules/vectors.lua index bc989054..5687ccd2 100644 --- a/res/modules/vectors.lua +++ b/res/modules/vectors.lua @@ -7,8 +7,12 @@ vector3.__index = vector3 vec2 = function(x, y) return vector2:new(x, y) end vec3 = function(x, y, z) return vector3:new(x, y, z) end - +-- vec2 cocnrtuct function vector2:new(x, y) + if type(x) ~= "number" or type(y) ~= "number" then + error("Invalid input argument. Expected two numbers. [ vec2(number, number) ]") + end + local obj = { x = x or 0, y = y or 0 @@ -17,11 +21,19 @@ function vector2:new(x, y) return obj end --- str vec +-- string vec function vector2:strvec2() return "(" .. self.x .. ", " .. self.y .. ")" end +-- round vector components +function vector2:round(decimals) + decimals = decimals or 0 + self.x = math.floor(self.x * 10^decimals + 0.5) / 10^decimals + self.y = math.floor(self.y * 10^decimals + 0.5) / 10^decimals + return self +end + -- magnitude (length) vec function vector2:len() return math.sqrt(self.x * self.x + self.y * self.y) @@ -29,8 +41,59 @@ end -- normalize vector function vector2:norm() - local length_vectors = self:len() - return vector2:new(self.x / length_vectors, self.y / length_vectors) + local length_vectors = self:len() + return vector2:new(self.x / length_vectors, self.y / length_vectors) +end + +-- dot product +function vector2:dot(v) + if type(v) == "number" then + error("Invalid input argument. Expected a vector2 object") + end + return self.x * v.x + self.y * v.y +end + +-- linear interpolation +function vector2:lerp(b, t) + if type(b) ~= "vector2" then + error("Invalid input argument. Expected a vector2 object") + end + if type(t) ~= "number" or t < 0 or t > 1 then + error("Invalid input argument. Expected a number between 0 and 1") + end + return vector2:new(self.x + t * (b.x - self.x), self.y + t * (b.y - self.y)); +end + +-- rot vec2 +-- @param angle -> float (radians) +-- @param axis -> string || nil .. if nil => rot axis z +-- @param convert2deg -> bool .. if true => deg2rad +-- @return vec2 +function vector2:rot(angle, axis, convert2deg) + if convert2deg == true then + angle = math.rad(angle) + end + + if type(axis) == "string" then + if axis == "x" then + local x_new = self.x + local y_new = self.y * math.cos(angle) - self.y * math.sin(angle) + self.y = y_new + elseif axis == "y" then + local x_new = self.x * math.cos(angle) + self.x * math.sin(angle) + local y_new = self.y + self.x = x_new + elseif axis == "z" then + local x_new = self.x * math.cos(angle) - self.y * math.sin(angle) + local y_new = self.x * math.sin(angle) + self.y * math.cos(angle) + self.x, self.y = x_new, y_new + end + elseif axis == nil then + local x_new = self.x * math.cos(angle) - self.y * math.sin(angle) + local y_new = self.x * math.sin(angle) + self.y * math.cos(angle) + self.x, self.y = x_new, y_new + end + return self:round(15) end -- add vec @@ -131,6 +194,11 @@ function vector3:new(x, y, z) setmetatable(obj, self) return obj end + +-- str vec +function vector3:strvec3() + return "(" .. self.x .. ", " .. self.y .. ", " .. self.z .. ")" +end -- dot product function vector3:dot(v) @@ -163,22 +231,15 @@ function vector3:round(decimals) return self end - -- check if two vectors are parallel + +-- check if two vectors are parallel function vector3:is_parallel(v) if type(v) ~= "vector3" then - error("Invalid input argument. Expected a vector3 object.") + error("Invalid input argument. Expected a vector3 object.") end return self:cross(v):len() < 1e-6 end - --- string vec -function vector3:strvec3() - return "(" .. self.x .. ", " .. self.y .. ", " .. self.z .. ")" -end - - - -- magnitude (length) vec function vector3:len() return math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z) @@ -188,11 +249,61 @@ end -- normalize vector function vector3:norm() - local length_vectors = self:len() - return vector3:new(self.x / length_vectors, self.y / length_vectors, self.z / length_vectors) + local length_vectors = self:len() + return vector3:new(self.x / length_vectors, self.y / length_vectors, self.z / length_vectors) end +-- linear interpolation (lerp) for vector3 +function vector3:lerp(b, t) + if type(b) ~= "vector3" then + error("Invalid input argument. Expected a vector3 object") + end + if type(t) ~= "number" or t < 0 or t > 1 then + error("Invalid input argument. Expected a number between 0 and 1") + end + return vector3:new(self.x + t * (b.x - self.x), self.y + t * (b.y - self.y), self.z + t * (b.z - self.z)); +end + + +-- rot vec3 +-- @param angle -> float +-- @param axis -> string || nil .. if nil => rot axis z +-- @param convert2deg -> bool || nil .. if true => deg2rad +-- @return vec3 +function vector3:rot(angle, axis, convert2deg) + if convert2deg == true then + angle = math.rad(angle) + end + + if type(axis) == "string" then + local cx, sx = math.cos(angle), math.sin(angle) + if axis == "x" then + local x, y, z = self.x, self.y, self.z + self.y = cx * y - sx * z + self.z = sx * y + cx * z + elseif axis == "y" then + local x, y, z = self.x, self.y, self.z + self.x = cx * x + sx * z + self.z = -sx * x + cx * z + elseif axis == "z" then + local x, y, z = self.x, self.y, self.z + self.x = cx * x - sx * y + self.y = sx * x + cx * y + end + elseif axis == nil then + local cosx, sx, cy, sy = math.cos(angle), math.sin(angle), math.cos(angle), math.sin(angle) + local x, y, z = self.x, self.y, self.z + self.x = cx * x - sx * y + self.y = sx * x + cx * y + self.z = cy * z - sy * self:len() + local len = self:len() + if len ~= 0 then + self.z = self.z / len + end + end + return self:round(15) +end -- add vec @@ -331,7 +442,3 @@ end function vector3.__tostring(vcrt3) return vcrt3:strvec3() end - - - -