I am not able to create a simple 3D sphere using the OpenGL library function glutSolidSphere() in C++.
Here's what I tried:
#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(); }
In OpenGL you don't create objects, you just draw them. Once they are drawn, OpenGL no longer cares about what geometry you sent it.
glutSolidSphere
is just sending drawing commands to OpenGL. However there's nothing special in and about it. And since it's tied to GLUT I'd not use it. Instead, if you really need some sphere in your code, how about create if for yourself?
#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; }
It doesn't seem like anyone so far has addressed the actual problem with your original code, so I thought I would do that even though the question is quite old at this point.
The problem originally had to do with the projection in relation to the radius and position of the sphere. I think you'll find that the problem isn't too complicated. The program actually works correctly, it's just that what is being drawn is very hard to see.
First, an orthogonal projection was created using the call
gluOrtho2D(0.0, 499.0, 0.0, 499.0);
which "is equivalent to calling glOrtho with near = -1 and far = 1." This means that the viewing frustum has a depth of 2. So a sphere with a radius of anything greater than 1 (diameter = 2) will not fit entirely within the viewing frustum.
Then the calls
glLoadIdentity(); glutSolidSphere(5.0, 20.0, 20.0);
are used, which loads the identity matrix of the model-view matrix and then "[r]enders a sphere centered at the modeling coordinates origin of the specified radius." Meaning, the sphere is rendered at the origin, (x, y, z) = (0, 0, 0), and with a radius of 5.
Now, the issue is three-fold:
pi*5^2/499^2
, which is closer to about 1/3170th) of the entire window, so it might be difficult to see. This is assuming the entire circle is drawn within the area of the window. It is not, however, as we will see in point 2.pi*5^2/(4*499^2)
, which is closer to 1/12,682nd) of the window size. This would make it even more difficult to see. Especially since the sphere is rendered so close to the edges/corner of the screen where you might not think to look.The solution is simply to change the viewing frustum and radius of the sphere. For instance,
gluOrtho2D(-5.0, 5.0, -5.0, 5.0); glutSolidSphere(5.0, 20, 20);
renders the following image.
As you can see, only a small part is visible around the "equator", of the sphere with a radius of 5. (I changed the projection to fill the window with the sphere.) Another example,
gluOrtho2D(-1.1, 1.1, -1.1, 1.1); glutSolidSphere(1.1, 20, 20);
renders the following image.
The image above shows more of the sphere inside of the viewing frustum, but still the sphere is 0.2 depth units larger than the viewing frustum. As you can see, the "ice caps" of the sphere are missing, both the north and the south. So, if we want the entire sphere to fit within the viewing frustum which has depth 2, we must make the radius less than or equal to 1.
gluOrtho2D(-1.0, 1.0, -1.0, 1.0); glutSolidSphere(1.0, 20, 20);
renders the following image.
I hope this has helped someone. Take care!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With