0

I don't know very much about openGL/glut, but I've used it before successfully for some exceedingly simple things in 2D. Now I want to be able to draw spheres in 3D. I'm trying to simulate particle collisions, so all I'm really going to need to do on the graphics end is draw spheres. Here's my abortive attempt

void renderScene() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); // Set the camera gluLookAt(1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); glutSwapBuffers(); } void timerProc(int arg) { glutTimerFunc(50,timerProc,0); // Reset transformations glLoadIdentity(); // Set the camera gluLookAt(1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glColor3f(0.0,0.0,0.0); //color = black glPushMatrix(); glTranslated(0,0,0); glutSolidSphere(.74, 500, 500); glPopMatrix(); glutSwapBuffers(); } int main(int argc, char **argv) { srand(time(NULL)); init(); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); glutInitWindowPosition(50,30); glutInitWindowSize(glutGet(GLUT_SCREEN_WIDTH)-80,glutGet(GLUT_SCREEN_HEIGHT)-60); mainWindow=glutCreateWindow("New Window"); //global variable WIDTH=glutGet(GLUT_WINDOW_WIDTH); //global variable HEIGHT=glutGet(GLUT_WINDOW_HEIGHT); //global variable glutDisplayFunc(renderScene); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glutTimerFunc(50,timerProc,0); glutMainLoop(); return 0; } 

Hopefully all of my problems stem from one really basic mistake... For some reason, this creates an oval. And, though the oval is pretty big (maybe about an 1/8th of the screen wide and tall), if I lower the radius down to .73 it vanishes, I'm guessing because it's too small to see. How would I make it so that this sphere would show up circular like you'd expect, and so that as I can see everything that's happening in a given volume, say a 10x10x10 box, the way you would if you were just standing next to a box of particles that were flying around and peering into it, or a reasonable approximation. Right now it's hard to tell what exactly I'm looking at (I know that I'm standing at 1,1,1 and looking at the origin, but it's hard to grasp exactly what I'm seeing) Also, occasionally when I run it the whole screen is just black. Then when I clean and build and run again it's fine. Not really a huge concern, but annoying, and I'd love to understand what was going on. Also, when I the number of slices and stacks was lower, it would look fine if the radius was large, but become extremely distorted when the radius was small, which I thought was very strange...

3
  • Not sure if this is the root cause of your problem, but I would start by moving all your sphere drawing code from your timerProc into renderscene(), and having your timer just call glutPostRedisplay() instead of doing its own drawing. It probably won't totally solve your problem, but it's good practice. At the very least, it will ensure that the color and depth buffers are cleared every frame. Also, add a call to glFlush() before you swap buffers. This will ensure that all drawing calls are complete. Commented Apr 15, 2014 at 20:08
  • Does the sphere still vanish if you use glutSolidSphere(0.73, 10, 10) (i.e. have fewer slices/stacks)? Commented Apr 15, 2014 at 21:43
  • @redsoxfantom Changed it, good to have good practice :) But it didn't change anything. @ChristianAichinger Yes, yes it does. If I leave the radius larger: glutSolidSphere(0.74, 10, 10) it becomes horribly deformed and much smaller. Commented Apr 16, 2014 at 19:32

1 Answer 1

1

The main problem you are having here is Z clipping. The initial Z range for the scene is (-1, 1) so you only see a part of the actual sphere and by change in its size you go out of z range.

Image

There are several problems I see in the code. It is good to get a grasp of how the GLUT workflow actually works.

Lets see what the code does wrong.

Main

int main(int argc, char **argv) { srand(time(NULL)); init(); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); glutInitWindowPosition(50, 30); glutInitWindowSize(glutGet(GLUT_SCREEN_WIDTH) - 80, glutGet(GLUT_SCREEN_HEIGHT) - 60); mainWindow = glutCreateWindow("New Window"); //global variable WIDTH = glutGet(GLUT_WINDOW_WIDTH); //global variable HEIGHT = glutGet(GLUT_WINDOW_HEIGHT); //global variable glutDisplayFunc(renderScene); 

Here you define the display function. It is called every time the window contents has to be invalidated. In this case it is invalidated only at start. The renderScene function does not do anything awesome, just clears the screen. So you get a black screen at the beginning.

 glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 

No need for blending at the moment. You can skip that part altogether.

 glutTimerFunc(50, timerProc, 0); 

Now you set up the timerProc function to be called in 50 milliseconds.

 glutMainLoop(); 

As the documentation states: glutMainLoop enters the GLUT event processing loop. This routine should be called at most once in a GLUT program. Once called, this routine will never return. It will call as necessary any callbacks that have been registered.

 return 0; } 

Render Scene

void renderScene() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

This is the only place where you clear the screen. Timer Func does not do this.

 glLoadIdentity(); 

You are reseting the matrices.

 // Set the camera gluLookAt(1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); 

Setting up the matrices. (One matrix to be precise)

 glutSwapBuffers(); 

And without drawing anything you swap buffers.

} 

Scene rendering function is called each time the window frame has to be redrawn.

Timer

This function does rely on the screen being cleared at first by the renderScene. void timerProc(int arg) { glutTimerFunc(50, timerProc, 0);

 // Reset transformations glLoadIdentity(); // Set the camera gluLookAt(1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 

Not clearing this time. Only setting the color.

 glColor3f(0.0, 0.0, 0.0); //color = black glPushMatrix(); glTranslated(0, 0, 0); glutSolidSphere(.74, 500, 500); glPopMatrix(); glutSwapBuffers(); } 

How to fix it?

Just setup the matrices. With proper Z range.

void resetTransformations() { glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-1, 1, -1, 1, -1000, 1000); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); } void renderScene() { glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Reset transformations resetTransformations(); // Just to see some triangles glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glColor3f(0.0, 0.0, 0.0); //color = black glPushMatrix(); glTranslated(0, 0, 0); glutSolidSphere(0.74, 500, 500); glPopMatrix(); glutSwapBuffers(); } int main(int argc, char **argv) { srand(time(NULL)); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); glutInitWindowPosition(50, 30); glutInitWindowSize(256, 256); mainWindow = glutCreateWindow("New Window"); //global variable WIDTH = glutGet(GLUT_WINDOW_WIDTH); //global variable HEIGHT = glutGet(GLUT_WINDOW_HEIGHT); //global variable glutDisplayFunc(renderScene); glutIdleFunc(renderScene); glutMainLoop(); return 0; } 
Sign up to request clarification or add additional context in comments.

4 Comments

This does work, but there's still a few strange things going on. From what I understand, glOrtho set's up how far away you can see objects? If I change that call to glOrtho(-10, 10, -10, 10, -1000, 1000); and the radius to something larger, say 7, the sphere shrinks when I run the code. Why would it shrink? I thought nothing is changing and the drawing code is only even called once since the window contents are only invalidated at the start of the program...
glOrtho is a parallel projection of a certain block of space. If you increase the block width and height like glOrtho(-10, 10, -10, 10, -1000, 1000); your sphere will span through less space of this block.
I meant it shrinks while the program is running. It starts out smaller than before, which makes sense, and then it shrinks to nothingness during runtime.
True, there is an error in the answer. No identity set. Fixed.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.