如何镶嵌贝塞尔曲线三角形?

Che*_*ery 5 rendering tesselation

我关心的是二次贝塞尔曲线三角形,我正尝试对其进行细分以渲染它们。

我已经设法通过像维基百科页面中所述那样递归地细分三角形来实现这一点。尽管我想更精确地细分。问题在于,要么细分过少,要么细分太多,因为在该算法的每次迭代中曲面的数量都会翻倍。

特别是,我需要一种自适应的镶嵌化算法,该算法可以定义边缘处的片段数量。我不确定是否可以做到这一点,所以我也想听听统一的镶嵌技术。

最困难的麻烦我在计算贝塞尔曲面中的点的法线时遇到了麻烦,我不确定是否需要它,但一直在努力解决。

Che*_*ery 1

自适应曲面细分。有很多算法可以实现这一点。但这里有一个:

def line_angle((x0,y0),(x1,y1)):
    return atan2(y1-y0,x1-x0)

def adaptive_bezier(p0,p1,p2,lev=32):
    p01 = midpoint(p0,p1)
    p12 = midpoint(p1,p2)
    m = midpoint(p01, p12)
    da = abs(line_angle(p0,p1) - line_angle(p1,p2))
    if da <= max_tolerance or lev <= 0:
        yield m
    else:
        for p in adaptive_bezier(p0,p01,m,lev-1): yield p
        for p in adaptive_bezier(m,p12,p2,lev-1): yield p
Run Code Online (Sandbox Code Playgroud)

对于以这种方式细分三角形,事情会变得很复杂。您需要根据边缘贝塞尔曲线的角度驱动自适应镶嵌器算法。细分时,三角形可以通过三种独特的方式进行分割。

 2 edges      one edge     3 edges    
--------     ---------    --------
\  ...//     \   |   /    \ /  \ /
 \/___/       \  |  /      \____/
  \  /         \ | /        \  /
   \/           \|/          \/
Run Code Online (Sandbox Code Playgroud)

为这些图案定义细分结果,您就一切顺利了。维基百科文章中仅描述了具有一条边的镶嵌。

通过研究一侧边缘分割的情况可以获得另外两个曲面细分结果。

通过先分割一条边,然后分割另一条边,可以直接获得“2 条边”。

找出“3条边”需要更多的工作。但您可以看到“2 个边缘”-案例为您带来了中间边缘。对于二次贝塞尔三角形,它是出现在那里的菱形的平均和:

--------      /\
\      /     /  \
 \____/     -____-
  \  /       \  /
   \/         \/
Run Code Online (Sandbox Code Playgroud)