使用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 结束,我不应该这样做吗?还是我在这里遗漏了什么? 是的。但是您使用<
来停止循环,而不是<=
。所以对于i < 360
,最后一次迭代是i == 359
。在 C 和 C++ 中,执行这样的循环是惯用的:int x[N]; for (int i = 0; i < 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));
但是width
和heigth
呢?
ps:对不起,我的英语不好。
--- 根据罗德里戈的建议修改 --
【讨论】:
我个人更喜欢第一个版本。第二个遭受angle
变量中累积的精度损失。如果您担心性能,您可以更改为float angle = (rad/180) * i;
,以便编译器能够将计算减少到只有一次乘法。
@rodrigo:好点;我会偷……嗯……从你的评论中汲取灵感,我会在我的回答中进行编辑。
对不起,我的代码中缺少 cmets。 width
height
x
和 y
用于不想做一个圆圈的情况,这就是我有 Type mode
参数的原因。例如,如果需要绘制正方形或矩形,那么我将使用这些参数,抱歉造成混淆。比例尺也不是我指定rad
为半径的半径,scale
很好,只是为了缩放圆,使其更大或更大。还要感谢您提供的信息,我没有意识到 sin
和 cos
只采用弧度,但由于某种原因,当我使用角度时它们仍然有效。希望这可以解决问题!
@zee: 所以rad
是用于“半径”而不是“辐射”?你的基本半径值是 PI?嗯......是的......现在我真的很困惑 :) 而且,是的:仍然使用角度而不是辐射,但你的点在中心周围做了 57 个循环。
刚刚测试了你给我的代码的第一个版本,它完美无缺,给了我和我一样的结果,期望缩放更容易做到!但它受到问题的困扰,但就像@rodrigo 所说的那样,使用for (int i = 0; i < 360; i++)
而不是for (int i = 0; i < 359; i++)
很容易解决这个问题以上是关于使用openGL在c ++中绘制圆的主要内容,如果未能解决你的问题,请参考以下文章
如何使用正交投影在 OpenGL Core 3.3 中绘制一个圆?
如何使用opengl函数制作一个用于在c中绘制3D点的3D窗口?