forked from Simnation/Main
532 lines
No EOL
14 KiB
Lua
532 lines
No EOL
14 KiB
Lua
LA = LA or {}
|
|
|
|
--https://easings.net
|
|
LA.Lerp = function(a, b, t)
|
|
return a + (b - a) * t
|
|
end
|
|
|
|
LA.LerpVector = function(a, b, t)
|
|
return vector3(LA.Lerp(a.x, b.x, t), LA.Lerp(a.y, b.y, t), LA.Lerp(a.z, b.z, t))
|
|
end
|
|
|
|
LA.EaseInSine = function(t)
|
|
return 1 - math.cos((t * math.pi) / 2)
|
|
end
|
|
|
|
LA.EaseOutSine = function(t)
|
|
return math.sin((t * math.pi) / 2)
|
|
end
|
|
|
|
LA.EaseInOutSine = function(t)
|
|
return -(math.cos(math.pi * t) - 1) / 2
|
|
end
|
|
|
|
LA.EaseInCubic = function(t)
|
|
return t ^ 3
|
|
end
|
|
|
|
LA.EaseOutCubic = function(t)
|
|
return 1 - (1 - t) ^ 3
|
|
end
|
|
|
|
LA.EaseInOutCubic = function(t)
|
|
return t < 0.5 and 4 * t ^ 3 or 1 - ((-2 * t + 2) ^ 3) / 2
|
|
end
|
|
|
|
LA.EaseInQuint = function(t)
|
|
return t ^ 5
|
|
end
|
|
|
|
LA.EaseOutQuint = function(t)
|
|
return 1 - (1 - t) ^ 5
|
|
end
|
|
|
|
LA.EaseInOutQuint = function(t)
|
|
return t < 0.5 and 16 * t ^ 5 or 1 - ((-2 * t + 2) ^ 5) / 2
|
|
end
|
|
|
|
LA.EaseInCirc = function(t)
|
|
return 1 - math.sqrt(1 - t ^ 2)
|
|
end
|
|
|
|
LA.EaseOutCirc = function(t)
|
|
return math.sqrt(1 - (t - 1) ^ 2)
|
|
end
|
|
|
|
LA.EaseInOutCirc = function(t)
|
|
return t < 0.5 and (1 - math.sqrt(1 - (2 * t) ^ 2)) / 2 or (math.sqrt(1 - (-2 * t + 2) ^ 2) + 1) / 2
|
|
end
|
|
|
|
LA.EaseInElastic = function(t)
|
|
return t == 0 and 0 or t == 1 and 1 or -2 ^ (10 * t - 10) * math.sin((t * 10 - 10.75) * (2 * math.pi) / 3)
|
|
end
|
|
|
|
LA.EaseOutElastic = function(t)
|
|
return t == 0 and 0 or t == 1 and 1 or 2 ^ (-10 * t) * math.sin((t * 10 - 0.75) * (2 * math.pi) / 3) + 1
|
|
end
|
|
|
|
LA.EaseInOutElastic = function(t)
|
|
return t == 0 and 0 or t == 1 and 1 or t < 0.5 and -(2 ^ (20 * t - 10) * math.sin((20 * t - 11.125) * (2 * math.pi) / 4.5)) / 2 or (2 ^ (-20 * t + 10) * math.sin((20 * t - 11.125) * (2 * math.pi) / 4.5)) / 2 + 1
|
|
end
|
|
|
|
LA.EaseInQuad = function(t)
|
|
return t ^ 2
|
|
end
|
|
|
|
LA.EaseOutQuad = function(t)
|
|
return 1 - (1 - t) ^ 2
|
|
end
|
|
|
|
LA.EaseInOutQuad = function(t)
|
|
return t < 0.5 and 2 * t ^ 2 or 1 - (-2 * t + 2) ^ 2 / 2
|
|
end
|
|
|
|
LA.EaseInQuart = function(t)
|
|
return t ^ 4
|
|
end
|
|
|
|
LA.EaseOutQuart = function(t)
|
|
return 1 - (1 - t) ^ 4
|
|
end
|
|
|
|
LA.EaseInOutQuart = function(t)
|
|
return t < 0.5 and 8 * t ^ 4 or 1 - ((-2 * t + 2) ^ 4) / 2
|
|
end
|
|
|
|
LA.EaseInExpo = function(t)
|
|
return t == 0 and 0 or 2 ^ (10 * t - 10)
|
|
end
|
|
|
|
LA.EaseOutExpo = function(t)
|
|
return t == 1 and 1 or 1 - 2 ^ (-10 * t)
|
|
end
|
|
|
|
LA.EaseInOutExpo = function(t)
|
|
return t == 0 and 0 or t == 1 and 1 or t < 0.5 and 2 ^ (20 * t - 10) / 2 or (2 - 2 ^ (-20 * t + 10)) / 2
|
|
end
|
|
|
|
LA.EaseInBack = function(t)
|
|
return 2.70158 * t ^ 3 - 1.70158 * t ^ 2
|
|
end
|
|
|
|
LA.EaseOutBack = function(t)
|
|
return 1 + 2.70158 * (t - 1) ^ 3 + 1.70158 * (t - 1) ^ 2
|
|
end
|
|
|
|
LA.EaseInOutBack = function(t)
|
|
return t < 0.5 and (2 * t) ^ 2 * ((1.70158 + 1) * 2 * t - 1.70158) / 2 or ((2 * t - 2) ^ 2 * ((1.70158 + 1) * (t * 2 - 2) + 1.70158) + 2) / 2
|
|
end
|
|
|
|
LA.EaseInBounce = function(t)
|
|
print(1 - LA.EaseOutBounce(1 - t))
|
|
return 1 - LA.EaseOutBounce(1 - t)
|
|
end
|
|
|
|
LA.EaseOutBounce = function(t)
|
|
if t < 1 / 2.75 then
|
|
return 7.5625 * t ^ 2
|
|
elseif t < 2 / 2.75 then
|
|
return 7.5625 * (t - 1.5 / 2.75) ^ 2 + 0.75
|
|
elseif t < 2.5 / 2.75 then
|
|
return 7.5625 * (t - 2.25 / 2.75) ^ 2 + 0.9375
|
|
else
|
|
return 7.5625 * (t - 2.625 / 2.75) ^ 2 + 0.984375
|
|
end
|
|
end
|
|
|
|
LA.EaseInOutBounce = function(t)
|
|
return t < 0.5 and (1 - LA.EaseOutBounce(1 - 2 * t)) / 2 or (1 + LA.EaseOutBounce(2 * t - 1)) / 2
|
|
end
|
|
|
|
LA.EaseIn = function(t, easingType)
|
|
easingType = string.lower(easingType)
|
|
if easingType == "linear" then
|
|
return t
|
|
elseif easingType == "sine" then
|
|
return LA.EaseInSine(t)
|
|
elseif easingType == "cubic" then
|
|
return LA.EaseInCubic(t)
|
|
elseif easingType == "quint" then
|
|
return LA.EaseInQuint(t)
|
|
elseif easingType == "circ" then
|
|
return LA.EaseInCirc(t)
|
|
elseif easingType == "elastic" then
|
|
return LA.EaseInElastic(t)
|
|
elseif easingType == "quad" then
|
|
return LA.EaseInQuad(t)
|
|
elseif easingType == "quart" then
|
|
return LA.EaseInQuart(t)
|
|
elseif easingType == "expo" then
|
|
return LA.EaseInExpo(t)
|
|
elseif easingType == "back" then
|
|
return LA.EaseInBack(t)
|
|
elseif easingType == "bounce" then
|
|
return LA.EaseInBounce(t)
|
|
end
|
|
end
|
|
|
|
LA.EaseOut = function(t, easingType)
|
|
easingType = string.lower(easingType)
|
|
if easingType == "linear" then
|
|
return t
|
|
elseif easingType == "sine" then
|
|
return LA.EaseOutSine(t)
|
|
elseif easingType == "cubic" then
|
|
return LA.EaseOutCubic(t)
|
|
elseif easingType == "quint" then
|
|
return LA.EaseOutQuint(t)
|
|
elseif easingType == "circ" then
|
|
return LA.EaseOutCirc(t)
|
|
elseif easingType == "elastic" then
|
|
return LA.EaseOutElastic(t)
|
|
elseif easingType == "quad" then
|
|
return LA.EaseOutQuad(t)
|
|
elseif easingType == "quart" then
|
|
return LA.EaseOutQuart(t)
|
|
elseif easingType == "expo" then
|
|
return LA.EaseOutExpo(t)
|
|
elseif easingType == "back" then
|
|
return LA.EaseOutBack(t)
|
|
elseif easingType == "bounce" then
|
|
return LA.EaseOutBounce(t)
|
|
end
|
|
end
|
|
|
|
LA.EaseInOut = function(t, easingType)
|
|
easingType = string.lower(easingType)
|
|
if easingType == "linear" then
|
|
return t
|
|
elseif easingType == "sine" then
|
|
return LA.EaseInOutSine(t)
|
|
elseif easingType == "cubic" then
|
|
return LA.EaseInOutCubic(t)
|
|
elseif easingType == "quint" then
|
|
return LA.EaseInOutQuint(t)
|
|
elseif easingType == "circ" then
|
|
return LA.EaseInOutCirc(t)
|
|
elseif easingType == "elastic" then
|
|
return LA.EaseInOutElastic(t)
|
|
elseif easingType == "quad" then
|
|
return LA.EaseInOutQuad(t)
|
|
elseif easingType == "quart" then
|
|
return LA.EaseInOutQuart(t)
|
|
elseif easingType == "expo" then
|
|
return LA.EaseInOutExpo(t)
|
|
elseif easingType == "back" then
|
|
return LA.EaseInOutBack(t)
|
|
elseif easingType == "bounce" then
|
|
return LA.EaseInOutBounce(t)
|
|
end
|
|
end
|
|
|
|
LA.EaseInVector = function(a, b, t, easingType)
|
|
local tEase = LA.EaseIn(t, easingType)
|
|
local x, y, z = a.x, a.y, a.z
|
|
local x2, y2, z2 = b.x, b.y, b.z
|
|
local x3, y3, z3 = x2 - x, y2 - y, z2 - z
|
|
local x4, y4, z4 = x3 * tEase, y3 * tEase, z3 * tEase
|
|
local x5, y5, z5 = x + x4, y + y4, z + z4
|
|
return vector3(x5, y5, z5)
|
|
end
|
|
|
|
LA.EaseOutVector = function(a, b, t, easingType)
|
|
local tEase = LA.EaseOut(t, easingType)
|
|
local x, y, z = a.x, a.y, a.z
|
|
local x2, y2, z2 = b.x, b.y, b.z
|
|
local x3, y3, z3 = x2 - x, y2 - y, z2 - z
|
|
local x4, y4, z4 = x3 * tEase, y3 * tEase, z3 * tEase
|
|
local x5, y5, z5 = x + x4, y + y4, z + z4
|
|
return vector3(x5, y5, z5)
|
|
end
|
|
|
|
LA.EaseInOutVector = function(a, b, t, easingType)
|
|
local tEase = LA.EaseInOut(t, easingType)
|
|
local x, y, z = a.x, a.y, a.z
|
|
local x2, y2, z2 = b.x, b.y, b.z
|
|
local x3, y3, z3 = x2 - x, y2 - y, z2 - z
|
|
local x4, y4, z4 = x3 * tEase, y3 * tEase, z3 * tEase
|
|
local x5, y5, z5 = x + x4, y + y4, z + z4
|
|
return vector3(x5, y5, z5)
|
|
end
|
|
|
|
LA.EaseVector = function(inout, a, b, t, easingType)
|
|
inout = string.lower(inout)
|
|
if inout == "in" then
|
|
return LA.EaseInVector(a, b, t, easingType)
|
|
elseif inout == "out" then
|
|
return LA.EaseOutVector(a, b, t, easingType)
|
|
elseif inout == "inout" then
|
|
return LA.EaseInOutVector(a, b, t, easingType)
|
|
end
|
|
assert(false, "Invalid type")
|
|
end
|
|
|
|
LA.EaseOnAxis = function(inout, a, b, t, easingType, axis)
|
|
axis = axis or vector3(0, 0, 0)
|
|
local x, y, z = a.x, a.y, a.z
|
|
local increment = 0
|
|
if inout == "in" then
|
|
increment = LA.EaseIn(t, easingType)
|
|
elseif inout == "out" then
|
|
increment = LA.EaseOut(t, easingType)
|
|
elseif inout == "inout" then
|
|
increment = LA.EaseInOut(t, easingType)
|
|
end
|
|
return axis * increment
|
|
end
|
|
|
|
LA.TestCheck = function(point1, point2)
|
|
local dx = point1.x - point2.x
|
|
local dy = point1.y - point2.y
|
|
local dz = point1.z - point2.z
|
|
return math.sqrt(dx*dx + dy*dy + dz*dz)
|
|
end
|
|
|
|
LA.BoxZoneCheck = function(point, lower, upper)
|
|
local x1, y1, z1 = lower.x, lower.y, lower.z
|
|
local x2, y2, z2 = upper.x, upper.y, upper.z
|
|
return point.x > x1 and point.x < x2 and point.y > y1 and point.y < y2 and point.z > z1 and point.z < z2
|
|
end
|
|
|
|
LA.DistanceCheck = function(pointA, pointB)
|
|
return #(pointA - pointB) < 0.5
|
|
end
|
|
|
|
LA.Chance = function(chance)
|
|
assert(chance, "Chance must be passed")
|
|
assert(type(chance) == "number", "Chance must be a number")
|
|
assert(chance >= 0 and chance <= 100, "Chance must be between 0 and 100")
|
|
return math.random(1, 100) <= chance
|
|
end
|
|
|
|
LA.Vector4To3 = function(vector4)
|
|
assert(vector4, "Vector4 must be passed")
|
|
assert(type(vector4) == "vector4", "Vector4 must be a vector4")
|
|
return vector3(vector4.x, vector4.y, vector4.z), vector4.w
|
|
end
|
|
|
|
LA.Dot = function(vectorA, vectorB)
|
|
return vectorA.x * vectorB.x + vectorA.y * vectorB.y + vectorA.z * vectorB.z
|
|
end
|
|
|
|
LA.Length = function(vector)
|
|
return math.sqrt(vector.x * vector.x + vector.y * vector.y + vector.z * vector.z)
|
|
end
|
|
|
|
LA.Normalize = function(vector)
|
|
local length = LA.Length(vector)
|
|
return vector3(vector.x / length, vector.y / length, vector.z / length)
|
|
end
|
|
|
|
LA.Create2DRotationMatrix = function(angle) -- angle in radians
|
|
local c = math.cos(angle)
|
|
local s = math.sin(angle)
|
|
return {
|
|
c, -s, 0, 0,
|
|
s, c, 0, 0,
|
|
0, 0, 1, 0,
|
|
0, 0, 0, 1,
|
|
}
|
|
end
|
|
|
|
LA.Create3DAxisRotationMatrix = function(vector)
|
|
local yaw = vector.z
|
|
local pitch = vector.x
|
|
local roll = vector.y
|
|
|
|
local cy = math.cos(yaw)
|
|
local sy = math.sin(yaw)
|
|
local cp = math.cos(pitch)
|
|
local sp = math.sin(pitch)
|
|
local cr = math.cos(roll)
|
|
local sr = math.sin(roll)
|
|
|
|
local matrix = {
|
|
vector3(cp * cy, cp * sy, -sp),
|
|
vector3(cy * sp * sr - cr * sy, sy * sp * sr + cr * cy, cp * sr),
|
|
vector3(cy * sp * cr + sr * sy, cr * cy * sp - sr * sy, cp * cr)
|
|
}
|
|
|
|
return matrix
|
|
end
|
|
|
|
LA.Circle = function(t, radius, center)
|
|
local x = radius * math.cos(t) + center.x
|
|
local y = radius * math.sin(t) + center.y
|
|
return vector3(x, y, center.z)
|
|
end
|
|
|
|
LA.Clamp = function(value, min, max)
|
|
return math.min(math.max(value, min), max)
|
|
end
|
|
|
|
LA.CrossProduct = function(a, b)
|
|
local x = a.y * b.z - a.z * b.y
|
|
local y = a.z * b.x - a.x * b.z
|
|
local z = a.x * b.y - a.y * b.x
|
|
return vector3(x, y, z)
|
|
end
|
|
|
|
LA.CreateTranslateMatrix = function(x, y, z)
|
|
return {
|
|
1, 0, 0, x,
|
|
0, 1, 0, y,
|
|
0, 0, 1, z,
|
|
0, 0, 0, 1,
|
|
}
|
|
end
|
|
|
|
LA.MultiplyMatrix = function(m1, m2)
|
|
local result = {}
|
|
for i = 1, 4 do
|
|
for j = 1, 4 do
|
|
local sum = 0
|
|
for k = 1, 4 do
|
|
sum = sum + m1[(i - 1) * 4 + k] * m2[(k - 1) * 4 + j]
|
|
end
|
|
result[(i - 1) * 4 + j] = sum
|
|
end
|
|
end
|
|
return result
|
|
end
|
|
|
|
LA.MultiplyMatrixByVector = function(m, v)
|
|
local result = {}
|
|
for i = 1, 4 do
|
|
local sum = 0
|
|
for j = 1, 4 do
|
|
sum = sum + m[(i - 1) * 4 + j] * v[j]
|
|
end
|
|
result[i] = sum
|
|
end
|
|
return result
|
|
end
|
|
|
|
--Slines
|
|
LA.SplineLerp = function(nodes, start, endPos, t)
|
|
-- Ensure t is clamped between 0 and 1
|
|
t = LA.Clamp(t, 0, 1)
|
|
|
|
-- Find the two closest nodes around t
|
|
local prevNode, nextNode = nil, nil
|
|
for i = 1, #nodes - 1 do
|
|
if nodes[i].time <= t and nodes[i + 1].time >= t then
|
|
prevNode, nextNode = nodes[i], nodes[i + 1]
|
|
break
|
|
end
|
|
end
|
|
|
|
-- Edge cases: If t is before or after the defined range
|
|
if not prevNode then return start end
|
|
if not nextNode then return endPos end
|
|
|
|
-- Normalize t within the segment
|
|
local segmentT = (t - prevNode.time) / (nextNode.time - prevNode.time)
|
|
|
|
-- Interpolate the value (y-axis)
|
|
local smoothedT = LA.Lerp(prevNode.value, nextNode.value, segmentT)
|
|
|
|
-- Perform final Lerp using the interpolated smoothing factor
|
|
return LA.Lerp(start, endPos, smoothedT)
|
|
end
|
|
|
|
LA.SplineSmooth = function(nodes, points, t)
|
|
-- Ensure valid input
|
|
if #points < 2 then return points end
|
|
t = LA.Clamp(t, 0, 1)
|
|
|
|
local smoothedPoints = {}
|
|
|
|
for i = 1, #points - 1 do
|
|
local smoothedPos = LA.SplineLerp(nodes, points[i], points[i + 1], t)
|
|
table.insert(smoothedPoints, smoothedPos)
|
|
end
|
|
|
|
-- Ensure last point remains unchanged
|
|
table.insert(smoothedPoints, points[#points])
|
|
|
|
return smoothedPoints
|
|
end
|
|
|
|
LA.Spline = function(points, resolution)
|
|
-- Ensure valid input
|
|
if #points < 2 then return points end
|
|
|
|
-- Create a list of nodes
|
|
local nodes = {}
|
|
for i = 1, #points do
|
|
table.insert(nodes, { time = i / (#points - 1), value = i })
|
|
end
|
|
|
|
-- Smooth the points
|
|
local smoothedPoints = {}
|
|
for i = 0, 1, resolution do
|
|
local smoothedPos = LA.SplineSmooth(nodes, points, i)
|
|
table.insert(smoothedPoints, smoothedPos)
|
|
end
|
|
|
|
return smoothedPoints
|
|
end
|
|
|
|
LA.SplineCatmullRom = function(points, resolution)
|
|
-- Ensure valid input
|
|
if #points < 4 then return points end
|
|
|
|
-- Create a list of nodes
|
|
local nodes = {}
|
|
for i = 1, #points do
|
|
table.insert(nodes, { time = i / (#points - 1), value = i })
|
|
end
|
|
|
|
-- Smooth the points
|
|
local smoothedPoints = {}
|
|
for i = 0, 1, resolution do
|
|
local smoothedPos = LA.SplineSmooth(nodes, points, i)
|
|
table.insert(smoothedPoints, smoothedPos)
|
|
end
|
|
|
|
return smoothedPoints
|
|
end
|
|
|
|
exports('LA', LA)
|
|
return LA
|
|
|
|
-- local easingTypes = {
|
|
-- "linear",
|
|
-- "sine",
|
|
-- "cubic",
|
|
-- "quint",
|
|
-- "circ",
|
|
-- "elastic",
|
|
-- "quad",
|
|
-- "quart",
|
|
-- "expo",
|
|
-- "back",
|
|
-- "bounce"
|
|
-- }
|
|
|
|
--local inout = {
|
|
-- "in",
|
|
-- "out",
|
|
-- "inout"
|
|
--}
|
|
|
|
|
|
-- LA.LerpAngle = function(a, b, t)
|
|
-- local num = math.abs(b - a) % 360
|
|
-- local num2 = 360 - num
|
|
-- if num < num2 then
|
|
-- return a + num * t
|
|
-- else
|
|
-- return a - num2 * t
|
|
-- end
|
|
-- end
|
|
|
|
-- LA.LerpVectorAngle = function(a, b, t)
|
|
-- local x, y, z = a.x, a.y, a.z
|
|
-- local x2, y2, z2 = b.x, b.y, b.z
|
|
-- local x3, y3, z3 = LA.LerpAngle(x, x2, t), LA.LerpAngle(y, y2, t), LA.LerpAngle(z, z2, t)
|
|
-- return vector3(x3, y3, z3)
|
|
-- end
|
|
|
|
-- return LA |