local function cubicBezier(t, p0, p1, p2, p3)
return (1 - t)^3*p0 + 3*(1 - t)^2*t*p1 + 3*(1 - t)*t^2*p2 + t^3*p3
end
local function createLUT(numSegments, ...)
local distSum = 0
local sums = {}
local step = 1/numSegments
for i = 0, 1, step do
local firstPoint = cubicBezier(i, ...)
local secondPoint = cubicBezier(i + step, ...)
local dist = (secondPoint - firstPoint).Magnitude
table.insert(sums, distSum)
distSum += dist
end
return sums
end
local function remap(n, oldMin, oldMax, min, max)
return (min + ((max-min) * ((n - oldMin) / (oldMax - oldMin))))
end
local Bezier = {}
Bezier.__index = Bezier
function Bezier.new(numSegments, p0, p1, p2, p3)
local self = setmetatable({}, Bezier)
self._points = {p0,p1,p2,p3}
self._distLUT = createLUT(numSegments, p0, p1, p2, p3)
return self
end
function Bezier:Calc(t)
local LUT = self._distLUT
local arcLength = LUT[#LUT]
local targetDist = arcLength * t
for i, dist in ipairs(LUT) do
local nextDist = LUT[i+1]
if targetDist >= dist and targetDist < nextDist then
local adjustedT = remap(targetDist, dist, nextDist, i/#LUT, (i+1)/#LUT)
return cubicBezier(adjustedT, unpack(self._points))
end
end
end
return Bezier
One way to achieve this is to calculate the distance between the current point and the target point using the Vector3.Magnitude
function, and then use this distance to modify the t
parameter passed to the cubicBezier
function. One possible approach is to define a variable that represents the maximum distance at which the camera should start slowing down, and then adjust the t
parameter based on the distance between the current point and the target point as follows:
function Bezier:Calc(t)
local LUT = self._distLUT
local arcLength = LUT[#LUT]
local targetDist = arcLength * t
local maxDist = 5 -- Adjust this value to control when the camera should start slowing down
for i, dist in ipairs(LUT) do
local nextDist = LUT[i+1]
if targetDist >= dist and targetDist < nextDist then
local adjustedT = remap(targetDist, dist, nextDist, i/#LUT, (i+1)/#LUT)
local currentPoint = cubicBezier(adjustedT, unpack(self._points))
local targetPoint = cubicBezier(math.min(adjustedT + 0.01, 1), unpack(self._points)) -- Adjust the second parameter (0.01) to control the speed of the slowdown
local distToTarget = (targetPoint - currentPoint).Magnitude
if distToTarget < maxDist then
local slowdownFactor = distToTarget / maxDist
adjustedT = adjustedT - slowdownFactor * (adjustedT - i/#LUT)
end
return cubicBezier(adjustedT, unpack(self._points))
end
end
end