Math/OpenGL ES: Draw 3D bezier curve of varying wi

2019-04-02 00:45发布

问题:

I've been working on a problem for several weeks and have reached a point that I'd like to make sure I'm not overcomplicating my approach. This is being done in OpenGL ES 2.0 on iOS, but the principles are universal, so I don't mind the answers being purely mathematical in form. Here's the rundown.

I have 2 points in 3D space along with a control point that I am using to produce a bezier curve with the following equation:

B(t) = (1 - t)2P0 + 2(1 - t)tP1 + t2P2

The start/end points are being positioned at dynamic coordinates on a fairly large sphere, so x/y/z varies greatly, making a static solution not so practical. I'm currently rendering the points using GL_LINE_STRIP. The next step is to render the curve using GL_TRIANGLE_STRIP and control the width relative to height.

According to this quick discussion, a good way to solve my problem would be to find points that are parallel to the curve along both sides taking account the direction of it. I'd like to create 3 curves in total, pass in the indices to create a bezier curve of varying width, and then draw it.

There's also talk of interpolation and using a Loop-Blinn technique that seem to solve the specific problems of their respective questions. I believe that the solutions, however, might be too complex for what I'm going after. I'm also not interested bringing textures into the mix. I prefer that the triangles are just drawn using the colors I'll calculate later on in my shaders.

So, before I go into more reading on Trilinear Interpolation, Catmull-Rom splines, the Loop-Blinn paper, or explore sampling further, I'd like to make sure what direction is most likely to be the best bet. I think I can say the problem in its most basic form is to take a point in 3D space and find two parallel points along side it that take into account the direction the next point will be plotted.

Thank you for your time and if I can provide anything further, let me know and I'll do my best to add it.

回答1:

This answer does not (as far as I see) favor one of the methods you mentioned in your question, but is what I would do in this situation.

I would calculate the normalized normal (or binormal) of the curve. Let's say I take the normalized normal and have it as a function of t (N(t)). With this I would write a helper function to calculate the offset point P:

P(t, o) = B(t) + o * N(t)

Where o means the signed offset of the curve in normal direction.

Given this function one would simply calculate the points to the left and right of the curve by:

Points = [P(t, -w), P(t, w), P(t + s, -w), P(t + s, w)]

Where w is the width of the curve you want to achieve.

Then connect these points via two triangles.

For use in a triangle strip this would mean the indices:

0 1 2 3

Edit

To do some work with the curve one would generally calculate the Frenet frame.

This is a set of 3 vectors (Tangent, Normal, Binormal) that gives the orientation in a curve at a given parameter value (t).

The Frenet frame is given by:

unit tangent = B'(t) / || B'(t) ||
unit binormal = (B'(t) x B''(t)) / || B'(t) x B''(t) ||
unit normal = unit binormal x unit tangent

In this example x denotes the cross product of two vectors and || v || means the length (or norm) of the enclosed vector v.

As you can see you need the first (B'(t)) and the second (B''(t)) derivative of the curve.