Advertisement

Bend a mesh along spline

Started by July 30, 2021 06:59 AM
8 comments, last by taby 3 years, 6 months ago

Hi guys,

I am trying to bend a mesh along a spline curve and currently out of ideas … at first i thought i just add spline point vectors to mesh's vertices , but i am looking for more optimized version of it …

so guys …

How can i bend a mesh along a spline, so that mesh, with some forward axis vector follows the spline and bends according to it and also repeat along the spline …

???

I have never done it, but the obvious algorithm should be like this i think:

Precalculation:

For every vertex, find closest point on spline, and store that. A single float is enough to parametrize a spline.

To prevent visual discontinuities, it might be necessary to diffuse this parameter with neighboring vertices. Such artifacts would happen if the spline has a complex shape, so parametrized value jumps big steps between close vertices. To avoid this, you likely want to have a simple rest shape of the spline, no sharp corners or knots - more like a straight line, which then becomes curvy only at runtime with animation.

Optional: Calculate reference frame at the spline for each vertex and store local vertex coordinates in this frame, so you can have faster runtime skinning if needed.

Runtime (or the actual deformation):

For each vertex, calculate reference frame given our stored parametrization value on the spline, and transform the vertex.

Maybe this older post helps with reference frame math. It solves a different but similar problem. There are ofc. many ways to do this: https://www.gamedev.net/forums/topic/697215-extruding-a-shape-along-a-spline/
Usually the problem is how to model twisting around the spline itself, which is something you need to add on top because a spline alone does not define this well.

Advertisement

ok … can somebody reference me to some PDF or paper for some thing similar …

https://computergraphics.stackexchange.com/questions/3724/how-to-deform-some-mesh-so-that-it-fits-along-a-spline-curve

how close it is ????? will it work …

I have no knowledge of the literature on the topic, but I did something very similar to what you're asking some time ago: I wanted to generate lathe meshes and bend them according to a spline. I think the same technique could be adapted to your case quite easily.

First you would need to define what your default axis is: if the input mesh corresponds to the case when the spline curve is a straight line, where is that line in 3D? It could be defined arbitrarily as the Y axis, the PCA of the mesh, or some manually defined axis.

The algorithm is then:

for each vertex v
{
    matrix4 M = ComputeTransformFromAxisToSpline(v);
    v = ApplyTransform(v, M);
}

The tricky part is obviously to define a transform MM. You could do something like:

matrix4 ComputeTransformFromAxisToSpline(vector3 v)
{
    float h = GetPositionOnAxis(v, originalAxis);
    vector3 p1 = GetPointOnSpline(h);
    vector3 p2 = GetPointOnSpline(h + dh); // dh is a small delta
    vector3 u = normalize(p2 - p1);

    // Define an orthogonal basis
    vector3 v = v0;
    vector3 w = normalize(cross(u, v));
    vector3 v = normalize(cross(w, u));

    return MakeTransform(u, v, w, p1) * MakeTranslation(originalAxis, -h);
}

v0v0 is going to be the problem. I have tried two approaches:

  • Use an absolute value, like an axis orthogonal to the default axis. This will work only if the spline never gets parallel to that axis. It may also lead to undesired shapes.
  • Start with an absolute value for the points at h=0h=0, then reuse the previous vv for bigger hh values. This means you have to treat vertices ordered by hh. In my case this was trivial because I was generating the vertices, but in your case that would probably mean to sort them. The result is a mesh that will tend to twist in curves, which may or may not be desirable.

Another possibility would be to define the orientation by having more information in the curve, but I haven't tried that approach as I was already satisfied with the result.

Enzio599 said:
how close it is ????? will it work …

Well, funnily the guy got the same answer than you got. (Lathe mesh along spline is probably the same as ‘extruding a shape along a spline’.)

But there are some issues:
First, there are better ways to get the tangent on a spline analytically than using a ‘small delta’. (See my snippet which does this for a cubic Bezier spline.)
Second, the proposals to calculate a second tangent are no really robust ideas. (See my snippet which solves this by modeling twist around the splines tangent externally from given orientations at end points.)

What you'd need further is a function to find the closest point on a spline from any position in 3D space.
The answer from stackexchange and also mine propose to avoid this by using a straight line for the initial configuration (referred as ‘input mesh’ or ‘rest pose’ in given answers).
It's not that hard to find closest point on a curve either, but using a straight line you avoid all the ‘visual discontinuities’ problems i tried to mention.

Will it work? Yes. If you make it work. If you don't provide feedback on which parts you do not understand, it's just hard to help about any details.

I am looking for a spline function. Can you share yours?

Advertisement

taby said:
I am looking for a spline function. Can you share yours?

I have only this basic bezier and catmull rom stuff as posted in the extrusion post.

But i recently looked up on gitHub for a spline lib and kept those tabs open:

https://github.com/ejmahler/SplineLibrary/blob/master/docs/SplineTypes.md

https://github.com/andrewwillmott/splines-lib

https://github.com/blurstudio/TwistSpline

Did not look in detail yet, and i may miss some good ones. The curse of having the choice :D

Thank you JoeJ. I have a Bezier function. I'm looking for something similar for b-splines. Surely one does not need a gigantic library.

// https://stackoverflow.com/questions/785097/how-do-i-implement-a-bézier-curve-in-c
vector_4 getBezierPoint(vector<vector_4> points, float t)
{
	int i = points.size() - 1;

	while (i > 0)
	{
		for (int k = 0; k < i; k++)
		{
			points[k].x += t * (points[k + 1].x - points[k].x);
			points[k].y += t * (points[k + 1].y - points[k].y);
			points[k].z += t * (points[k + 1].z - points[k].z);
			points[k].w += t * (points[k + 1].w - points[k].w);
		}

		i--;
	}

	return points[0];
}

I found it!!!! A Bezier, b-spline, and Catmull-Rom curve function!

https://github.com/chen0040/cpp-spline

This topic is closed to new replies.

Advertisement