Math/OpenGL ES:绘制不同宽度的3D贝塞尔曲线 [英] Math/OpenGL ES: Draw 3D bezier curve of varying width

查看:392
本文介绍了Math/OpenGL ES:绘制不同宽度的3D贝塞尔曲线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经研究了一个问题好几个星期了,以至于我想确保自己不会使方法过于复杂.这是在iOS的OpenGL ES 2.0中完成的,但是原理是通用的,因此我不介意答案纯粹是数学形式的.这是清单.

我在3D空间中有2个点以及一个控制点,我将使用该控制点生成具有以下等式的贝塞尔曲线:

B(t)=(1-t) 2 P 0 + 2(1-t)tP 1 + t 2 P 2

起点/终点被定位在相当大的球体上的动态坐标上,因此x/y/z变化很大,因此静态解决方案不那么实用.我目前正在使用GL_LINE_STRIP渲染点.下一步是使用GL_TRIANGLE_STRIP渲染曲线,并控制相对于高度的宽度.

根据此快速讨论,解决我的问题的一种好方法是在考虑到曲线方向的情况下找到与曲线平行的点.我想总共创建3条曲线,传入索引以创建宽度可变的贝塞尔曲线,然后绘制它.

也有关于 Loop-Blinn技术似乎可以解决各自问题的具体问题.我认为,对于我要追求的目标而言,解决方案可能太复杂了.我也不希望将纹理添加到混合中.我更喜欢使用我稍后将在着色器中计算的颜色绘制三角形.

因此,在我进一步阅读三线性插值,Catmull-Rom样条曲线,Loop-Blinn论文或进一步探讨采样之前,我想确定什么方向最有可能成为最佳选择.我想我可以说,最基本形式的问题是在3D空间中获取一个点,并在其旁边找到两个平行点,其中考虑了下一个点的绘制方向.

感谢您的时间,如果我可以提供更多信息,请告诉我,我会尽力添加.

解决方案

(据我所知)此答案不赞成您在问题中提到的一种方法,但是在这种情况下我会这样做. /p>

我将计算曲线的归一化法线(或双法线).假设我采用归一化的法线并将其作为t(N(t))的函数.这样,我将编写一个辅助函数来计算偏移点P:

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

其中o表示曲线在法线方向上的有符号偏移.

鉴于此功能,您可以通过以下方式简单地计算曲线左侧和右侧的点:

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

w是要获得的曲线的宽度.

然后通过两个三角形将这些点连接起来.

在三角形条中使用将表示索引:

0 1 2 3

修改

要对曲线进行一些处理,通常会计算出Frenet帧.

这是一组3个向量(Tangent,Normal,Binormal),它们在给定参数值(t)处给出曲线的方向.

Frenet帧由下式给出:

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

在此示例中,x表示两个向量的叉积,|| v ||表示封闭的向量v的长度(或范数).

如您所见,您需要曲线的一阶(B'(t))和二阶(B''(t)).

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.

解决方案

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.

这篇关于Math/OpenGL ES:绘制不同宽度的3D贝塞尔曲线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆