使用openGL在c ++中绘制圆

Posted

技术标签:

【中文标题】使用openGL在c ++中绘制圆【英文标题】:Drawing a circle in c++ using openGL 【发布时间】:2016-05-08 17:14:26 【问题描述】:

我一直在尝试使用 openGL 在 c++ 中画一个圆。 So far i have a compresses circle and it just has a random line going across the screen。 这是我用来获得这个形状的函数。

void Sprite::init(int x, int y, int width, int height, Type mode, float scale) 
    _x = x;
    _y = y;
    _width = width;
    _height = height;
    //generate buffer if it hasn't been generated
    if (_vboID == 0) 
        glGenBuffers(1, &_vboID);
    
    Vertex vertexData[360];
    if (mode == Type::CIRCLE) 
        float rad = 3.14159;
        for (int i = 0; i < 359; i++) 
            vertexData[i].setPosition((rad * scale) * cos(i), (rad * scale) * sin(i));
        
    

    //Tell opengl to bind our vertex buffer object
    glBindBuffer(GL_ARRAY_BUFFER, _vboID);
    //Upload the data to the GPU
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);

    //Unbind the buffer
    glBindBuffer(GL_ARRAY_BUFFER, 0);

是什么导致了这条线?为什么我的圈子被压缩了?

对不起,如果这是一个愚蠢的问题,或者这个问题不属于这个网站,我对 c++ 和这个网站都很陌生。

【问题讨论】:

【参考方案1】:

如果不亲自测试代码很难确定,但我还是会猜测。

你奇怪的行可能是由于缓冲区没有完全初始化造成的。这是错误的:

Vertex vertexData[360];
for (int i = 0; i < 359; i++) 

应该是:

for (int i = 0; i < 360; i++) 

否则vertexData[359] 处的位置未初始化并包含一些较远的点。

关于椭圆而不是圆形,这可能是由于您的视口在水平和垂直方向上没有相同的比例造成的。如果将视口和变换矩阵配置为具有 X=-10..10、Y=-10..10 的视锥,但实际视口为 X=0..800 且 Y=0..600,例如,如果比例不同,您的图像就会失真。

解决方案是以下之一:

    创建方形视口而不是矩形。检查您对glViewport() 的论点。 定义视图矩阵以考虑与视口相同的比率。您没有展示如何设置视图/世界矩阵,也许您甚至没有使用矩阵...如果是这种情况,您可能应该使用一个。

【讨论】:

非常感谢!只是一个问题,如果 vertexData 数组存储 360 个顶点的坐标并且它从 0 开始并在 359 结束,我不应该这样做吗?还是我在这里遗漏了什么? 是的。但是您使用&lt; 来停止循环,而不是&lt;=。所以对于i &lt; 360,最后一次迭代是i == 359。在 C 和 C++ 中,执行这样的循环是惯用的:int x[N]; for (int i = 0; i &lt; N; ++i) x[i] = ...;.【参考方案2】:

我不明白,确切地说,你想要得到什么,但是...... cos()sin() 收到了一个光辉的论点;所以,不是cos(i)sin(i),我想你需要cos((2*rad*i)/360.0))sin((2*rad*i)/360.0)),或者简而言之,cos((rad*i)/180.0))cos((rad*i)/180.0))

那么圆的中心和半径呢?

(x, y) 应该是圆心吗?

scale 是辐射吗?

在这种情况下,我想你应该写类似(注意:未测试)

Vertex vertexData[360];
float  rad = 3.14159;
if (mode == Type::CIRCLE) 
    for (int i = 0; i < 359; ++i) 
        float  angle = (rad / 180) * i; // (thanks Rodrigo)
        vertexData[i].setPosition(x + scale * cos(angle), y + scale * sin(angle));
    

或者,失去精度但避免一些蜕皮,

Vertex vertexData[360];
float  rad = 3.14159;
float  angIncr = rad / 180.0;
if (mode == Type::CIRCLE) 
    for (int i = 0, float angle = 0.0; i < 359; ++i, angle += angIncr) 
        vertexData[i].setPosition(x + scale * cos(angle), y + scale * sin(angle));
    

但是widthheigth 呢?

ps:对不起,我的英语不好。

--- 根据罗德里戈的建议修改 --

【讨论】:

我个人更喜欢第一个版本。第二个遭受angle 变量中累积的精度损失。如果您担心性能,您可以更改为float angle = (rad/180) * i;,以便编译器能够将计算减少到只有一次乘法。 @rodrigo:好点;我会偷……嗯……从你的评论中汲取灵感,我会在我的回答中进行编辑。 对不起,我的代码中缺少 cmets。 width height xy 用于不想做一个圆圈的情况,这就是我有 Type mode 参数的原因。例如,如果需要绘制正方形或矩形,那么我将使用这些参数,抱歉造成混淆。比例尺也不是我指定rad 为半径的半径,scale 很好,只是为了缩放圆,使其更大或更大。还要感谢您提供的信息,我没有意识到 sincos 只采用弧度,但由于某种原因,当我使用角度时它们仍然有效。希望这可以解决问题! @zee: 所以rad 是用于“半径”而不是“辐射”?你的基本半径值是 PI?嗯......是的......现在我真的很困惑 :) 而且,是的:仍然使用角度而不是辐射,但你的点在中心周围做了 57 个循环。 刚刚测试了你给我的代码的第一个版本,它完美无缺,给了我和我一样的结果,期望缩放更容易做到!但它受到问题的困扰,但就像@rodrigo 所说的那样,使用for (int i = 0; i &lt; 360; i++) 而不是for (int i = 0; i &lt; 359; i++) 很容易解决这个问题

以上是关于使用openGL在c ++中绘制圆的主要内容,如果未能解决你的问题,请参考以下文章

如何使用正交投影在 OpenGL Core 3.3 中绘制一个圆?

如何使用opengl函数制作一个用于在c中绘制3D点的3D窗口?

C ++ / OpenGL - 2D - 如何在矩形边界框中剪切圆

在 OpenGL 中绘制形状的标准(常用)方法是啥?

在 C++.NET 中使用 OpenGL 并在视口上绘画

在OpenGL中绘制一个相机对齐的圆