在 OpenGL 中绘制新月形状

发布于 2024-12-02 14:29:34 字数 137 浏览 1 评论 0原文

如何在 OpenGL 中绘制 2D 新月或月亮形状?我尝试过使用 sin 和 cos ,就像我画圆时所做的那样,但因为新月内部有一个“切口”,所以 sin 和 cos 看起来不够。我也不知道如何在两个多边形之间进行相交。所以我在想是否有一个绘制新月的数学公式?

How can I draw a 2D crescent or moon shape in OpenGL? I have tried using sin and cos like how I did for drawing circles but because a crescent has a "cut" inside it, the sin and cos don't look enough. I couldn't figure out how I could do an intersection between 2 polygons either. So I'm thinking if there a mathematical formula for drawing the crescent?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

泅人 2024-12-09 14:29:34

这在数学上并不正确,但它可能足以满足您的需求:

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,它会画出一个很细的新月。您可以使用两个不同的填充度值:rightFullnessleftFullness,并始终将其中之一设置为 1.0f,以便您可以更改填充方向新月。

This isn't mathematically correct, but it may be close enough to meet your needs:

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);
}

or

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);
}

At fullness=1, it will draw a circle of size scale while at fullness=-0.99f, it will draw a very thin cresent. You could use two different fullness values, rightFullness and leftFullness, and always set one of them to 1.0f so you can change the direction of the crescent.

热鲨 2024-12-09 14:29:34

您可以绘制两个相互相交的垂直椭圆。从其中一次日食中切出的空间形成了新月。绘图时可以使用按位与非逻辑运算符去除交集。

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

完成此操作的漫长方法是指定一堆顶点,这些顶点形成您想要的形状的骨架。然后,您可以使用 GL_LINES“连接点”来绘制形状。如果您想要更平滑的形状,可以使用顶点作为 Bezier/Catmull-Rom 样条线的控制点,该样条线将绘制一条连接所有顶点的平滑曲线。

You can draw two perpendicular ellipses that intersect each other. A crescent is formed with the space that is cut out from one of the eclipses. The intersection can be removed by using a bitwise NAND logical operator when drawing.

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

The long way of doing it is to specify a bunch of vertices that form a skeleton for the shape that you want. You can then 'connect the dots' with GL_LINES to draw your shape. If you want a smoother shape, you can use the vertices as control points for a Bezier/Catmull-Rom spline that would draw a smooth curve joining all your vertices.

打小就很酷 2024-12-09 14:29:34

您可以尝试以下操作:

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 程序会很好地处理它,但如果你有一个栅栏错误,这可能就是它的来源

You can try this:

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;
}

This produces the intersected polys version of a crescent. It will give you an array of coordinates for an inside and outside arc for a crescent. Then you can feed these through your favorite draw method.

NOTE: The endpoints of inside and outside overlap (I did this so that I wouldn't have +/- 1's all over the place). I'm pretty sure a GL program will be fine with it, but if you have a fence post error with this, that may be where it came from

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文