如何在只投影其控制点的情况下,视觉上匹配Bézier曲线的透视投影与原始曲线?

4
我正在编写一个立方贝塞尔曲线编辑器,旨在让您在3D世界中创建、选择和修改贝塞尔曲线。
目前我正在开发选择/挑选界面。 我希望能够根据用户在屏幕空间内与实际投影表示的曲线之间的像素距离来选择曲线。
我的第一种方法是在三维空间中使用拾取光线段与曲线立方段的边界框相交处的数字分析。 我使用二分搜索来找到射线在曲线上最接近的点的近似值。它起作用,但在使用情况下缺乏稳健性,并且需要根据相机与曲线上点之间的距离来缩放“选择距离”设置。对我而言,它也不够优雅。
我目前的想法是手动将曲线部分投影到近平面上,以获得我可以进行数字分析的投影贝塞尔曲线。此外,以前的拾取光线参数现在将被缩小为单个点:用户在视口上单击的位置。
很不幸,我在原型制作之前所担心的问题成真了:贝塞尔曲线在平面上的投影不完全等同于其控制点的投影所得到的曲线。在进一步阅读该主题后(我一般对数学很糟糕),似乎投影曲线以某种方式退化为有理贝塞尔曲线,其表达方式不同。
新曲线的视觉表现与原始曲线不匹配,看起来非常接近,但我需要像素完美的匹配。
我还有其他选项来解决我的问题,例如在场景中投射一个拾取锥体,或者将曲线段一旦离散化便进行投影作为折线。不过我想知道,是否存在通过重新参数化或使用我无法自己解决的数学技巧更改投影曲线的当前问题的快速简易解决方案。
提前致谢。 编辑示例投影图像:http://i.imgur.com/1XawRof.png

为什么这是个问题呢?将3D贝塞尔曲线投影到2D平面上,可以得到一个有理贝塞尔曲线,您可以用它来进行点到曲线距离检查。这不是您想要做的吗?(实际上:使用有理形式检查坐标是否靠近投影曲线让您感到担忧的原因是什么?) - Mike 'Pomax' Kamermans
Mike,也许我解释得不够准确和清晰:我目前使用的曲线是有理贝塞尔曲线,由原始(3D场景中的)曲线控制点的投影定义。结果发现,这条新曲线与原始曲线所有点的实际投影不匹配,我不知道是否可以用贝塞尔参数来描述它。我需要能够重建曲线的精确表示,以便在鼠标拾取时检查点的位置与光标位置的对应关系。 - dummydev
这是一个示例图片(由于声望不够,我无法将其添加到主帖):http://i.imgur.com/1XawRof.png。绿色曲线是原始曲线,红色曲线是控制点在近平面上投影所描述的曲线。 - dummydev
1
已经为您添加了帖子链接,尽管很难确定曲线投影的原因;您能否将该曲线描述为曲线点的x/y/z坐标集、您要投影的二维平面以及您的投影曲线具有的二维坐标?这也可能只是投影代码存在错误,因此展示如何进行投影的一些代码也可能会有用。 - Mike 'Pomax' Kamermans
确实,这就是我现在作为备选方案正在做的事情:评估3D曲线并将其投影到近平面作为折线。它运行良好,并且如预期地完全匹配原始曲线。不过,我希望找到一种评估有理曲线的方法。关于投影代码,我不能担保它的正确性(因为我不是它的作者;)),但我非常自信它可以正常工作。顺便说一下,感谢您将图片添加到我的原始帖子中。 - dummydev
1个回答

2

通过使用相应的视图矩阵将Bezier曲线的控制点投影到近平面,应该可以得到一个有理Bezier曲线,它与您在视口中看到的相同。

问题可能来自多个问题。如果是我的代码,我会尝试以下内容:

  • 确保向平面的投影是正确的。您需要使用从世界坐标系到近平面的透视投影矩阵,而不仅仅是将输入的Bezier控制点投影到视图平面上。矩阵的透视投影部分使多项式控制点变为有理点。

  • 您可以创建一个三维折线并通过透视矩阵将折线投影到您的近平面。您的折线点应为有理点,应与您在视觉上看到的完全匹配(尽管对于折线,有理点不会改变呈现方式)。这是检查投影是否正常工作的好方法。

  • 确保您的有理曲线评估正常工作。一个好方法是在2D中渲染一个有理圆弧,并确保输出点完全是圆形的。我会通过数值方法来避免任何与投影/视图混淆的情况。


因此,有几种不同的方法可以评估有理Bezier曲线。我最喜欢的方法是使用简单方程来评估齐次点类型,但我见过一些人单独求和权重,或者通过将控制点乘以基矩阵来进行评估。无论哪种方法,都可以。

这是2D有理曲线评估的一个很好的测试。让我们从以原点为中心的圆弧开始。我们将使用二次有理Bezier。点将存储为[xw,yw,w]。

三个点是:

P0 = [1,0,1],P1 = [0.707107,0.707107,0.707107],P2 = [0,1,1]

其中0.707107实际上是sqrt(2)/ 2

如果我们在t = 0.5处进行评估,我们将得到P = [0.603553,0.603553,0.853553]

如果我们除以w,则得到P = [0.707107,0.707107,1]

希望这能帮助到您.. :)


tfinniga,我仔细检查了投影代码,似乎它正在执行预期的操作。作为备选方案,我目前使用您的第二个建议来实现3D拾取:在近平面上,该代码计算鼠标位置相对于投影折线的每个线段的投影。但是,我对您的第三个点感到困惑:到目前为止,我完全按照原始曲线评估了有理(“投影”)曲线的方式。唯一的区别是它是用2D向量在2D空间中完成的。这个过程是否应该产生完全相同的曲线? - dummydev
我会在我的答案中添加有关有理曲线评估的更多细节,因为在评论中有点受限.. ;) - tfinniga
哦,我开始明白了,谢谢!您知道如何检索相应的权重,以便将投影控制点应用于原曲线以获得相同的形状吗? - dummydev
1
所以,你的世界到屏幕矩阵将是一个4x4矩阵。你的控制点是3D点,但你可以将它们表示为齐次点,w=1:[x,y,z,1]。将其乘以你的4x4矩阵,你将得到一个齐次点[xw,yw,zw,w]。那将在你的屏幕空间中,只需使用[xw,yw,w]即可。 - tfinniga
哦,好的,我从来没有想过 那个 w 对于预测曲线的评估会有影响!非常感谢。我会尽快测试,然后发布结果并接受你的答案。 - dummydev

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