Table of Contents:
2.1 The GLUT Framework
As a starting point in learning OpenGL, I needed a window management framework in order to begin
rendering the images to the screen. Using the GLUT library allowed maximal abstraction of
the window system, and gave me the ability to focus primarily on OpenGL programming. Although GLUT
has its limitations, it enabled creation of a window
(titled as 'Spider' for this project) and supported GLUT callbacks in response to keyboard
presses, mouse clicks, resizing of the window and timer functions.
2.1.1 Window Creation
Used in conjunction with FindWindow() and SetFocus() (Win32 APIs), the GLUT framework allows for
control of the 'Spider' window when rendering scenes. That is, if no spider window
is present on the system, then it needs to be created. However, if one is already present on the
system, then the animation or scene modification needs to appear as if it is happening in the same
window. This is essential when the spider GUI is used to change the parameters of the spider
image or motion. The following code illustrates how the GLUT window is found or created:
hwnd = FindWindow("GLUT", "Spider");
if(hwnd != NULL)
2.1.2 Window Management
In order to reflect morphological changes or animation, the current window had to be redisplayed.
This is done by making calls to the following functions:
The first function, glutPostRedisplay(), refreshes the drawing and is needed after every callback
is triggered. The latter function makes use of double buffering in the glut library. Double
buffering allows rendering of drawings to be done in a separate buffer. When the drawing
is complete, a call to glutSwapBuffers() will place the offscreen drawing into the onscreen buffer.
This allows partial drawings to be invisible to the viewer and for smoother animation to occur.
To initialize double buffering, the following function call is needed in the beginning of the program:
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
2.1.3 GLUT Callbacks
Window Callbacks correlate with window changes indicated by the user (e.g., mouse clicks or
key presses) or when input is available for the window. Callbacks that are done in this program
include the following:
glutReshapeFunc(ChangeSize); // enable resizing of window
glutMouseFunc(Mouse); // detect mouse clicks
glutSpecialFunc(SpecialKeys); // detect arrow key presses
glutDisplayFunc(RenderScene); // render spider
Therefore, although most user control is located at the level of the 'Spider GUI' window (see
Matlab GUI section for details), there are a few manipulations
that can be controlled within the rendered 'Spider' window itself. The user controls located
here are as follows:
Left Mouse Clicks:
||pause/play spider animation
If the left mouse click is used in conjunction with the 'Spider GUI' window's Play menu
options (See Menu Options section in the Matlab
GUI design for details), user should beware that additional mouse clicks may be needed
to restart the spider animation.
Global callbacks correlate with the tracking of time. In this case, a timer was needed to estimate
performance of OpenGL rendering on the systems. Thus, in the final product, the following call
is commented out:
glutTimerFunc(DELAY, timing, 0);
2.2 Object Composition and Modeling
2.2.1 The coordinate system
As a first step in learning about object composition and modeling, I needed to understand
the coordinate system. This required a few exercises such as drawing a
very simple orbital system containing spheres and cylinders with very contrasting
colors. From this system, (see image on the right), I understood how objects
rotated (through the cylinders and attached spheres) and translated (through the
smaller green spheres). Click here to view
an avi file containing the full animation of the orbital system.
Since the coordinates most familiar to me was the two dimensional x-axis and y-axis
in the horizontal and vertical directions, I consistently built objects with respect
to these axes. If the final object needed to be moved, I would rotate or translate
the object once more to its final destination.
2.2.2 Hierarchical Modeling
After understanding the coordinate system, I began learning about
hierarchical modeling through the following tutorial (see Chap 3.1):
Since hierarchical modeling allows objects to be subordinate to other objects, I found it
very useful in spider animation. By using the functions:
the stack will keep track of the hierarchy of objects. Thus, movement of one object will
cause it's subordinate objects to move relative to each other. In the case of the spider,
the leg segments must move synchronously with each other,
and movement of one segment should cause all other segments to become relatively displaced to
the first segment.
In my implementation, I began by building the central body structures (i.e., the abdomen and the
thorax). Once these were complete, I built the head and hierarchically placed the spinnerets
on the head as well. Therefore, control of the head through the spider GUI actually increases
or decreases the size of both the head and the spinnerets. After completing all body structures,
the legs were rendered last. Each leg was hierarchically modeled by creating leg segments
2.2.3 Creating the Geometry: Quadrics
Once I completed the prototyping, I was ready to model the spider more accurately.
Using Eileen's video playback image of a Schizochosa uetzi, I was able to measure the spider's
geometry manually. In addition, I found images on the web of wolf spiders to more accurately
measure some areas of the spider that were hidden in the video playback.
the geometry by hand measurements, I needed a way to render the image using drawing primitives that
were already present in opengl (i.e., by creating quadrics). Basically, quadrics allowed drawing of
cyinders and spheres. Thus, by using a combination of these primitives, I was able to create the
entire image of the spider.
The wire framed image to the right shows the different geometric shapes used to render the spider.
(for the body: spheres are drawn in blue, cylinders are drawn in red).
2.3 Color, Lighting and Materials
I wanted to give the user control of all aspects of the spider. Therefore, in order to make
the color of each individual body segment adjustable, I had to make many calls to glColor3f()
throughout the code (i.e., prior to each rendering of a body or leg segment).
There are 3 types of lighting to consider when rendering an object:
Of the 3 light sources, ambient light is the only one that is directionless. It is light that
comes from rays bounced around the room. Therefore, a strong ambient light (with no diffuse
or specular lighting), will result in the image shown on the left below (notice the
lack of dimension that results from such a case). Diffuse light, on the other hand,
reflects evenly off
a surface, resulting in the 2nd image below. Lastly, specular lighting requires a light source.
It is reflected sharply and uniformly as shown in the rightmost image below. I allow the user
to control all aspects of lighting even though it is apparent that values in certain
ranges will produce quite unrealistic results. However, across different hardware,
OpenGL may render the lighting differently. Giving the user full control will
allow them to adjust to the proper settings.
In addition to the lighting effects, the material of the object needed to be set. Material in
this sense refers to the type of lighting that the material will reflect. If the material
property is not set, no light will be reflected and the colors specifying the object can
not be simply changed through the glColor3f() function call. Thus, the material is set to:
glMaterialfv(GL_FRONT, GL_SPECULAR, specref);
glMateriali(GL_FRONT, GL_SHININESS, 128);
The glEnable() call allows the color of the material to be set with the glColor3f() function
throughout the rest of the program.
The GL_FRONT parameter specifies that the front of the spider will take on the material
properties set in the program.
In order to achieve spider animation, the leg movements needed to be redisplayed in
every time step. This required further enhancements to the individual angles between the
leg segments. In addition, a timeStep variable was needed to know when the leg was back
at rest and the animation needed to be restarted. Therefore, the following parameters tracked
new angles between the leg segments and the time steps:
int timeStep = 0;
int max_timeStep = 120;
// tracks timeSteps
GLfloat newrf_ang1 = rf_ang1;
GLfloat newrf_ang2 = rf_ang2;
GLfloat newrf_ang3 = rf_ang3;
GLfloat newrf_ang4 = rf_ang4;
In addition, I wanted this animation to be interactive. Therefore, I allowed the user to
start and stop the animation through a mouse click. See
GLUT Callbacks section for details on how to control movement of the spider.