Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

AppGameKit Classic Chat / [T1 & T2] Open Bezier Curve Library

Author
Message
Clonkex
Forum Vice President
13
Years of Service
User Offline
Joined: 20th May 2010
Location: Northern Tablelands, NSW, Australia
Posted: 20th Mar 2014 11:57 Edited at: 11th Apr 2014 10:30
Hi all,

I spent some time working on some functions for calculating bezier curves for my current project and I thought I'd share

I tried to take a screenshot but printscreen doesn't work with AGK. I'll try FRAPS later. Done:





Basically this code lets you specify a set of points and then calculate where a point would be along a curve using those points to guide it.

EDIT: Currently the closed curves aren't working as expected. Give me half an hour and they should be fixed.
Done. Both kinds of curve now work perfectly

Currently the library is tier 1 only, but I need to convert it to tier 2 for my project, so rest assured you will soon have an identical T2 version
Done! You now have a C++ tier 2 version in the download

Features:
- Fast bezier curve calculation
- Open and closed curves
- Easily find closest point on curve
- Can divide curve into arbitrary number of segments for line drawing
- Floating point precision for sub-pixel alignment
- Both Tier 1 and Tier 2 support

Changes:
[20/03/14] 1.0 - Public release
[21/03/14] 1.1 - Fixed closed curves (so they actually work and all that)
[22/03/14] 1.11 - Tiny eency little fix (forgot to change an X to a Y)
[22/03/14] 1.2 - Fixed some floats not being floats and wrote the C++ version of the library
[11/04/14] 1.21 - Fixed some bugs in the C++ version related to for-loops

Download:
Version 1.0 - 20/03/14 - Obsolete
Version 1.1 - 21/03/14 - Obsolete
Version 1.11 - 22/03/14 - Obsolete
Version 1.2 - 22/03/14 - Obsolete
Version 1.21 - 11/04/14 - Current

Attachments

Login to view attachments
Phaelax
DBPro Master
21
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 20th Mar 2014 16:37
Instead of fraps, try bandicam.

So would I be able to trace around this curve at a constant speed?

Clonkex
Forum Vice President
13
Years of Service
User Offline
Joined: 20th May 2010
Location: Northern Tablelands, NSW, Australia
Posted: 21st Mar 2014 00:25 Edited at: 21st Mar 2014 00:27
Quote: "Instead of fraps, try bandicam."


Will do

Quote: "So would I be able to trace around this curve at a constant speed?"


Not currently. Using a linear increase of the input value, the speed of the result would increase on straights and decrease on corners. However, I will look into providing a way to trace linearly around the curve

Phaelax
DBPro Master
21
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 21st Mar 2014 01:10
That would be awesome if you get that part working. I tried before but never got very far.

I think I have a possible solution in my head at the moment, but the pre-calculations necessary wouldn't be very efficient if the path changed dynamically.

Phaelax
DBPro Master
21
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 21st Mar 2014 03:37
Haha, solved it! Didn't make any changes to the library, I put all necessary code into the main source.

To draw the bezier curve, you make many small line segments. Starting from the beginning of the curve, I add the distance of each line segment together, recording the overall distance that each point lies from the start. Also, store the total length of the curve.

Then, take that total distance and your step value (whatever you want the time index to be between 0 and 1) to calculate how far you are along the curve. Now that we know how far we are, we can look up which line segment we currently fall on.

Determine the length of that line segment by subtracting its value(the precalculated values we did) from the value of the next point ahead. Then calculate how far along this single segment we actually are by subtracting that points value (its distance from the start of the curve, not its length) from the overall distance we are at on the curve.

Divide those two values to get a new time value for that line segment. I've explained each line in the code comments which might be easier to understand.





Satchmo
18
Years of Service
User Offline
Joined: 29th May 2005
Location:
Posted: 21st Mar 2014 04:24
What can bezier curves be used for? Genuinely curious I've never used them in any programming before.

Phaelax
DBPro Master
21
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 21st Mar 2014 07:39
Making curved paths!

Clonkex
Forum Vice President
13
Years of Service
User Offline
Joined: 20th May 2010
Location: Northern Tablelands, NSW, Australia
Posted: 21st Mar 2014 14:26
Quote: "Then, take that total distance and your step value (whatever you want the time index to be between 0 and 1) to calculate how far you are along the curve. Now that we know how far we are, we can look up which line segment we currently fall on."


After literally several hours' research, I can tell you that is definitely the way to do it I was hoping for a simple formula to calculate it more easily (and faster), but alas, it is not possible One day I will probably implement your system more directly into my code and make it easier to use, but for now, you have your system and I don't need it

Quote: "What can bezier curves be used for? Genuinely curious I've never used them in any programming before."


They can be used for anything that needs a curve; drawing curvy lines immediately leaps to mind Practically speaking, though, they can be used to calculate "the racing line in a racing game, or the line in line-drawing games such as Flight Control, or the looping butterfly that enlivens an RPG" (awesome bezier curve tutorial).

Quote: "Making curved paths!"


This.

I've also updated the code (well, I will have in a few minutes) with a teency little minor bug (I forgot to change an X to a Y in one of my copy-paste marathons).

Clonkex
Forum Vice President
13
Years of Service
User Offline
Joined: 20th May 2010
Location: Northern Tablelands, NSW, Australia
Posted: 22nd Mar 2014 05:55
Update: Fixed a couple more bugs and converted the code to C++, so the tier 2 version is now available in the zip on the first post!

Please freely report any bugs you find

Clonkex
Forum Vice President
13
Years of Service
User Offline
Joined: 20th May 2010
Location: Northern Tablelands, NSW, Australia
Posted: 6th Apr 2014 01:51
Unashamed bump Just to ensure it doesn't get locked any time soon

Clonkex
Forum Vice President
13
Years of Service
User Offline
Joined: 20th May 2010
Location: Northern Tablelands, NSW, Australia
Posted: 11th Apr 2014 10:29
Update!

For those of you using the C++ version, if you've been having troubles, this may help you. Turns out I'm an idiot and didn't think about how for-loops work in C++ compared to BASIC; long story short, I fixed it and the download's in the first post.

Changes:
[11/04/14] 1.21 - Fixed some bugs in the C++ version related to for-loops

Phaelax
DBPro Master
21
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 12th Apr 2014 08:22
Quote: "didn't think about how for-loops work in C++ compared to BASIC"


Start at 0 and not 1?

Clonkex
Forum Vice President
13
Years of Service
User Offline
Joined: 20th May 2010
Location: Northern Tablelands, NSW, Australia
Posted: 12th Apr 2014 18:04
Quote: "Start at 0 and not 1?"


Haha no, I'm not THAT noob Plus...in that respect, C++ and BASIC are identical; neither HAS to start at 1 or 0, just depends how you set up the arrays. No, it was the fact that in BASIC you would do this:



...which I converted thusly:



...but in BASIC, the conditional part expects 'i' to EQUAL 'somethingCount-1', not be less than, so half the stuff failed miserably until I discovered my error. I suppose I could have changed the '<' to a '==', but I prefer to use '<' so I just removed the '-1'. Although in retrospect it would actually have been easier and less error-prone to just change it to a '=='.

Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 12th Apr 2014 20:54
The correct C version of the Basic is:
Quote: "
for(int i=0;i<=somethingCount-1;i++)
{
//do stuff
}
"


The 'i<=somethingCount-1' means to do the loop as long as 'i' is less than or equal to 'somethingCount-1'.

You can get the same results by just using 'i<somethingCount' and it would remove the extra math operation (subtracting 1).

If you had used 'i==somethingCount-1', then your loop would fail immediately unless somethingCount happend to be 1.

Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master
Clonkex
Forum Vice President
13
Years of Service
User Offline
Joined: 20th May 2010
Location: Northern Tablelands, NSW, Australia
Posted: 13th Apr 2014 08:17
Quote: "The 'i<=somethingCount-1' means to do the loop as long as 'i' is less than or equal to 'somethingCount-1'."


Ah, yes of course, duh. THAT'S what the BASIC code does, it uses '<='. Thanks, I'm an idiot to not think of that

Quote: "The 'i<=somethingCount-1' means to do the loop as long as 'i' is less than or equal to 'somethingCount-1'."


I know

Quote: "You can get the same results by just using 'i<somethingCount' and it would remove the extra math operation (subtracting 1)."


I know, and that's what I did initially, but the problem is that if the BASIC for-loop was 'i<somethingCount' already, then when I convert it to C++ then I would have to do 'i<somethingCount+1' to make it work. Kinda dumb, so for those cases I used '=='.

Also, I would never worry about the extra maths operation as doing so is micro-optimisation, which is mostly pointless except in rare circumstances.

Quote: "If you had used 'i==somethingCount-1', then your loop would fail immediately unless somethingCount happend to be 1."


Hey, I was tired when I wrote that I think I was thinking that condition was the condition to END the block, not start it.

In conclusion: When converting BASIC...



...to C++, do this:



That guarantees identical behaviour between the two languages.

Clonkex
Forum Vice President
13
Years of Service
User Offline
Joined: 20th May 2010
Location: Northern Tablelands, NSW, Australia
Posted: 5th May 2014 19:22 Edited at: 5th May 2014 19:23
Anti-lock bump; I would like to add things to this thread in future.

Jambo B
14
Years of Service
User Offline
Joined: 17th Sep 2009
Location: The Pit
Posted: 24th Jul 2014 16:47
Clonkex - thank you so much... this is an excellent library which has saved me loads of time. I love it!

Thanks again,

James
Clonkex
Forum Vice President
13
Years of Service
User Offline
Joined: 20th May 2010
Location: Northern Tablelands, NSW, Australia
Guido Italy
18
Years of Service
User Offline
Joined: 25th Dec 2005
Location:
Posted: 25th Jul 2014 13:25
Thanks from me too !
xGEKKOx
AGK Master
15
Years of Service
User Offline
Joined: 7th Dec 2008
Location: Italy
Posted: 25th Jul 2014 20:23
The right way is :


Long life to Steve!
Clonkex
Forum Vice President
13
Years of Service
User Offline
Joined: 20th May 2010
Location: Northern Tablelands, NSW, Australia
Posted: 26th Jul 2014 05:36
Quote: "Thanks from me too !"


You're welcome!

Quote: "The right way is :"


Both ways are "right". If I had been writing a program from scratch in C++, I would have used the more obvious way you suggested, but since I was converting the code from AppGameKit to C++, I had to use a method that would cause the least bugs. Some parts of the AppGameKit code were like this:



...and some were like this:



To convert to C++ your way would mean they become:



...and:



That, quite frankly, is more confusing and more difficult to spot than this:



...and:



I'm sure there's a tiny speed difference, but it would be extremely small. Other than that, it's a matter of personal preference.

Guido Italy
18
Years of Service
User Offline
Joined: 25th Dec 2005
Location:
Posted: 26th Jul 2014 14:48
Ciao,

please ,
can you write code to draw lines and curves as in Paint.net ?

( with "Open Bezier Curve Library" )

Thank
xGEKKOx
AGK Master
15
Years of Service
User Offline
Joined: 7th Dec 2008
Location: Italy
Posted: 27th Jul 2014 02:45
Ah yes of course, i mean, is right because you don't see the -1, so you know is < of that number.
Who code in c++ usually do < so maybe can think to < number -1 if he read fast.
That's the reason is right <.


Long life to Steve!
Guido Italy
18
Years of Service
User Offline
Joined: 25th Dec 2005
Location:
Posted: 27th Jul 2014 14:02
anyone help me? ( Please ! )
Clonkex
Forum Vice President
13
Years of Service
User Offline
Joined: 20th May 2010
Location: Northern Tablelands, NSW, Australia
Posted: 28th Jul 2014 04:13
Quote: "anyone help me? ( Please ! )"


Gotta be patient, man, I was out all of yesterday

Quote: "please ,
can you write code to draw lines and curves as in Paint.net ?

( with "Open Bezier Curve Library" )"


Ok, so I would suggest that my curve library is not ideal for this task, and neither is AppGameKit (at least, V1) with its limited drawing functionality. The problem is that all you can do with my library is specify the points, and it works out the tangent handles for you. You can't manually specify the tangent handles, which means you can't draw a straight line if there's more than two points.

So let me suggest that you find a different way to achieve your goal.

Guido Italy
18
Years of Service
User Offline
Joined: 25th Dec 2005
Location:
Posted: 28th Jul 2014 09:21
Sorry !!

Thank !
Guido Italy
18
Years of Service
User Offline
Joined: 25th Dec 2005
Location:
Posted: 4th Aug 2014 00:10
... any news ?
Clonkex
Forum Vice President
13
Years of Service
User Offline
Joined: 20th May 2010
Location: Northern Tablelands, NSW, Australia
Posted: 4th Aug 2014 14:38
Quote: "... any news ?"


About what? I realise something may be lost in the translation to Italian (in fact I just tried Google Translating from English to Italian and back again, and it was worded such that I was saying the exact opposite), so let me try to make it clear:

My code is not good for what you want. Sorry.

Guido Italy
18
Years of Service
User Offline
Joined: 25th Dec 2005
Location:
Posted: 4th Aug 2014 15:36
hops... sorry for my bad translate !!!

And you ( or other people ) can not help me ? (please )
Clonkex
Forum Vice President
13
Years of Service
User Offline
Joined: 20th May 2010
Location: Northern Tablelands, NSW, Australia
Posted: 4th Aug 2014 16:21
Quote: "hops... sorry for my bad translate !!!

And you ( or other people ) can not help me ? (please )"


No, I cannot help you. You should make a new thread on this forum somewhere rather than post on this thread. Then someone might be able to help you.

Clonkex
Forum Vice President
13
Years of Service
User Offline
Joined: 20th May 2010
Location: Northern Tablelands, NSW, Australia
Posted: 19th Aug 2014 12:31
So yes, I AM going to spam most of the threads I have created recently with a message:

VOTE FOR RTA! The voting is down the bottom of the page and does not require a login.

Rush To Adventure is an awesome retro Zelda-style 2D platformer made with AppGameKit that's already doing really well on Android mobile devices and Ouya. It's created by Digital Awakening, who has put a huge amount of work into this game; it's well worth checking out and VOTING FOR. Go. Now. Vote for RTA!

Login to post a reply

Server time is: 2024-04-20 05:03:40
Your offset time is: 2024-04-20 05:03:40