Need help understanding Bezier Curves

damn it, this might be my fault, I think it’s the way I worded it.

by “closest point” I don’t mean the point that is closest to the i’th point. forget about the original curve for a second, just think in distances.

you need the closest distance that is <= target. noticed how I put the distances and vectors in the same little tables. each distance has a corresponding point, and that’s the one you’re looking for.

in your second loop don’t iterate the points, iterate by t like you did in the first one, use it to find the target, then get the matching point using that.

I did iterate with t in the 2nd who though

ok… might need to start from the top. first off, in the second loop that I wrote, you need points[#points+1] = {…}. forgot the +1. otherwise it’s overwriting the same thing every time.

second, you can scratch the inner for loop. target is already total * t. use that.

But isnt that why we have the starter one?

I think im just gonna start from fresh, after the

yeah, that’s to fall back on when using previous. by the end it should be n+1 points long. to that end, you can start t at 0.01 instead of 0 or it will get added twice. right now it just ends with one point added.

that’s fair. by the way, I could send you the whole code right now if it’s getting frustrating. just wanted to help you understand it :slight_smile:

Send me the code and ill ask about any questions i have

Im just bad with tables and dictionaries and stuff of that sort so

sure, sure. I’m afraid I can’t send it now as it’s late, will get it back to you tomorrow morning. keep trying if you can.

All good im also going to bed so ill see your tomorrow, i cant express how thankful i am for your help.

function lerp(p0, p1, t)
    return p0 + t * (p1 - p0)
end

local points = {}
points[1] = {
    ["Position"] = Vector3.new(), -- starting point
    ["Distance"] = 0
}

for t = 0.01, 1, 0.01 do
    local position = bezierPoint(t, ...) -- get unweighted position
    local previous = points[#points] 
    local gap = (position - previous.Position).Magnitude
    local distance = previous.Distance + gap

    -- store the vector3 as position, total distance as distance
    -- and distance from the previous point as gap
    points[#points+1] = {
        ["Position"] = position,
        ["Distance"] = distance,
        ["Gap"] = gap
    }
end

-- total curve length
local length = points[#points].Distance
local bezier = {}

for t = 0.01, 1, 0.01 do
    local target = length * t

    -- find the first point that is >= target and the one before it
    -- that means the target length is in between these two points
    local p0, p1
    for i, point in pairs(points) do
        if point.Distance >= target then
            p0 = points[i-1]
            p1 = point
            break
        end
    end

    bezier[#bezier+1] = lerp(
        p0.Position,
        p1.Position,
        (target - p0.Distance) / p1.Gap
    )
end

return bezier

note, I stored p1.Distance - p0.Distance as "Gap" so it doesn’t have to calculate twice. I also didn’t use binary search to keep it simple. haven’t tested, ask me about any problems.

1 Like

Sorry for the delay, so how do I know when to use each bezier point? it just returns them all in 1 table right?

yeah. if you want, instead of storing them in a table you can put a part there or something.

also FYI, it doesn’t include the first point. did that on purpose so you can chain them, if you want to add the first point then change it to t=0 for the second loop.

i changed the t thing but it does this for some reason it does this: https://i.gyazo.com/aba6882287af761868706e4f84808a31.gif

what’s the issue? is it because it stops early before reaching the top right square?

it looks like the spacing works, at least.

That and it begins at 0,0,0 for some reason

at the first part when you do points[1]=… change Vector3.new() to the starting point.

edit: looks like an error on my part. you need to change points[#points] to points[1]!