better Vector3 coercion semantics
This commit is contained in:
parent
4900c50850
commit
40c9af4803
@ -27,6 +27,25 @@ local function is_weak_vector3(t)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---Coerces t to a Vector3. If t is already a Vector3, returns it without copying.
|
||||||
|
---@param t vectorlike
|
||||||
|
---@param do_err boolean?
|
||||||
|
---@param def Vector3?
|
||||||
|
---@return boolean error, Vector3 result
|
||||||
|
local function coerce(t, do_err, def)
|
||||||
|
do_err = do_err or true
|
||||||
|
if do_err and not is_weak_vector3(t) then
|
||||||
|
def = def or Vector3()
|
||||||
|
error("Vector3: can not coerce t into Vector3. Returning " .. tostring(def))
|
||||||
|
return true, def
|
||||||
|
end
|
||||||
|
if t["_CLASS_"] == "Vector3" then
|
||||||
|
return false, t
|
||||||
|
end
|
||||||
|
|
||||||
|
return false, Vector3(t)
|
||||||
|
end
|
||||||
|
|
||||||
---Returns a Vector3 multiplied either component-wise (if b is a weak Vector3) or multiplies each component by b if b is a number.
|
---Returns a Vector3 multiplied either component-wise (if b is a weak Vector3) or multiplies each component by b if b is a number.
|
||||||
---@param b number|vectorlike
|
---@param b number|vectorlike
|
||||||
---@return Vector3
|
---@return Vector3
|
||||||
@ -167,12 +186,11 @@ end
|
|||||||
---@param with vectorlike
|
---@param with vectorlike
|
||||||
---@return number
|
---@return number
|
||||||
function Vector3:dot(with)
|
function Vector3:dot(with)
|
||||||
if not is_weak_vector3(with) then
|
local err, v2 = coerce(with)
|
||||||
error("Vector3: with must be a Vector3-like table. Returning 0")
|
if err then
|
||||||
return 0
|
return 0.0
|
||||||
end
|
end
|
||||||
|
|
||||||
local v2 = Vector3(with)
|
|
||||||
return self.x * v2.x + self.y * v2.y + self.z * v2.z
|
return self.x * v2.x + self.y * v2.y + self.z * v2.z
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -180,11 +198,10 @@ end
|
|||||||
---@param with vectorlike
|
---@param with vectorlike
|
||||||
---@return Vector3
|
---@return Vector3
|
||||||
function Vector3:cross(with)
|
function Vector3:cross(with)
|
||||||
if not is_weak_vector3(with) then
|
local err, v2 = coerce(with)
|
||||||
error("Vector3: with must be a Vector3-like table. Returning Vector3()")
|
if err then
|
||||||
return Vector3()
|
return v2
|
||||||
end
|
end
|
||||||
local v2 = Vector3(with)
|
|
||||||
return Vector3 {
|
return Vector3 {
|
||||||
self.y * v2.z - self.z * v2.y,
|
self.y * v2.z - self.z * v2.y,
|
||||||
self.z * v2.x - self.x * v2.z,
|
self.z * v2.x - self.x * v2.z,
|
||||||
@ -197,17 +214,22 @@ end
|
|||||||
---@param angle number
|
---@param angle number
|
||||||
---@return Vector3
|
---@return Vector3
|
||||||
function Vector3:rotated(axis, angle)
|
function Vector3:rotated(axis, angle)
|
||||||
if not is_weak_vector3(axis) then
|
-- if not is_weak_vector3(axis) then
|
||||||
error("Vector3: axis must be a Vector3-like table. Returning Vector3()")
|
-- error("Vector3: axis must be a Vector3-like table. Returning Vector3()")
|
||||||
return Vector3()
|
-- return Vector3()
|
||||||
|
-- end
|
||||||
|
local err, vaxis = coerce(axis)
|
||||||
|
if err then
|
||||||
|
return vaxis
|
||||||
end
|
end
|
||||||
|
|
||||||
axis = Vector3(axis):normalized()
|
---@diagnostic disable-next-line: undefined-field
|
||||||
|
vaxis = vaxis:normalized()
|
||||||
local cosa = math.cos(angle)
|
local cosa = math.cos(angle)
|
||||||
local sina = math.sin(angle)
|
local sina = math.sin(angle)
|
||||||
-- __mul is only defined for the left operand (table), numbers don't get metatables.
|
-- __mul is only defined for the left operand (table), numbers don't get metatables.
|
||||||
-- as such, the ordering of operations here is specific
|
-- as such, the ordering of operations here is specific
|
||||||
local v = (self * cosa) + (axis * ((1 - cosa) * self:dot(axis))) + (axis:cross(self) * sina)
|
local v = (self * cosa) + (vaxis * ((1 - cosa) * self:dot(vaxis))) + (vaxis:cross(self) * sina)
|
||||||
return Vector3(v)
|
return Vector3(v)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -222,12 +244,11 @@ end
|
|||||||
---@param t number
|
---@param t number
|
||||||
---@return Vector3
|
---@return Vector3
|
||||||
function Vector3:lerp(b, t)
|
function Vector3:lerp(b, t)
|
||||||
-- return self:copy()
|
local err, w = coerce(b)
|
||||||
if not is_weak_vector3(b) then
|
if err then
|
||||||
error("Vector3: b must be a Vector3-like table. Returning copy of self.")
|
return w
|
||||||
return self:copy()
|
|
||||||
end
|
end
|
||||||
local w = Vector3(b)
|
|
||||||
return Vector3{
|
return Vector3{
|
||||||
util.lerp(self.x, w.x, t),
|
util.lerp(self.x, w.x, t),
|
||||||
util.lerp(self.y, w.y, t),
|
util.lerp(self.y, w.y, t),
|
||||||
@ -235,6 +256,44 @@ function Vector3:lerp(b, t)
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Vector3:direction_to(to)
|
||||||
|
local err, other = coerce(to)
|
||||||
|
if err then
|
||||||
|
return 0.0
|
||||||
|
end
|
||||||
|
|
||||||
|
return Vector3(other.x - self.x, other.y - self.y, other.z - self.z):normalized()
|
||||||
|
end
|
||||||
|
|
||||||
|
---Returns the squared distance between this vector and to.
|
||||||
|
---@param to vectorlike
|
||||||
|
---@return number
|
||||||
|
function Vector3:distance_squared_to(to)
|
||||||
|
local err, other = coerce(to)
|
||||||
|
if err then
|
||||||
|
return 0.0
|
||||||
|
end
|
||||||
|
|
||||||
|
return (other - self):length_squared()
|
||||||
|
end
|
||||||
|
|
||||||
|
---Returns the distance between this vector and to.
|
||||||
|
---@param to vectorlike
|
||||||
|
---@return number
|
||||||
|
function Vector3:distance_to(to)
|
||||||
|
local err, other = coerce(to)
|
||||||
|
if err then
|
||||||
|
return 0.0
|
||||||
|
end
|
||||||
|
|
||||||
|
return (other - self):length()
|
||||||
|
end
|
||||||
|
|
||||||
|
---Returns a new vector with the Y discarded (0).
|
||||||
|
---@return Vector3
|
||||||
|
function Vector3:horizontal()
|
||||||
|
return Vector3(self.x, 0.0, self.z)
|
||||||
|
end
|
||||||
---- CONSTANTS
|
---- CONSTANTS
|
||||||
|
|
||||||
Vector3.UP = Vector3(0, 1, 0)
|
Vector3.UP = Vector3(0, 1, 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user