数学/OpenGL ES:绘制宽度可变的3D贝塞尔曲线

3
我已经在解决一个问题上工作了几个星期,现在想确认一下我的方法是否过于复杂。这是在iOS上使用OpenGL ES 2.0完成的,但原则是通用的,所以答案可以纯数学形式给出。以下是摘要。
我有3D空间中的2个点和一个控制点,我正在使用它们来生成贝塞尔曲线,公式如下:
B(t) = (1 - t)²P₀ + 2(1 - t)tP₁ + t²P₂
起始/结束点被定位在一个相当大的球体上的动态坐标上,因此x/y/z变化很大,使得静态解决方案不太实用。我目前正在使用GL_LINE_STRIP渲染这些点。下一步是使用GL_TRIANGLE_STRIP渲染曲线并控制其宽度相对于高度。
根据这个快速讨论,解决我的问题的好方法是找到与曲线平行的点,考虑它的方向。我希望总共创建3条曲线,传入索引以创建不同宽度的Bezier曲线,然后绘制它。
还有插值和使用Loop-Blinn技术的讨论,似乎可以解决各自问题的特定问题。然而,我认为这些解决方案可能对我追求的目标过于复杂。我也不想将纹理混合在一起。我希望三角形只使用我稍后在着色器中计算的颜色进行绘制。
所以,在我深入阅读三线性插值,Catmull-Rom样条,Loop-Blinn论文或进一步探索采样之前,我想确保哪个方向最有可能是最好的选择。我认为,可以将问题以其最基本的形式表述为:在3D空间中取一个点,并找到两个平行的点,沿着它一起考虑下一个点绘制的方向。
感谢您的时间,如果需要任何进一步的信息,请告诉我,我会尽力添加。

你需要宽度在三维空间中独立于视角进行测量,还是希望在屏幕上具有固定的宽度(比如说两端始终为1像素,中间为5像素宽)? - Nobody moving away from SE
宽度需要在OpenGL中考虑3D空间而不是像素。从技术上讲,它应该独立于视图方向,并且可能比其他要计算的贝塞尔点更少动态。 - Javier Otero
1个回答

2

我认为这个答案并不偏向于你在问题中提到的任何一种方法,但是这是我在这种情况下会做的。

我会计算曲线的归一化法线(或副法线)。假设我将归一化法线作为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

编辑

要对曲线进行一些工作,通常需要计算弗雷内特框架。

这是一组由三个向量(切向量、法向量、副法向量)组成的集合,它们在给定参数值(t)下给出了曲线的方向。

弗雷内特框架由以下公式给出:

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))导数。

如果答案与我提到的方法不同,那也没关系,我很喜欢这样 :) 从简单性的角度来看,这种逻辑似乎是一个很好的选择。然而,我仍然在努力理解规范化。在这种情况下,我特别不确定曲线的法向量是指什么。我很抱歉要求您再详细解释一下,但我认为这会帮助我更好地理解它。非常感谢! - Javier Otero
@JavierOtero添加了一个关于normal的段落。希望现在能够理解。 - Nobody moving away from SE
我会让你知道进展情况,目前为止它很有意义 :) - Javier Otero

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接