MonoGame.SplineFlower - Create wonderful smooth Bézier-, CatMulRom- and Hermite-Splines!

It’s there:

https://github.com/sqrMin1/MonoGame.SplineFlower/tree/master/Utils

Great, thank you a lot:

But how do I reference it?

I would presume that it was included in the Monogame.SplineFlower.dll…

That, I don’t know, I am not that far with tinkering right now…

I will take a look at this soon. Currently pretty busy.

1 Like

The problem should be fixed now. Please install the newest nuget package(s).

https://www.nuget.org/packages/MonoGame.SplineFlower/
https://www.nuget.org/packages/MonoGame.SplineFlower.Content/
https://www.nuget.org/packages/MonoGame.SplineFlower.Content.Pipeline/

1 Like

2.0.0 :champagne: - Complete Overhaul + Hermite Splines!

Breaking Changes: this update is not compatible with older versions of this library!

  • Added the missing “AddCurveRight” override in the HermiteSpline class.
  • Initial setup initialization in all sample controls.
  • Added a new PolygonTextureTest spline and texture called “RaceTrack.json” (CatMulRomSpline) and “roadTexture.png” (Texture2D).
  • Added more possibilities of showing or hiding specific elements of a spline (Lines, Points).
  • The selected tangent text is now drawn directly inside the HermiteSplineControl instead as a forms label.
  • The game project now includes spline json data generated with the revised MonoGame.SplineFlower library update. It defaults to the HermiteSpline test now and loads it as an xnb file with the ContentManger to show that it can handle the latest additions and changes to the library and the pipeline.
  • Updated the samples project to work with the new MonoGame.SplineFlower update.
  • Based on the revised library update the MonoGame.SplineFlower.Content.Pipeline library now reflects the latest changes and additions.
  • New spline type: HermiteSpline! (basically a CatMulRomSpline but with “Bias” & “Tension” parameters as well as moveable Tangents, which gives more precise control over the curve of this spline.
  • Complelty revised the MonoGame.SplineFlower library and gave it more structure and encapsulation, which makes it way easier now to understand and use the library as well as adding new spline types.
  • Updated AssemblyInfo
  • Solution upgraded to support Visual Studio 2019

Heyya, here is finally the update I wanted to do for a longer time now: it’s nothing less than a complete overhaul of the library.

It should be easier now to understand and use it. Unfortunatley this makes it incompatible with older versions. Espacially your generated splines will not likely to load.

However, adding new spline types is now a breeze. That’s why a new spline type is already included with this update; the Hermite Spline!

Let’s take a look:

The Hermite Spline is basically a CatMulRom Spline, but you have more control over it by setting “bias” and “tension” values. On top of it there a moveable tangents (the orange handles in the animation), which makes it possible to control the curve more precisely.

And this is what gives you design and typography powers now. Look at this:

Things like that are created in minutes. Try it for yourself with the included samples and editor project!

I also reworked the PolygonSpline sample a bit, by adding a new road texture and some checkboxes to enable or disable specific visual elements of the spline:

BTW: the MonoGame ContentManager is fully supported!

Load a spline simply like this:
MySpline = Content.Load<SplineBase>(@"HermiteTest");

Nugets are fully generated and uploaded for the ease of integration!


Phew… now I have this library in a state I always wanted it to be. It is ready for further production in other projects. This is incredible if you think about the fact that this library exists since Aug 14, 2018.

But it is definitley worth the time.

My intention is to implement the MonoGame.SplineFlower library into the Mercury Particle Sandbox:

… and let thousands of particles flow on the splines.

Feel free to click on the link above to find out more about my particle sandbox!

And feel free to follow the further development process of my projects here in MonoGame or via steam dev, steam news, twitter, indiedb or even youtube.

Thank you very much for your support and have a nice day! :sun_with_face:

:: Marcel :heart:

2 Likes

Updated the repo according to the new law in germany, which sais that the symbolic usage of the letter “Z” is forbidden now, because of the war in ukraine, triggered by Wladimir Putin.

Here is the repo link:

Here is a before/after comparison for your imagination:

Here is the mini-changelog:

  • Removed the write baseline in the image to avoid misunderstandings with the forbidden “Z” symbol.
  • Added the animated HermiteSpline.gif image to the gitignore list to avoid misunderstandings with the forbidden “Z” symbol.
  • Updated the Readme.md file to avoid misunderstandings with the forbidden “Z” symbol.

Notes:

  • The core functionallity of the library is still the same, which means that for example the default generation of a spline with the command MySpline.Reset() still generates a white baseline which looks like a “Z”. This is to visualize the specific technical curve of the corresponding spline and has nothing to do with a symbolic usage.

  • This repo/library exists since 14.08.2018 - long time before anyone could ever think about that a simple letter like “Z” could be a symbol of war like the “swatiska”.

Explanation:

I’m doing these changes mainly on the public frontsite of my github repo page to avoid conflicts with the law. I am not doing this because I’m paranoid, I’m doing this because alot of other people are paranoid these days. And yeah… It’s valid law now in germany and you can get in jail for 3 years or getting financial penalties when using the letter “Z” now…

I wish I could say this is a joke, but it isn’t.

Other than that I wish you a peacful day. And let’s hope together that this nightmare will end soon and that we all can live in peace and harmony again.

Cheers!

:: Marcel :heart:

:rainbow_flag: :sun_with_face:

PS: I’m also planning a new update with new functionalities for this library - soon more.

PPS: I hope I made clear that I am against war of any kind. I am not supporting Putin or the war - of course not!

1 Like

2.1.0 - :chains: Chain Splines! :chains:

Chain Spline

ADDED:

  • Added a new ChainSplineControl to the project.
  • Points of a spline are now calculating their neighbours (Left & Right).
  • It’s possible to translate a specific Transform now instead of all or just the selected one.
  • Added a recursive chain-logic to enable the dynamic movement of control points (Transforms) of a spline, based on user input like mouse movement.
  • The chain translation of Transforms can now happen in the inverse direction, which affects the direct neighbours of the corresponding Transform (middle point).
  • Added EndPointColor and EndPointThickness to the Setup class.
    – Also changed the StartPointColor from Magenta to White.
    – The EndPointColor is Black, so the user can easily determine if such a specific point is the start or the end of a spline.

CHANGED:

  • Changed the display text of the PolygonSplineControl to PolygonSpline.
  • Changed internal Transform.Translate() to public. This gives more fine control over Transforms - espacially useful to programmatically control the tangents of a HermiteSpline (NOTE: Will be reverted in the next update and exchanged with an overridable virtual function)
  • The difference between TranslatePointFirstClick and current mouse location is now stored as “Acceleration” inside a spline. This is useful in ChainSplines.
  • The index of a Point is now set when a Transform/Tangent/Point is beeing created instead of in the draw loop.
  • Updated AssemblyInfo, LicenseYear and TwitterLink.
  • Adjusted PointColor and PointThickness, so that it is more homogeneous.
  • Simplified the drawing of a spline, by moving the calculations of the angle and distances between points to the DrawPoint()and DrawLine() methods.
  • Removed the Tank-SplineWalker from the project and added an advanced version of the Car-SplineWalker instead.
  • A spline gets drawn with Spline.Draw() now instead of Spline.DrawSpline().

FIXED:

  • Fixed a bug with “Transform.Size” beeing wrong after translation.

Performance Test:

i3-9100F CPU @ 3.60GHz | GTX 1050 Ti

Notes:

When the selected Point (center) of a Spline is moving, then his direct neighbours (left & right) will check their distances to him.

  • If the distance is bigger than a certain value, the specific neighbour will move into the direction of the Point.
  • If the distance is lower than a certain value, the specific neighbour will move into the inverse direction of the Point.

Now that the neighbours are moving, the neighbours of those neighbours are checking for distances. This is a recursive operation as you can see and it’s happening for the whole spline every frame in the game loop (update). On top of it there is a distance and angle calculation in the draw method of a spline - also happening each frame, which draws the actual spline; the curve (yellow), the direction vectors (green), the tangents (orange) the base line (white) and the points (usually red) - at least if you want to show them all.

The most demanding operation is of course to draw the curve, because each segment (4 connected points) has roughly 300 yellow dots. In the last performance test of the video you see 100921 sprites (curve + points + base line + center point). The generated spline contains 304 points, so 300 dots * 304 points = 91200 sprites at the default spline resolution of 1000 - just for the yellow curve.

Angle and distance calculations are happening on every single dot right now, so my plan in a future update of the library is to only calculating those values on demand and maybe storing them in an array. I can also imagine to have custom fixed recalculation intervals on the spline, so that for example such calculations only happening 1, 10, 33 times per frame (and/or on demand) - adjustable by the user; either per spline or per project (setup class). Another thing is to use a sprite sheet for the textures. It’s just a square and a circle but reducing texture swaps should always be the aim. On top of it this is an easy addition, so it’s a must have.

The question you are probably asking right now is: “why do you even care about such big splines? o.O”

This leads me to the next topic…

Future Features of MonoGame.SplineFlower:

I want to extend this library with bigger (and more impressive) features. One of them is the ability of creating branches!

It should be possible to select a point on the curve and then just create a branch on that point. From this branch-connection it should be possible to connect other splines. And on such connected splines it should be possible to … right, create even more branches! :slight_smile:

This can lead to HUGE spline-networks. And now imagine you would move points on that network in a recursive way using this “Chain-Spline-Technology”… YES, now we are talking. :rofl:

You see? Performance is an important factor and big splines are a very great way of testing different performance scenarios - on the way to the branch-feature in one of the next updates.

Keep curious and stay tuned! :wink:

Have a nice day! :sparkling_heart:

:: Marcel

PS: Sorry for the wall of text :stuck_out_tongue:

3 Likes

2.2.0 - :chains: Chain Spline Performance Boost! :chains:

ADDED:

  • InitializeSplineControlSample() added so that corresponding SplineSampleControls are getting correctly re-initialized after tab page switches.
  • Added TangentColor to better seperate it from the rest of the spline colors.
  • The solution now supports Visual Studio 2022.

CHANGED:

  • It’s now possible to add a float factor value to the Add/Substract Tension and Bias functions of the HermiteSpline type.
  • Changed the default spline generation function “Reset()” to form a “C” symbol instead of a “Z” symbol now by default.
  • The HermiteSplineControl sample now shows more possibilites of creating a custom HermiteSpline using Tension, Bias and modifying Tangents just by code (programmatically).
  • Only Rotate, Scale and ScaleRotate if the value is not 0.
  • Calling SetSplineMarkerResolution() also updates the SplineStepDistance from now on, which gives a huge performance boost when drawing curves of splines.
  • Applied modifications to the ChainSplineControl project to enable performance tests in the ChainSplineControl.
  • CenterSplineColor is now Magenta for better visibility.
  • Updated the MonoGame version of all projects.
  • Updated nuspec files and nuget packages.

FIXED:

  • FindNearestPoint fixed end of spline wasn’t detected correctly - by adding a small value to the MaxProgress() function.

Performance Test 2/2:

i3-9100F CPU @ 3.60GHz | GTX 1050 Ti

The old performance test from my last post showed that the maximum limit of sprites to draw a curve of a spline was about 100.000, which usually resulted in having roughly 300 control points (red squares) on the spline. This however, was because of the fact, that such a spline would have a resolution of 1000. This means maximum quality and ultra smooth curves - of the costs of performance of course… huge costs :wink:

I’m now using a formula which bounds the spline resolution to a value called “SplineStepDistance”.
I calculate it like this:

SplineStepDistance = SplineMarkerResolution / (float)Math.Pow(SplineMarkerResolution, 2) * 3f;

The draw function of the spline now uses this value to raise “t” along all control points, like this:

for (float t = 0; t < _Points.Length; t += Setup.SplineStepDistance)

So, the lower the SplineResolution, the higher the SplineStepDistance, the shorter the for loop, the faster the draw function… :smiley: (much faster).

This interpolates the curve like this:

sp_resolution_00
From low resolution to high resolution.

As a result the new limits are much more impressive. We are going from ~300 control points for ~100.000 sprites to ~9000[!] control points for ~50.000[!] sprites. This means we can have 30x more control points, but only using half of the sprites as before. Surprisingly the curve is still looking pretty much smooth.

But why?

Well, the answer is simply: because the distance between each control point is very short, which makes the curve generation naturally smoother. I am using this little trick to boost the performance immensely without taking away to much quality.

In fact this boosted the performance that much, that we would rather get a stack overflow exception from the recursive operations of the chain spline control points, than a FPS-drop…
On the other hand it would be interesting to experiment with shaders to push some work to the GPU. Espacially when it comes to calculate angle and distances. But at this point this would only raise the quality of a spline, because we could set a higher spline resolution then. The FPS are already stable.

And this is the reason for me to go further in developing new features for MonoGame.SplineFlower like the complex “branching system”.

I hope you enjoyed the performance video and this update in general.

Keep curious and stay tuned! :wink:

Have a nice day :sparkling_heart: