我正在尝试使用 openGL 创建一个具有纬度和经度线的线框球体。目前,我遇到了一个问题,我认为我只是忽略了这个问题,并且在一些帮助下可以通过创建球体快速纠正。我的代码是创建显示的类中的以下代码:
double rho = 1;
gl.glBegin(GL2.GL_LINE_LOOP);
for (int i = 0; i< 360; i++){
theta = i/180 * Math.PI;
for (int j = 0; j< 360; j++){
double phi = j/180 * Math.PI;
double x = rho * Math.sin(phi) * Math.cos(theta);
double y = rho * Math.sin(phi) * Math.sin(theta);
double z = rho * Math.sin(phi);
gl.glVertex3d(x, y, z);
}
gl.glEnd();
}
从这段代码中,我目前没有显示任何内容。我错过了什么?
最佳答案
这段代码有很多问题:
- 正如评论中已经指出的,
glBegin()
和glEnd()
是不平衡的。glBegin()
需要位于第一个循环内。 - 第二个角度只能从 0 到 180 度循环,而不是 360 度。这是基于球坐标的定义。
- 在除法
i/180
和j/180
中,两个值都是int
类型,因此运算是整数除法。使用所使用的值,这些除法的结果将始终为 0 或 1。 - z坐标的计算需要使用
cos(phi)
而不是sin(phi)
。
没有错,只是建议:
- 无需使用 double 值。 OpenGL 无论如何都会使用单精度。
- 如评论中所述,代码使用了现代版本 OpenGL 中已弃用和删除的旧功能。
坚持使用立即模式绘图,解决这些问题应该会产生有效的(未经测试的)代码:
float radius = 1.0f;
for (int i = 0; i <= 360; i++) {
gl.glBegin(GL2.GL_LINE_LOOP);
float theta = i * (Math.PI / 180.0f);
for (int j = 0; j <= 180; j++) {
float phi = j * (Math.PI / 180.0f);
float x = radius * Math.sin(phi) * Math.cos(theta);
float y = radius * Math.sin(phi) * Math.sin(theta);
float z = radius * Math.cos(phi);
gl.glVertex3f(x, y, z);
}
gl.glEnd();
}
这将为您提供经度线。纬度线的代码非常相似,只是交换了两个循环。
至于关于已弃用/遗留功能的讨论,这里讨论的内容有点宽泛。所以只是一个非常快速的总结:
您在这里使用的通常称为“立即模式绘图”。这是 OpenGL 在原始版本中的工作方式。大约 20 年前引入了更有效的指定顶点数据的方法。最初是顶点数组,然后是顶点缓冲区对象(VBO)。后来引入了顶点数组对象(VAO)以使状态设置更加高效。
2009 年推出的 OpenGL 3.2 定义了两个“配置文件”:
- 核心配置文件:删除已弃用的旧功能,包括即时模式绘图。
- 兼容性配置文件:仍然支持所有功能以保持向后兼容性。
如果您编写新代码,特别是如果您刚刚开始学习,则没有充分的理由学习遗留功能。使用Core Profile时初始阈值稍高(主要是因为它要求你用GLSL编写自己的着色器),但这是非常值得的。当前版本的 OpenGL ES 也更接近 Core Profile,并且没有任何这些遗留功能。
关于java - 具有纬度/经度 OpenGL 的线框球体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26207441/