使用OpenGL绘制椭圆或圆时,应该使用多少个顶点?

5

我们应该盲目地使用360个顶点吗?720似乎效果更好,但我们该在哪里停止呢?

2个回答

11
这取决于您可以容忍多少误差(即视觉质量)以及圆形(椭圆形)的大小。更大的圆需要更多的点才能达到相同的质量。您可以通过一些数学计算出给定误差所需的确切点数。
如果您将圆表示为一系列线段,则线段的端点恰好位于圆上(忽略像素网格)。真实圆形和我们的线段表示之间最大的偏差发生在每个线段的中心,而且这个误差对所有线段来说是相同的。
观察从x轴逆时针方向开始的第一个线段,它的两个端点为:
A = (r, 0)
B = (r . cos(th), r . sin(th))

其中r为圆的半径,th为每条线段所覆盖的角度(例如,如果我们有720个点,则每条线段覆盖0.5度,因此th将为0.5度)。

该线段的中点位于

M = A + (B - A) / 2
  = (r, 0) + (r (cos(th) - 1) / 2, r . sin(th) / 2)
  = (r / 2) . (1 + cos(th), sin(th))

并且从原点到该点的距离为

l = (r / 2) . sqrt((1 + cos(th))^2 + (sin(th))^2)
  = (r / 2) . sqrt(2) . sqrt(1 + cos(th))

如果我们的线段表示完美无缺,那么这个长度应该等于半径(线段的中点应该落在圆上)。通常会存在一些误差,这个点会略小于半径。误差为

e = r - l
  = r . (1 - sqrt(2) . sqrt(1 + cos(th)) / 2)

重新排列,使得我们可以用er表示th

2 . e / r = 2 - sqrt(2) . sqrt(1 + cos(th))
sqrt(2) . sqrt(1 + cos(th)) = 2 . (1 - e / r)
1 + cos(th) = 2 . (1 - e / r)^2

th = arccos(2 . (1 - e / r)^2 - 1)

这使我们可以计算出每个点之间可实现特定误差的最大角度。例如,假设我们用100像素的半径绘制一个圆,希望最大误差为0.5像素,我们可以计算:

th = arccos(2 . (1 - 0.5 / 100)^2 - 1))
   = 11.46 degrees

这相当于使用 ceil(360 / 11.46) = 32 个点绘制一个半径为100的圆,最差的像素位置误差小于一半,这意味着我们绘制的每个像素都将在正确的位置(忽略混叠现象)。

这种分析方法同样适用于椭圆,但是按照数学精神,这留给读者作为练习;)(唯一的区别是确定最大误差发生的位置)。


2
你的回答给我的启示是,在猜测可能的值之前,你需要充分定义好约束条件。我能想到的最好的方法是使用椭圆周长作为一个因素。然而,你的方法完美地解决了这个问题。我会尝试一下并很快回来。谢谢 :-) - Plumenator

2
根据你所使用的分辨率或者视觉效果所需,需要的顶点数量是不确定的,主要取决于你想要实现什么。在CAD程序中,一个看起来像八边形的圆可能会让人感到烦恼。另一方面,在iPhone上编写游戏时,如果汽车轮子看起来像八边形,这并不是一个大问题。
一种可能的策略是评估每个线段的长度与当前视图的分辨率,如果超过了3个像素,就增加你使用的顶点数量,但只针对可见的线段。这样,当你放大时,可以增加分辨率,但不必描述你不打算绘制的顶点。

非常有道理。不过,我只是在询问非常简单的2D和单分辨率情况。:-D - Plumenator

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