Trace a curve which pass through all of the points.

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Pordrack
Prole
Posts: 13
Joined: Tue Sep 04, 2018 5:23 pm

Trace a curve which pass through all of the points.

Hi ! I'm currently coding a game where the player swing using a rope, using love.physics as the physics engine, the rope is made with rectangles jointed together thanks to RevoluteJoint , to render the rope graphically, I wanted to use Bezier Curved, to have a smooth rope , instead of rectangles, so I give all the anchor points to the bezier curve and render it, but I noticed that it doesn't use all the points, it takes some shortcut.

raidho36
Party member
Posts: 2063
Joined: Mon Jun 17, 2013 12:00 pm

Re: Trace a curve which pass through all of the points.

That's how bezier curves work, yes. It doesn't look far off to me so you can just keep it that way.

TheHUG
Citizen
Posts: 59
Joined: Sun Apr 01, 2018 4:21 pm

Re: Trace a curve which pass through all of the points.

Whatever my girlfriend's svg editing software used for it's curves ( which it did call bezier) does pass through all the points, so I was also surprised by this.

I spent some time looking for this, and I didn't find anything. I think you'll need to come up with it yourself. I was thinking of doing it myself but haven't gotten around to it and probably won't for a while.

I expect it'd be some pretty tough math though, and if it's just for rendering then raidho is right - it still looks pretty good.

Pordrack
Prole
Posts: 13
Joined: Tue Sep 04, 2018 5:23 pm

Re: Trace a curve which pass through all of the points.

The problem is, it can sometime pass through walls because of that.
Last edited by Pordrack on Sat Jul 20, 2019 11:04 am, edited 2 times in total.

grump
Party member
Posts: 645
Joined: Sat Jul 22, 2017 7:43 pm

Re: Trace a curve which pass through all of the points.

Use Catmull-Rom instead of Bezier splines.

raidho36
Party member
Posts: 2063
Joined: Mon Jun 17, 2013 12:00 pm

Re: Trace a curve which pass through all of the points.

You can try using centers of bodies as end points and joints as control points.

Pordrack
Prole
Posts: 13
Joined: Tue Sep 04, 2018 5:23 pm

Re: Trace a curve which pass through all of the points.

I did that, and yes, it's better, not perfect, but good enough for me.

unixfreak
Citizen
Posts: 79
Joined: Thu Oct 15, 2015 6:25 am
Location: Bristol, UK
Contact:

Re: Trace a curve which pass through all of the points.

Not sure if this is any use, but a while back i was trying to understand the use of moving an object along a bezier curve (typically a rocket/missile), this example that someone fixed for me may be useful in plotting the points along the curve:

https://love2d.org/forums/viewtopic.php ... 10#p211910

May be some other relevant info in that thread also.

pgimeno
Party member
Posts: 2335
Joined: Sun Oct 18, 2015 2:58 pm

Re: Trace a curve which pass through all of the points.

One method to do what the OP wants with LÖVE is the Kochanek-Bartels method. It works by drawing one Hermite curve between each pair of points.

While the method generates Hermite curves, these can easily be converted to Bézier for them to be drawn with LÖVE. You can adjust tension to the desired value, and leave continuity and bias set to 0. In my experience, a bit of negative tension works better than zero tension (which would produce a Catmull-Rom spline).

To convert a start Hermite vector to the first control point of a cubic Bézier, divide it by 3 and add the start point. To convert an end Hermite vector to the second point of a cubic Bézier, divide it by -3 and add the end point.

For example, if the Hermite curve is given by start and end points p0 and p1, and tangents d0 and d1, the corresponding Bézier control points P0, P1, P2, P3 (where P0 and P3 are the starting and ending point, and P1 and P2 are the control points) are:

P0 = p0
P1 = p0 + d0 / 3
P2 = p1 - d1 / 3
P3 = p1

Edit: Sorry, I previously said "multiply by 3". I misremembered, it should have been "divide by 3".

Edit 2: Simple example follows:

Code: Select all

local bez = love.math.newBezierCurve(0,0, 0,0, 0,0, 0,0)

local function Kochanek_Bartels(t, c, b,
p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y)
local P0x = p1x
local P0y = p1y
local P1x = p1x + (  (1-t)*(1+b)*(1+c) * (p1x - p0x)
+ (1-t)*(1-b)*(1-c) * (p2x - p1x) ) / 6
local P1y = p1y + (  (1-t)*(1+b)*(1+c) * (p1y - p0y)
+ (1-t)*(1-b)*(1-c) * (p2y - p1y) ) / 6
local P2x = p2x - (  (1-t)*(1+b)*(1-c) * (p2x - p1x)
+ (1-t)*(1-b)*(1+c) * (p3x - p2x) ) / 6
local P2y = p2y - (  (1-t)*(1+b)*(1-c) * (p2y - p1y)
+ (1-t)*(1-b)*(1+c) * (p3y - p2y) ) / 6
local P3x = p2x
local P3y = p2y
bez:setControlPoint(1, P0x, P0y)
bez:setControlPoint(2, P1x, P1y)
bez:setControlPoint(3, P2x, P2y)
bez:setControlPoint(4, P3x, P3y)
love.graphics.line(bez:render())
end

local points = {0, 0, 200, 0, -200, -150, -250, 120, 300, 250}

local tension = -0.6
local continuity = 0
local bias = 0

function love.draw()
love.graphics.translate(love.graphics.getWidth()/2, love.graphics.getHeight()/2)

-- Draw dots
love.graphics.setColor(1, 1, 1, 1)
for i = 1, #points, 2 do
love.graphics.circle("fill", points[i], points[i + 1], 5)
end

love.graphics.setColor(0, 0.3, 1, 1)
local len = #points
local npoints = len / 2
if npoints >= 3 then
-- do first segment by repeating first point
Kochanek_Bartels(tension, continuity, bias,
points[1], points[2], points[1], points[2],
points[3], points[4], points[5], points[6])
-- do middle segments
for i = 2, npoints - 2 do
local base = i * 2 - 1
Kochanek_Bartels(tension, continuity, bias,
points[base - 2], points[base - 1],
points[base], points[base + 1],
points[base + 2], points[base + 3],
points[base + 4], points[base + 5])
end
-- do last segment by repeating last point
Kochanek_Bartels(tension, continuity, bias,
points[len - 5], points[len - 4], points[len - 3], points[len - 2],
points[len - 1], points[len], points[len - 1], points[len])
elseif npoints == 2 then
-- just draw a line between the points
love.graphics.line(points)
end
end

function love.keypressed(k) return k == "escape" and love.event.quit() end

Snapshot:
Attachments
KochanekBartels.png (12.06 KiB) Viewed 2123 times

Who is online

Users browsing this forum: No registered users and 37 guests