Please keep in mind, that the way that they are arranged can vary, and the amount of points / nodes that I have can also vary. What I’m trying to do is interpolate a part from point 1 all the way to the next point until it reaches the last point. I could use TweenService to tween that part from point one, to point two, and then from point two all the way to point three, and keep doing this until the last point, but that defeats the purpose of my question. I’m trying to figure out if it’s possible to somehow make some type of ‘multi-point interpolation’ where I can use a number between zero, and one, where zero means the part is at point 1, and if it’s one, it’s at the last point, but if it’s anywhere between, it’ll be somewhere between the first, and last point, but still following the path of nodes. If it’s possible to do this, does anyone have any idea how I could do this? It seems possible, but as soon as I try to visualize, or try to come up with any of the math, I’m pretty much lost.
Edit(s):
I kinda figured it out, but there is a little bug now.
local runService = game:GetService("RunService")
local totalLength = 0
local nodeIndex = 0
local lastNode = nil
while true do
nodeIndex += 1
local node = workspace:FindFirstChild("p"..nodeIndex)
if not node then break end
if node and lastNode then
totalLength += (node.Position - lastNode.Position).Magnitude
end
lastNode = node
end
local function lerp(y1, y2, mu)
return (y1*(1-mu)+y2*mu)
end
function interpolate(theta)
local originOffset = lerp(0, totalLength, theta)
local foundNodes = nil
local lastNode = nil
local currentDistance = 0
local nodeIndex = 0
while true do
nodeIndex += 1
local node = workspace:FindFirstChild("p"..nodeIndex)
if lastNode then
local newDist = currentDistance + (node.Position - lastNode.Position).Magnitude
if currentDistance < originOffset and newDist >= originOffset then
foundNodes = {firstNode = lastNode, secondNode = node, nextDist = newDist}
break
end
currentDistance += newDist
end
lastNode = node
end
local desiredDist = originOffset - currentDistance
local interDist = foundNodes.nextDist
local newTheta = desiredDist / interDist
local newCoord = foundNodes.firstNode.CFrame:Lerp(foundNodes.secondNode.CFrame, newTheta)--lerp(0, interDist, newTheta)
return newCoord
end
task.wait(5)
local howLongItShouldTake = 10
local theta = 0
repeat
local eT, dt = runService.Stepped:Wait() -- Lol, there is a movie called ET (eT actually means elapsedTime)
theta = math.min(1, theta + dt/howLongItShouldTake)
local newCoord = interpolate(theta)
workspace.ToInter.CFrame = newCoord
until theta == 1
I think you’re looking for Beizer curves. This kind of stuff is everywhere, and you can find an algorithm for it with some digging.
Otherwise, you’re probably looking for something similar to a NumberSequence, and the documentation has this function that lets you interpolate between multiple keyframes:
Ok, I managed to figure it out now. Here is the file, in case you want do figure out how I accomplished it: Interpolation.rbxl (35.3 KB)
There is a script inside of ServerScriptService, and that is the script that will have the “Multi-Node Interpolation”.
If anyone has anything else they want to say (Like if you found a bug, or maybe a much better way of doing it, or if you have something meaningful to contribute), please feel free to post it here. Also, don’t use the script in the edit of the main post, it still has the glitch (or bug) in it.
Edit: @SubtotalAnt8185 I actually only wanted a linear one, but thanks for helping. Also, don’t delete your reply, your script looks kinda interesting, and I might take a look at it later at some point, so I can learn how it works.
I’ve reviewed the script, and it will interpolate, but… it’s linear.
I’ve made a system in the past that interpolates without a linear algorithm to keep everything smooth.
function quadBezier(t, p0, p1, p2)
local l1 = p0:lerp(p1, t)
local l2 = p1:lerp(p2, t)
local quad = l1:lerp(l2, t)
return quad
end
local part = workspace.place
local tracksFolder = workspace.tracks
local tracks = tracksFolder:GetChildren()
local max = #tracks
--Name the tracks
for i, v in (tracks) do
if tonumber(v.Name) then continue end
local num = 1
for _, closest in (tracks) do
local dot = closest.CFrame.LookVector:Dot((v.Position - closest.Position).Unit)
if dot >= 0 and dot < 1 then
num+=1
end
end
v.Name = num
end
local speed = 100
while task.wait(5) do
--workspace.CurrentCamera.CameraType = Enum.CameraType.Scriptable
for index, _ in ipairs(tracks) do
local track = tracksFolder:FindFirstChild(index)
if not track then continue end
local lastTrack = tracksFolder:FindFirstChild(index-1) or track
local mag = (lastTrack.Position - track.Position).Magnitude
if part.CFrame.LookVector:Dot(track.Position - part.Position) < 0 then
continue
end
--local nextTrack = tracksFolder:FindFirstChild(index+1) or track
--local nextTrack2 = tracksFolder:FindFirstChild(index+2) or nextTrack
local origMag = mag
local t = 0
--print(index, lastTrack, track, nextTrack)
while t < 1 do
local dt = game:GetService("RunService").Heartbeat:Wait()
--local newcf = quadBezier(t, lastTrack.CFrame, track.CFrame, nextTrack.CFrame)
local newcf = lastTrack.CFrame:Lerp(track.CFrame, t)
local targetcf = newcf
local targetrot = Vector3.new(targetcf:ToOrientation())
local diffrot = targetrot - Vector3.new(part:GetPivot():ToOrientation())
part.AssemblyAngularVelocity = diffrot / dt / math.pi * 2
part.AssemblyLinearVelocity = (targetcf.Position - part.Position).Unit * speed
part:PivotTo(part:GetPivot():Lerp(targetcf * CFrame.new(0, 20, 0), dt * 10))
--part:PivotTo(targetcf)
--workspace.CurrentCamera.CFrame = part.CFrame * CFrame.new(0, 4, 0)
t+=dt/origMag*speed
end
--speed += 1
--part["Radio Engine Start 1 (SFX)"].PlaybackSpeed += .001
--part.track:Play()
--track.Transparency = 1
end
end
This is an automatic track ordering script that also uses Beizer curves as @Prototrode mentioned. It will also automatically order the tracks, so you don’t have to name them (it doesn’t do the best job though, but it works pretty well if you don’t have very tight curves).
also to you, bezier curves are a spline that is imprecise. (you cannot guarantee position of points).
If you wanted something like that I would use catmull rom splines or natural splines. Would curve tho not linear.