2 OpenGL/Visual C++

Abstract
Usage
Design
Results
Extended Features
Future Direction
Appendix
Acknowledgements
References

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 hwnd;
	...
	hwnd = FindWindow("GLUT", "Spider");
	if(hwnd != NULL)
		SetFocus(hwnd);
    	else
		glutCreateWindow("Spider");

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:

	glutPostRedisplay();
	glutSwapBuffers();

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:
Special Keys:

pitch up
pitch down
rotate right
rotate left

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): http://www.dev-gallery.com/programming/opengl/book/b_index.htm. Since hierarchical modeling allows objects to be subordinate to other objects, I found it very useful in spider animation. By using the functions:
	glPushMatrix();
	glPopMatrix();
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 and joints.

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.

After determining 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

2.3.1 Color

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).

2.3.2 Lighting

There are 3 types of lighting to consider when rendering an object:

  • Ambient light
  • Diffuse light
  • Specular light
  • 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.

    2.3.3 Materials

    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:
    	glEnable(GL_COLOR_MATERIAL);
    	
    	glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
    	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.


    2.4 Animation

    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.