[Kstars-devel] OpenGL: the beginning

Jason Harris kstars at 30doradus.org
Fri Dec 5 01:54:09 CET 2003


Hello,

Sorry, I should have explained the code more.  First of all, for reference I 
am using the Qt openGL examples ($QTDIR/examples/opengl), an O'Reilly 
tutorial 
(http://www.oreillynet.com/pub/a/network/2000/06/23/magazine/opengl_render.html),
and I also bought a book: "OpenGL Super Bible" by Richard Wright and Michael 
Sweet (http://www.starstonesoftware.com/OpenGL/opengl_superbbile.htm).

On to the code.

Note on naming of OpenGL functions: all standard OpenGL functions gave a "gl" 
prefix.  Those in the GLU extension lib have a "glu" extension, and those in 
GLUT have a "glut" extension.  The next part of the function name describes 
what the function does.  Finally, the suffix of the function name describes 
the number of arguments and their data type (the suffix is only used when 
convenient).  For example the function "glVertex3f()" is a standard OpenGL 
function that defines a point in the 3D-volume using 3 floats for the X, Y 
and Z positions.  

I didn't intend the "makeObject()" function to be uncommented, which is why it 
didn't work right away for you.  That functions is cut-and-pasted from the Qt 
"box" example.  I thought it would be useful in the future when we are adding 
more objects to the canvas, which is why I didn't remove it completely.

The reason you are not seeing all of the cube is a feature of OpenGL called 
the "clipping volume".   The clipping volume is the volume in the 3D model 
space which should be rendered on the screen.  Using the glFrustrum() 
function, one can define lower and upper limits in X, Y and Z; OpenGL will 
then *only* render those objects which lie inside that volume.

I also found an easier function that does the same thing, gluPerspective().  
The difference is that you can simply send it a field-of-view angle in 
degrees and an aspect ratio to define the X and Y dimensions of the clipping 
volume.  This is much better suited to our purposes in KStars.  This is what 
you see in KGLWidget::doProjection().  

In the Z direction, the clipping volume extends from 10.0 (front edge) to 20.0 
(back edge).  These are defined so that the "front half" of the celestial 
sphere is not drawn, because it is outside the clipping volume.  The sphere's 
center is at x,y,z=(0,0,10) relative to the camera (by virtue of 
"glTranslatef(0.0f,0.0f,-10.0f)", and has a radius of 10 (the first parameter 
in "glutWireSphere()" is the radius (1.0), but that gets multipled by scale, 
which is 10.0).  So, the camera is exactly on the front edge of the sphere, 
but we can only see the back half of it due to the clipping volume.  (By the 
way, the other two parameters to glutWireSphere() define the number of 
longitudinal and latitudinal "panels" to use in rendering the sphere; I used 
24 and 18, so each panel is 1 hour wide and 10 degrees tall). 

You can't disable the clipping volume, but you can certainly make it bigger.

There are two "matrix modes" in OpenGL (there may be more, I only know of 
these two so far): GL_PROJECTION and GL_MODELVIEW.  When talking about 
matrices, we're talking about the standard 3x3 X,Y,Z matrix for 3D graphics.  
When OpenGL is in GL_PROJECTION mode, any matrix manipulations you make 
affect the camera.  You also define the clipping volume in GL_PROJECTION 
mode.  When you are ready to define the objects to be  rendered, you switch 
to GL_MODELVIEW mode.  So, doProjection() is simply a convenience function 
containing the camera manipulations, including the definition of the clipping 
volume.  All I do in doProjection() is call glLoadIdentity(), which resets 
the camera-matrix to the default identity matrix (no translation, no 
rotation, no scaling).  I also define the clipping volume, of course.

In this simple program, I chose to put all of the matrix manipulations in 
paintGL(), where we are working with GL_MODELVIEW mode, but I certainly could 
have put calls to glTranslatef(), glRotatef(), etc. in doProjection().  In 
fact, in a more complicated render scene, we'd probably want to have the 
translation and rotations take place in GL_PROJECTION mode (i.e., in 
doProjection() ) instead.

By the way, paintGL() is the analog of the regular QWidget::paintEvent() 
function, in that it gets called by "update()" and "repaint()".

I hope this helps answer your question about how to translate the camera.  In 
short, you'd want to put the calls to glTranslatef() and glRotatef() in 
doProjection() instead of paintGL().  Like I said, they probably make more 
sense there anyway.  

regards,
Jason
-- 
-------------------------------
KStars: KDE Desktop Planetarium
kstars at 30doradus.org


More information about the Kstars-devel mailing list