--!native --!optimize 2 -- Compiled with roblox-ts v3.0.0 local TS = _G[script] local CFrameTools = TS.import(script, script.Parent, "cframe_tools").CFrameTools local Vector3Tools = TS.import(script, script.Parent, "vector3_tools").Vector3Tools local MatrixTools = TS.import(script, script.Parent, "matrix_tools").MatrixTools --TODO finish local SplineTools = {} do local _container = SplineTools local b_spline_matrix = MatrixTools.MultiplyScalarByNumber(1 / 6, { { 1, 4, 1, 0 }, { -3, 0, 3, 0 }, { 3, -6, 3, 0 }, { -1, 3, -3, 1 } }) local bezier_spline_matrix = { { 1, 0, 0, 0 }, { -3, 3, 0, 0 }, { 3, -6, 3, 0 }, { -1, 3, -3, 1 } } local catmull_rom_sline_matrix = MatrixTools.MultiplyScalarByNumber(1 / 2, { { 0, 2, 0, 0 }, { -1, 0, 1, 0 }, { 2, -5, 4, -1 }, { -1, 3, -3, 1 } }) local matrices = { [0] = b_spline_matrix, [1] = bezier_spline_matrix, [2] = catmull_rom_sline_matrix, } --TODO hermite spline --[[ * * @link https://www.youtube.com/watch?v=jvPPXbo87ds&ab_channel=FreyaHolm%C3%A9r ]] local function GetSpline(points, t, bezier_type) local points_matrix = { { points[1] }, { points[2] }, { points[3] }, { points[4] } } local numbers_matrix = matrices[bezier_type] local t_matrix = { { 1, t, t * t, t * t * t } } local bernstein_matrix = MatrixTools.MultiplyMatrices(t_matrix, numbers_matrix) local summ = MatrixTools.MultiplyNumberByVector3(bernstein_matrix, points_matrix) return summ[1][1] end _container.GetSpline = GetSpline local function GetSplineVector(points, t, bezier_type) local points_matrix = { { points[1] }, { points[2] }, { points[3] }, { points[4] } } local numbers_matrix = matrices[bezier_type] local t_matrix = { { 1, t, t * t, t * t * t } } local bernstein_matrix = MatrixTools.MultiplyMatrices(t_matrix, numbers_matrix) local summ = MatrixTools.MultiplyNumberByVector(bernstein_matrix, points_matrix) return summ[1][1] end _container.GetSplineVector = GetSplineVector local function GetSplineCFrame(points, t, bezier_type) local points_matrix = { { points[1] }, { points[2] }, { points[3] }, { points[4] } } local numbers_matrix = matrices[bezier_type] local t_matrix = { { 1, t, t * t, t * t * t } } local bernstein_matrix = MatrixTools.MultiplyMatrices(t_matrix, numbers_matrix) local summ = MatrixTools.MultiplyNumberByCFrame(bernstein_matrix, points_matrix) return summ[1][1] end _container.GetSplineCFrame = GetSplineCFrame --[[ * * used for the splines that dont start from the first point, extends the start and the end of the full path * @returns $tuple([point_0, point_1, point_2, point_3], local_t); ]] local function Get4PointsWithExtention(points, t) local size = #points local _arg0 = size > 1 assert(_arg0, "No enough points provided") --will break on 1; t = math.clamp(t, 0, 0.9999) local index_float = (size - 1) * t local local_t = index_float % 1 local index = math.floor(index_float) --reflects point 1 around start to get pre start point local point_0 = points[index] or Vector3Tools.Mirror(points[2], points[1]) local point_1 = points[index + 1] local point_2 = points[index + 2] --reflects pre last point around last to get extention at the end local point_3 = points[index + 3] or Vector3Tools.Mirror(points[size - 1], points[size]) return { point_0, point_1, point_2, point_3 }, local_t end --[[ * * used for the splines that dont start from the first point, extends the start and the end of the full path * @returns $tuple([point_0, point_1, point_2, point_3], local_t); ]] local function Get4PointsWithExtentionVector(points, t) local size = #points local _arg0 = size > 1 assert(_arg0, "No enough points provided") --will break on 1; t = math.clamp(t, 0, 0.9999) local index_float = (size - 1) * t local local_t = index_float % 1 local index = math.floor(index_float) --reflects point 1 around start to get pre start point local point_0 = points[index] or points[2]:MirrorAround(points[1]) local point_1 = points[index + 1] local point_2 = points[index + 2] --reflects pre last point around last to get extention at the end local point_3 = points[index + 3] or points[size - 1]:MirrorAround(points[size]) return { point_0, point_1, point_2, point_3 }, local_t end local MirrorPostionAround = CFrameTools.MirrorPositionAround --[[ * * used for the splines that dont start from the first point, extends the start and the end of the full path * @returns $tuple([point_0, point_1, point_2, point_3], local_t); ]] local function Get4PointsWithExtentionCFrame(points, t) local size = #points local _arg0 = size > 1 assert(_arg0, "No enough points provided") --will break on 1; t = math.clamp(t, 0, 0.9999) local index_float = (size - 1) * t local local_t = index_float % 1 local index = math.floor(index_float) --reflects point 1 around start to get pre start point local point_0 = points[index] or MirrorPostionAround(points[2], points[1], true) local point_1 = points[index + 1] local point_2 = points[index + 2] --reflects pre last point around last to get extention at the end local point_3 = points[index + 3] or MirrorPostionAround(points[size - 1], points[size], true) return { point_0, point_1, point_2, point_3 }, local_t end local function InterpolateBSpline(points, t) local control_points, local_t = Get4PointsWithExtention(points, t) return GetSpline(control_points, local_t, 0) end _container.InterpolateBSpline = InterpolateBSpline local function InterpolateBSplineVector(points, t) local control_points, local_t = Get4PointsWithExtentionVector(points, t) return GetSplineVector(control_points, local_t, 0) end _container.InterpolateBSplineVector = InterpolateBSplineVector local function InterpolateBSplineCFrame(points, t) local control_points, local_t = Get4PointsWithExtentionCFrame(points, t) return GetSplineCFrame(control_points, local_t, 0) end _container.InterpolateBSplineCFrame = InterpolateBSplineCFrame local function InterpolateCatmullRom(points, t) local control_points, local_t = Get4PointsWithExtention(points, t) return GetSpline(control_points, local_t, 2) end _container.InterpolateCatmullRom = InterpolateCatmullRom local function InterpolateCatmullRomVector(points, t) local control_points, local_t = Get4PointsWithExtentionVector(points, t) return GetSplineVector(control_points, local_t, 2) end _container.InterpolateCatmullRomVector = InterpolateCatmullRomVector end return { SplineTools = SplineTools, }