Add Spline primitive

Avatar
  • updated
  • Under Consideration

We already have PolyLine, but is better to have spline.

Interpolated  if possible.

Reporting a bug? please specify Unity version:
Reporting a bug? please specify Shapes version:
Reporting a bug? please specify Render Pipeline:
Duplicates 2
Add Bezier mode to Polyline

Polyline works great. I love the mesh constructions in different modes. This is great! But in regular use-cases we need to work with Bezier curve. Of course, we can make a Bezier curve generator on top of Polyline, it will work. But not all of us know how to do that. Because bezier is math. People buying the Shapes plugin just for that reason - to not work with math directly or save time. In both cases creating your own Bezier implementation is not right.


People asking you - how did you build the curve. That is the point.

Image 410



My proposition - to add Bezier mode to Polyline. Or if it does not work architecturally, it would be a dedicated component called "Curve" or "Bezier" or even "Bezier Curve". That will be really great. Of course please don't forget to add a property for customizing amount of intermediate (smooth) points.

With love!

Curved polylines and polyshapes request - bezier curve or rounded control between points

Hiya
I'd like to make the request to have, curves or arcs any control to create rounded or seemingly rounded shapes perhaps via bezier curves or able to set the radius between points. I'm sure you know what I'm on about.

Avatar
Freya Holmér creator
  • Under Consideration

This is something I need to think about a little more

currently, this is the only thing immediate mode supports that the components don't, and I feel like this should work similar in components as it does in polylines

in other words - it should also support the ArcTo functions, in addition to the bezier splines you were requesting

Avatar
byron tik

In case you havn't seen this maybe this cornershape solution, it may have relevance? 
https://github.com/cukiakimani/jelly-platforms/ 

Avatar

Hi, I'm really need the splines too. How did the curved 3d-line was drawn, one on the asset-shop screenshots?

Avatar
Freya Holmér creator

At the moment, you're best off drawing them in immediate mode, where there are multiple ways of drawing it. The easiest is to use a billboarded polyline, but if you need a true volumetric 3D line you'll need to stitch together several 3D lines. Here's an example script that does both! Add this script to an object in your scene. You can check the polyline box in the inspector to toggle between polyline path vs 3D line path



using Shapes;
using UnityEngine;

public class BezierDraw : MonoBehaviour {

public Vector3 a = new Vector3( 0, 0, 0 );
public Vector3 b = new Vector3( -2, 1, 1 );
public Vector3 c = new Vector3( 2, 1, 3 );
public Vector3 d = new Vector3( 0, 0, 4 );
public float lineThickness = 0.05f;
public bool polyline = false;
public int pointCount = 48;

void OnDrawGizmos() {
if( polyline ) { // Drawing using billboard polylines
Draw.PolylineGeometry = PolylineGeometry.Billboard;
using( var path = new PolylinePath() ) {
path.AddPoint( a );
path.BezierTo( b, c, d, pointCount );
Draw.Polyline( path, lineThickness, PolylineJoins.Simple );
}
} else { // Drawing using 3D lines
Draw.LineGeometry = LineGeometry.Volumetric3D;
Vector3[] pts = new Vector3[pointCount];
for( int i = 0; i < pointCount; i++ )
pts[i] = GetBezierPt( a, b, c, d, i / ( pointCount - 1f ) );
for( int i = 0; i < pointCount - 1; i++ )
Draw.Line( pts[i], pts[i + 1], lineThickness, LineEndCap.Round );
}
}

static Vector3 GetBezierPt( Vector3 a, Vector3 b, Vector3 c, Vector3 d, float t ) {
float omt = 1f - t;
float omt2 = omt * omt;
return a * ( omt2 * omt ) + b * ( 3f * omt2 * t ) + c * ( 3f * omt * t * t ) + d * ( t * t * t );
}

}
Avatar
stefan wagner

Thanks for the example. Is it also possible to draw a dashed curved 3d line?

Avatar
Freya Holmér creator
Quote from stefan wagner

Thanks for the example. Is it also possible to draw a dashed curved 3d line?

currently polylines don't support it, but in the example code above using individual lines, you could skip every second line or so for a dashed look

Avatar
Freya Holmér creator

I'm curious for those of you who have voted on this - what is your specific use case for splines?

It would help me to know what the uses will be when designing a potential spline component :)

Avatar
Lollie

On a project that I'm currently on, we've been using polylines as detail elements in scenes, for things like pixel-thin wires, cables, power lines. Splines would help us cut down the number of points we have to use in order to draw freestyle curves. Weighted handles in particular would be very handy, as well as split handles (for hard/pinched corners or asymmetrical curve weights).

Avatar
Denis Antipov
Quote from Freya Holmér

I'm curious for those of you who have voted on this - what is your specific use case for splines?

It would help me to know what the uses will be when designing a potential spline component :)

I wanted to make projectile traectory. It should be basic cubic spline.
Also it suits some mechanics of dragNdrop like in Slay the Spire (Red pointer from card)

Avatar
Freya Holmér creator

I think the main questions for me revolve around three things:

A. 
Should this be an extension of polylines? as in, an inspector/scene view based component that automatically calculates polyline points for you, similar to the immediate mode splines and arcs?

B.
Should this be an entirely separate shape? as in, a spline component that allows you to chain multiple control points together with dedicated controls

C.
if it *is* an entirely separate shape, that has a few implications - while this (mostly) isn't possible with cubic beziers, quadratic beziers can actually have vector-based smoothness instead of having multiple control points, though it would then be limited to a flat plane instead of the billboarding support that polylines have, which instead is a little bit more limiting

another question is how important it is to chain multiple curves together in a single component, or if one spline segment per component would be fine

there are lots of questions I need to figure out a good design for, so, yeah, we'll see! more of your actual use cases would be helpful regardless :)

Avatar
Demid Lupin

I prefer has one line with multiply point. For example to draw past or predicted trajectory. So some poins and smooth line between them

Avatar
Lollie

It would make sense for splines to be treated like a new shape component, as it requires a more complex set of controls compared to polylines. However, it could always use polylines under the hood — allow the user to select the resolution of the curve (maybe per-segment?), and that controls the number of polyline points generated.

(edit: Realized this is what you meant by your first question, so - yes! Extension of polylines sounds good and sensible)

If you already have other components that function on top of polylines, great! Consistency between components is an excellent reason to go that path.

 

I think it's important for splines to support chaining multiple points. Sometimes, a desired curve just can't be achieved with a single segment, and having to craft multiple single segments for longer/complex curves could become a real pain very quickly.

Avatar
-3
Philip Askins
Quote from Freya Holmér

I'm curious for those of you who have voted on this - what is your specific use case for splines?

It would help me to know what the uses will be when designing a potential spline component :)

I know this is a late reply to this comment but I thought it might help nonetheless. Really I'm using Shapes for design work so this spline feature would be great for creating certain shapes that aren't possible currently. So just having handles to be able to control the curves between points would be what I'd most use it for, akin to designing in any vector program. Also like those programs, being able to break tangents would be a huge help too but that might be a whole other issue to contend with. Thanks for all the hard work so far!

Avatar
alex harding

For me personally it isn't so much about having handles that can be manipulated with a cursor in the editor, but about generating curved shapes with code. Ideally it would work along the lines of the curves in processing, with the priority being the "continuous spline curve" mode whereby it interpolates between n control points. 

Another thing (since we're here) I'd love a radius option for the rounded corners in poly lines, similar to the roundness value on regular polygons!

Avatar
Tom Mertz
Quote from alex harding

For me personally it isn't so much about having handles that can be manipulated with a cursor in the editor, but about generating curved shapes with code. Ideally it would work along the lines of the curves in processing, with the priority being the "continuous spline curve" mode whereby it interpolates between n control points. 

Another thing (since we're here) I'd love a radius option for the rounded corners in poly lines, similar to the roundness value on regular polygons!

I was looking for something similar to this. I realize based on other posts that maybe the purpose of the library isn't so much a graphing/interpolation library. But passing a group of points into a method to create a splined curve would be pretty sweet. I had a hard time actually finding out how to do Bezier curves without this post (code sample was very helpful, but nothing in the docs). Here's my basic "spline?" attempt, improvements welcome, I'm definitely not a "math person" so those words could be wrong, not to mention this implementation :)

using Shapes;
using UnityEngine;

public class BezierDraw : MonoBehaviour {
    [Range(0.0f, 1.0f)]
    public float curveAmount = 0.5f;
    [Range(0.1f, 10.0f)]
    public float sphereRadius = 0.5f;
    public int interpolationPoints;
    public float lineThickness = 0.2f;
    public Vector3[] points;

    void OnDrawGizmos() {
        // bail unless we have 2 points
        if (points.Length < 2) return;

        Draw.PolylineGeometry = PolylineGeometry.Billboard;
        using (var path = new PolylinePath())
        {
            Vector3 prevTan = Vector3.zero;
            for (int i = 0; i < points.Length; i++)
            {
                if (i == 0)
                {
                    // if we're on the first point, there's no tangent
                    path.AddPoint(points[0]);
                    prevTan = points[0];
                    continue;
                }
                else if (i == points.Length - 1)
                {   
                    // if we're on the last point, we use the previous tangent and end point
                    path.BezierTo(prevTan, points[i], points[i], interpolationPoints);
                    continue;
                }

                // Find the direction between the previous point and the next point to interpolate
                Vector3 dir = (points[i+1] - points[i-1]).normalized;
                // This points ending tangent
                Vector3 tan = points[i] - (dir * (Vector3.Distance(points[i-1], points[i]) * curveAmount));
                // What will be the next points starting tangent
                Vector3 endTan = points[i] + (dir * (Vector3.Distance(points[i], points[i+1]) * curveAmount));

                // draw tangent line visuals
                Draw.Color = Color.blue;
                Draw.Line(tan, endTan);

                path.BezierTo(prevTan, tan, points[i], interpolationPoints);
                prevTan = endTan;
            }

            // Draw the Polyline
            Draw.Color = Color.white;
            Draw.Polyline(path, lineThickness, PolylineJoins.Simple);
        }

        Draw.Color = Color.white;
        using(var path = new PolylinePath())
        {
            foreach(Vector3 point in points)
            {
                Draw.Sphere(point, sphereRadius);
            }
        }
    }
}

Result:

Image 442

Avatar
cpetry

Is this still being considered?
Would buy if this is actively worked on.

Avatar
Freya Holmér creator
Quote from cpetry

Is this still being considered?
Would buy if this is actively worked on.

Currently on hold - Shapes can already draw splines if you provide the points for a polyline component, or draw them in immediate mode.

The thing is, Shapes isn't a spline library, it's a rendering library, but you can certainly use it with splines!

If you want some code for common curves used in splines, you can find that here: https://github.com/FreyaHolmer/Mathfs/tree/dev/Curves

Avatar
christian petry
Quote from Freya Holmér

Currently on hold - Shapes can already draw splines if you provide the points for a polyline component, or draw them in immediate mode.

The thing is, Shapes isn't a spline library, it's a rendering library, but you can certainly use it with splines!

If you want some code for common curves used in splines, you can find that here: https://github.com/FreyaHolmer/Mathfs/tree/dev/Curves

With the new splines package from Unity, how would I go about using this as a base?
Would be really nice to draw a spline 'directly' with Shapes

Avatar
Freya Holmér creator
Quote from christian petry

With the new splines package from Unity, how would I go about using this as a base?
Would be really nice to draw a spline 'directly' with Shapes

it depends on how you sample splines in their package (I personally haven't used it), but in immediate mode it would look something like this:

using( PolylinePath pp = new() ) {
const int DETAIL = 100;
for( int i = 0; i < 100; i++ ) {
float t = i / (DETAIL-1f); // assumes the spline is sampled in a 0 to 1 range
pp.AddPoint(spline.Eval( t ));
}
Draw.Polyline( pp );
}

and for component polylines you would do something similar, except apply the points to the polyline component

Avatar
christian petry
Quote from Freya Holmér

it depends on how you sample splines in their package (I personally haven't used it), but in immediate mode it would look something like this:

using( PolylinePath pp = new() ) {
const int DETAIL = 100;
for( int i = 0; i < 100; i++ ) {
float t = i / (DETAIL-1f); // assumes the spline is sampled in a 0 to 1 range
pp.AddPoint(spline.Eval( t ));
}
Draw.Polyline( pp );
}

and for component polylines you would do something similar, except apply the points to the polyline component

I would rather use it in non immediate mode. I need to implement a spline editor tool in my runtime application. De -serialization for saving and all.

Thanks though for this first step. I'll work my way through and come back if I stumble on my way.