我无法使用C++中的OpenGL库函数glutSolidSphere()创建一个简单的3D球体.
这是我试过的:
#include<GL/glu.h>
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0,0.0,0.0);
glLoadIdentity();
glutSolidSphere( 5.0, 20.0, 20.0);
glFlush();
}
void myInit()
{
glClearColor(1.0,1.0,1.0,1.0);
glColor3f(1.0,0.0,0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,499.0,0.0,499.0);
glMatrixMode(GL_MODELVIEW);
}
void main(int argc,char **argv)
{
qobj = gluNewQuadric();
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(500,500);
glutCreateWindow("pendulum");
glutDisplayFunc(display);
myInit();
glutMainLoop();
}
Run Code Online (Sandbox Code Playgroud)
dat*_*olf 77
在OpenGL中,您不创建对象,只需绘制它们即可.绘制完成后,OpenGL不再关心您发送的几何体.
glutSolidSphere只是将绘图命令发送到OpenGL.然而,它并没有什么特别之处.因为它与GLUT联系在一起我不会使用它.相反,如果你的代码中确实需要一些球体,那么如何为自己创造呢?
#define _USE_MATH_DEFINES
#include <GL/gl.h>
#include <GL/glu.h>
#include <vector>
#include <cmath>
// your framework of choice here
class SolidSphere
{
protected:
std::vector<GLfloat> vertices;
std::vector<GLfloat> normals;
std::vector<GLfloat> texcoords;
std::vector<GLushort> indices;
public:
SolidSphere(float radius, unsigned int rings, unsigned int sectors)
{
float const R = 1./(float)(rings-1);
float const S = 1./(float)(sectors-1);
int r, s;
vertices.resize(rings * sectors * 3);
normals.resize(rings * sectors * 3);
texcoords.resize(rings * sectors * 2);
std::vector<GLfloat>::iterator v = vertices.begin();
std::vector<GLfloat>::iterator n = normals.begin();
std::vector<GLfloat>::iterator t = texcoords.begin();
for(r = 0; r < rings; r++) for(s = 0; s < sectors; s++) {
float const y = sin( -M_PI_2 + M_PI * r * R );
float const x = cos(2*M_PI * s * S) * sin( M_PI * r * R );
float const z = sin(2*M_PI * s * S) * sin( M_PI * r * R );
*t++ = s*S;
*t++ = r*R;
*v++ = x * radius;
*v++ = y * radius;
*v++ = z * radius;
*n++ = x;
*n++ = y;
*n++ = z;
}
indices.resize(rings * sectors * 4);
std::vector<GLushort>::iterator i = indices.begin();
for(r = 0; r < rings; r++) for(s = 0; s < sectors; s++) {
*i++ = r * sectors + s;
*i++ = r * sectors + (s+1);
*i++ = (r+1) * sectors + (s+1);
*i++ = (r+1) * sectors + s;
}
}
void draw(GLfloat x, GLfloat y, GLfloat z)
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(x,y,z);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, &vertices[0]);
glNormalPointer(GL_FLOAT, 0, &normals[0]);
glTexCoordPointer(2, GL_FLOAT, 0, &texcoords[0]);
glDrawElements(GL_QUADS, indices.size(), GL_UNSIGNED_SHORT, &indices[0]);
glPopMatrix();
}
};
SolidSphere sphere(1, 12, 24);
void display()
{
int const win_width = …; // retrieve window dimensions from
int const win_height = …; // framework of choice here
float const win_aspect = (float)win_width / (float)win_height;
glViewport(0, 0, win_width, win_height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, win_aspect, 1, 10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
#ifdef DRAW_WIREFRAME
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
#endif
sphere.draw(0, 0, -5);
swapBuffers();
}
int main(int argc, char *argv[])
{
// initialize and register your framework of choice here
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Vic*_*ian 21
到目前为止,似乎任何人都没有解决原始代码的实际问题,所以我想我会这样做,即使问题在这一点上已经很老了.
问题最初与投影相关的球体半径和位置有关.我想你会发现问题不是太复杂.该程序实际上正常工作,只是被绘制的东西很难看到.
首先,使用该调用创建正交投影
gluOrtho2D(0.0, 499.0, 0.0, 499.0);
Run Code Online (Sandbox Code Playgroud)
" 相当于用near = -1和far = 1调用glOrtho. "这意味着视锥体的深度为2.因此,半径大于1(直径= 2)的球体将不完全适合在视锥体内.
然后是电话
glLoadIdentity();
glutSolidSphere(5.0, 20.0, 20.0);
Run Code Online (Sandbox Code Playgroud)
使用,加载模型 - 视图矩阵的单位矩阵,然后" [r]进入以指定半径的建模坐标原点为中心的球体. "意思是,球体在原点渲染,(x,y, z)=(0,0,0),半径为5.
现在,问题是三方面的:
pi*5^2/499^2是整个窗口的1/2,500 (实际上,接近约1/3170),因此可能很难看到.这假设整个圆圈是在窗口区域内绘制的.但是,正如我们将在第2点中看到的那样.pi*5^2/(4*499^2)是窗口大小的1/10,000(实际上,接近1/12,682nd).这将使其更难以看到.特别是因为球体渲染得如此接近屏幕的边缘/角落,您可能不会想到它.解决方案只是改变视锥体和球体的半径.例如,
gluOrtho2D(-5.0, 5.0, -5.0, 5.0);
glutSolidSphere(5.0, 20, 20);
Run Code Online (Sandbox Code Playgroud)
呈现以下图像.

正如您所看到的,在半球为5的球体的"赤道"周围只能看到一小部分.(我更改了投影以用球体填充窗口.)另一个例子,
gluOrtho2D(-1.1, 1.1, -1.1, 1.1);
glutSolidSphere(1.1, 20, 20);
Run Code Online (Sandbox Code Playgroud)
呈现以下图像.

上面的图像显示了视锥体内部的更多球体,但是球体仍然比观察平截头体大0.2个深度单位.正如你所看到的,球体的"冰盖"在北方和南方都缺失了.因此,如果我们希望整个球体适合具有深度2的视锥体,我们必须使半径小于或等于1.
gluOrtho2D(-1.0, 1.0, -1.0, 1.0);
glutSolidSphere(1.0, 20, 20);
Run Code Online (Sandbox Code Playgroud)
呈现以下图像.

我希望这对某人有所帮助.照顾自己!
小智 10
我不明白datenwolf的索引生成怎么可能是正确的.但我仍然觉得他的解决方案很清楚.这是我在思考之后得到的:
inline void push_indices(vector<GLushort>& indices, int sectors, int r, int s) {
int curRow = r * sectors;
int nextRow = (r+1) * sectors;
indices.push_back(curRow + s);
indices.push_back(nextRow + s);
indices.push_back(nextRow + (s+1));
indices.push_back(curRow + s);
indices.push_back(nextRow + (s+1));
indices.push_back(curRow + (s+1));
}
void createSphere(vector<vec3>& vertices, vector<GLushort>& indices, vector<vec2>& texcoords,
float radius, unsigned int rings, unsigned int sectors)
{
float const R = 1./(float)(rings-1);
float const S = 1./(float)(sectors-1);
for(int r = 0; r < rings; ++r) {
for(int s = 0; s < sectors; ++s) {
float const y = sin( -M_PI_2 + M_PI * r * R );
float const x = cos(2*M_PI * s * S) * sin( M_PI * r * R );
float const z = sin(2*M_PI * s * S) * sin( M_PI * r * R );
texcoords.push_back(vec2(s*S, r*R));
vertices.push_back(vec3(x,y,z) * radius);
push_indices(indices, sectors, r, s);
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
95425 次 |
| 最近记录: |