Bezier curve control point

Started by
32 comments, last by JoeJ 1 year, 8 months ago

@joej I haven't got any luck on making the Bezier not freeze so I tried your catmul code but don't know how to call it?

I tried:

                Vector2 catv1 = CatmullRom3D(0, pv1, tangentEndPoint0, tangentEndPoint1, pv2);

                Vector2 catv2 = CatmullRom3D(1, pv1, tangentEndPoint0, tangentEndPoint1, pv2);

Basically same values I give to the bezier library

with that i get some lines but not arc

EDIT: I get arcs now but not in correct place, trying to figure how to call these functions :D

Advertisement

heh65532 said:
I tried your catmul code but don't know how to call it?

For quadratic bezier, compatible with your former setup code, you'd need to call my EvaluateBezier3() function:

Pen bpe1 = new Pen(Color.Blue, 5);
            Pen bpe2 = new Pen(Color.Black, 5);

            Vector2 spv = new Vector2(50, 50);
            Vector2 mpv = new Vector2(100, 50);
            Vector2 epv = new Vector2(80, 150);

            Bezier beez = new Bezier(spv, mpv, epv);

            e.Graphics.DrawEllipse(bpe2, spv.X - 2, spv.Y - 2, 4, 4);
            e.Graphics.DrawEllipse(bpe2, epv.X - 2, epv.Y - 2, 4, 4);

            IEnumerable<IPathShape> bpoints1 = beez.ToArcs();


			Vector2 p0;

			int tess = 13;
				for (int i=0; i<=tess; i++) // tess of 5 would give us 4 line segments
				{
					float t = float(i) / float(tess); // gives a number going from 0 to 1
					sVec3 p1 = EvaluateBezier3 (t, spv, mpv, epv); // calculate the point on the curve as parametrized by t
					if (i) e.Graphics.DrawLine(bpe1, p0.X, p0.Y, p1.X, p1.Y); // draw a straight line segment fromt eh previous to the current point
					p0 = p1;
				}
			

For Catmull Rom there is no need to calculate any interior control points.

Let's say your data has 7 vertices, forming a loop, like in the image of first post.

To draw one segment, we give the previous, current, next, and next next control points. This draws the segment from current to next. Prev and next next are used only to define the curve.

So the code would be:

constexpr count = 7;
Vector2 vertices[count] = {... your data ...};
for (int i1=0; i1<count; i1++)
{
	int i0 = (i1+count-1) % count; // prev
	int i2 = (i1+1) % count; // next
	int i3 = (i1+2) % count; // next next
	
	Vector2 p0;

			int tess = 13;
				for (int i=0; i<=tess; i++) // tess of 5 would give us 4 line segments
				{
					float t = float(i) / float(tess); // gives a number going from 0 to 1
					sVec3 p1 = CatmullRom3D (t, vertices[i0], vertices[i1], vertices[i2], vertices[i3]); // calculate the point on the curve as parametrized by t
					if (i) e.Graphics.DrawLine(bpe1, p0.X, p0.Y, p1.X, p1.Y); // draw a straight line segment fromt eh previous to the current point
					p0 = p1;
				}
}

@joej All your examples working now, ty!

but I don't see difference between catmul and bezier:

(Red line catmul, blue bezier4)

heh65532 said:
but I don't see difference between catmul and bezier: (Red line catmul, blue bezier4)

Yes, i have mentioned this before.

I think it's ok to say ‘Cubic Bezier is a generalization of Catmull Rom’, because Cubic Bezier can do everything that Catmull Rom can do, but not the other way around.

To point out the difference, let's build up some context:

On the top of your image we see the spline is wobbling, although we likely want it more straight.
Personally i worked as artist, so i did a lot of logo designs with Cubic Bezier (Cubic Bezier is used in all related standards and programs: Postscript, pdf, svg, all of our fonts, Illustrator, Photoshop, etc.).
Looking at the image, i feel the desire to fix the wobbles, simply by dragging the internal control points so they form a straight line with the knots.
And with Cubic Bezier i could do this, but with Catmull Rom i could not (because it has no internal control points). That's why Cubic Bezier is so widely used: It's intuitive to manual artwork.

Now, working on games the perspective changes for me: Suddenly manual artwork design no longer my usual goal. Instead i want to reduce the requirement of manual tweaking. I want automation, procedural generation, etc. So just like you, usually i want to calculate internal control points automatically.
But it turns out that's not as easy as i have assumed and hoped.
If you agree the wobbles are an issue, one attempt of solution would be to filter the input vertices, removing vertices which are close to each other, or vertices which form a straight line with their neighbors.
Another attempt would be to make the calculation of internal control points better, e.g. aligning them to the straight segments on the top, or making them shorter for the sharp corner on the bottom right.

If you lack experience with art tools supporting splines, playing with them would help to understand what they do, and in what situations their results are bad / how to do better. (I'd recomment 2D tools over complex 3D stuff like NURBS)
Usually you end up minimizing the number of control points as good as possible, and you accept compromises like making the two tangent handles at a knot of different length.

Now coming back to the actual reason of why results are equal…
You construct the internal control points following my code example. But my example is just the most basic and trivial approach, and using just that, you won't see any advantage over Catmull Rom, because Catmull Rom is based on that exact same trivial and basic idea.
So to get the advantage, we need to use more advanced methods to define interior control points. By far the easiest way to do this is tweaking them manually.

I can not really make any proposal for a better automated method, because i never did it.
But i thought about it, and this would be my starting point:

Take a 2D vector design tool like Illustrator, Ink Scape, or also Photoshop, and make a circle (red).
You see the circle has only 4 knots.
Compare this with your results, using the same arrangement of 4 knots. It gives you a square shape with round corners, but no perfect circle (green).
Observing the reason, we see the internal control points of the circle are farther away from the knots.
We can conclude: The angle between the two line segments connecting our knot to it's neighboring knots should eventually affect the length of the tangent handles as well, not just the length of the line segments alone.
Further i assume: Our trivial approach is ‘correct’ if our curve forms a straight line, but ‘wrong' if they don't. So we know how a angle of 180 degrees should behave.
Starting from there, we should be able to figure out some math to 'blend' between a straight line and a circle example. But first we need to figure out how to calculate tangent handle length to give us a perfect circle, so we know how an angle of 90 should behave.

I guess this gives us some improvements, but i would not wonder if it also introduces new problems… as usual ; )

There surely is related research work, and the problems you see are also reason why there's still ongoing research to develop new spline types.

@joej question, what does the tangent do in your EvaluateBezier4 function? what can it be used for?

i was thinking I need some kind of normal at the points to draw things pointing to right direction

heh65532 said:
@joej question, what does the tangent do in your EvaluateBezier4 function? what can it be used for? i was thinking I need some kind of normal at the points to draw things pointing to right direction

Yeah, that's what it's good for.

The tangent gives only the direction of the curve at the current point. So we usually need a second direction to get a 3D transform. The trivial approach is to use a global up vector.
Another approach is to define transforms at the knots, interpolating them along the curve segments.
Or we interpolate just one transform along the whole curve. I did some example for this: https://cone3d.gamedev.net/forums/topic/697215-extruding-a-shape-along-a-spli

ne/

But if you are just in 2D, one direction is enough, because you can just use the perpendicular direction for a well defined orientation in 2D.

This topic is closed to new replies.

Advertisement