[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