在OpenGL中绘制月牙形。

3

如何在OpenGL中绘制2D新月形状?我尝试使用正弦和余弦来绘制圆形,但由于新月形状内部有一个“切口”,所以正弦和余弦看起来不够。我也无法想出如何在两个多边形之间进行交集。所以我在思考是否有绘制新月的数学公式?


1
一个新月是两个非同心圆之间的差异。 - R. Martinho Fernandes
但我需要一种方法来“相交”这些圆,以便其中一个圆清除另一个圆的相交区域。我该怎么做? - Carven
3个回答

2

这并不是数学上正确的,但可能已经足够满足您的需求:

void drawCrescentLine(float step,float scale,float fullness) {
   float angle=0.0f;
   while (angle<M_PI) {
      glVertex2f(scale*sinf(angle),scale*cosf(angle));
      angle+=step;
   }
   while (angle<(2.0f*M_PI)) {
      glVertex2f(fullness*scale*sinf(angle),scale*cosf(angle));
      angle+=step;
   }
   glVertex2f(0.0f,scale);
}

或者

void drawCrescentTriStrip(float step,float scale,float fullness) {
    glVertex2f(0.0f,scale);
    float angle=step;
    while (angle<M_PI) {
        float sinAngle=sinf(angle);
        float cosAngle=cosf(angle);
        glVertex2f(scale*sinAngle,scale*cosAngle);
        glVertex2f(-fullness*scale*sinAngle,scale*cosAngle);
        angle+=step;
    }
    glVertex2f(0.0f,-scale);
}

fullness=1时,它会绘制一个大小为scale的圆形,而在fullness=-0.99f时,它会绘制一个非常细的新月形。您可以使用两个不同的fullness值,即rightFullnessleftFullness,并始终将其中一个设置为1.0f,以便您可以更改新月形的方向。


我用多边形绘制了这段代码,但多边形的端点以一条直线连接成整个图形。当填充颜色时,整个形状都被填充了出来。 - Carven
@xEnOn 原始版本生成的顶点顺序适用于使用 GL_LINE_STRIP。我已更新答案,包括一个应该适用于 GL_TRIANGLE_STRIP 的版本。 - IronMensan
非常感谢!这确实是一种非常聪明的绘制新月形的方法!谢谢! :) - Carven

1

你可以画两个相交的垂直椭圆。从其中一个椭圆中切出一块空间,形成了一个新月形状。在绘制时,可以使用按位 NAND 逻辑运算符来移除交集。

glEnable(GL_COLOR_LOGIC_OP);
drawEllipse1(); 
glLogicOp(GL_NAND);
drawEllipse2();

一个较为繁琐的方法是指定一堆顶点,形成你所需的形状骨架。然后,你可以使用GL_LINES将这些点连接起来以绘制你的形状。如果你想要一个更平滑的形状,你可以使用这些顶点作为Bezier/Catmull-Rom样条的控制点,这将绘制一条平滑的曲线连接所有的顶点。


我该如何在OpenGL中指定逻辑运算符以消除交集?glBegin或glVertex2f不允许我添加按位运算符参数。 - Carven
谢谢!我尝试使用逻辑操作符,但看起来像素要么混合到背景颜色中,要么变成许多点状像素。为什么它不能去除交集?我用通常的正弦和余弦方法以多边形方式正常绘制了我的椭圆形。 - Carven

0
你可以尝试这个:
Vertex outside [N+1]; // Fill in N with the precision you want
Vertex  inside [N+1]; // Fill in N with the precision you want

double neg_size = sqrt (1 + NEG_DIST); // Size of intescting circle.
                                       // NEG_DIST is the distance between their centers
                                       //  Greater NEG_DIST => wider crecent

double start_angle = atan (1 / NEG_DIST); // Start angle for the inside edge
double arc = M_PI - (2 * start_angle);    // Arc of the inside edge

for (int i = 0; i <= N; i++)
{
  // Outside edge
  outside [i].x = cos ((M_PI / N) * i) * SIZE;
  outside [i].y = sin ((M_PI / N) * i) * SIZE;

  // Inside edge
  inside [i].x = (cos (start_angle + ((arc / N) * i)) * neg_size) * SIZE;
  inside [i].y = (sin (start_angle + ((arc / N) * i)) * neg_size - NEG_DIST) * SIZE;
}

这将生成一个月牙形的交叉多边形版本。它会为月牙的内部和外部弧线提供一组坐标。然后,您可以通过您喜欢的绘图方法来处理它们。

注意:内部和外部的端点重叠(我这样做是为了避免到处都有+/- 1)。我相信GL程序不会有问题,但如果您在使用此功能时出现错误,可能就是问题所在。


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