|
CECS 361 Computer Graphics I |
| MVL Homepage | Department of Computer Engineering and Computer Science |
Polygon animation can be implemented using a sequence of geometric transformations applied to verticies. Use the four polygons (defining the dinosaur) from assignment #4 to implement the animation sequences specified below. Your polygons should be filled correctly. You can use the OpenGL filled polygon routines instead of the previous assignment.
Write your own transformation subroutines to do translation, rotation, and scaling (i.e. my_translate( ), my_rotate( ), my_scale( ) ). Implement matrix multiplication in software, do not use GLMULT. Use the 's' key to repeat the animation and the 'ESC' key to quit from the program. You can use the right arrow key or the '1' (one-) key to step through each frame of the animation.
To enable use of the extended keyboard (arrow keys, function keys, etc.) you will need to define an additional glut function which can still use the same keyboard() callback function:
glutKeyboardFunc(keyboard); glutSpecialFunc(keyboard);
Implement the transformations from the first part using the OpenGL geometric transformation routines.
Use menus from the glut library for implementing the following choices:
EXTRA POINTS - Create a 3-D dinosaur and enable control of 3-D tranformations including translation, rotation, and scaling.
You can use glIdleFunction( ) to specify the transformations to be done automatically without any user intervention. This function is called when there are no user events to process.
OpenGL correctly fills convex polygons. Non-convex polygons must be tessellated into convex sub-polygons in OpenGL. Use the following function to tessellate the polygons in the OpenGL part of the assignment (the compiler should not produce any warning messages since the callback functions are typecast to GLvoid pointer to a function. Note that typecasting of callback functions so that your code will run on both Windows and Unix is bit tricky (see Page 473 in the OpenGL Programming Guide or "Red Book"). In the straightforward (but inefficient) approach the nonConvexPolygon( ) function is called before drawing each polygon as shown in the following example that translates an object composed of four non-convex polygons.
glTranslatef(pos_x, pos_y,0); glColor3f(0.0, 0.50, 0.0); nonConvexPolygon(poly1, num_of_vertices1); glColor3f(1.0, 1.0, 0.0); nonConvexPolygon(poly2, num_of_vertices2); glColor3f(0.67, 0.31, 0.0); nonConvexPolygon(poly3, num_of_vertices3); glColor3f(1.0, 0.0, 0.0); nonConvexPolygon(poly4, num_of_vertices4);
/*
* This function will fill any simple polygon using OpenGL
* tessellation functions.
*
* input:
* vertices: 2-d array of floats containing polygon vertices
* num: number of vertices in the polygon
*/
void nonConvexPolygon( float vertices[][2], int num)
{
GLUtriangulatorObj *tobj; /* tessellation object */
GLdouble v[3]; /* passed to gluTessVertex, prototype used 3d */
int i;
/* create a new tessellation object */
tobj = gluNewTess();
/* specify function callback for starting of a primitive */
gluTessCallback(tobj, GLU_BEGIN, (GLvoid (*)())glBegin);
/* specify function callback used for vertices */
gluTessCallback(tobj, GLU_VERTEX, (GLvoid (*)())glVertex2fv);
/* specify function callback for ending a primitive */
gluTessCallback(tobj, GLU_END, glEnd);
/* begin polygon vertices for tessellation */
gluBeginPolygon(tobj);
{
for (i = 0; i < num; i++) {
/* send vertex for tessellation, it expects 3d array of double */
v[0] = vertices[i][0];
v[1] = vertices[i][1];
v[2] = 0.0;
gluTessVertex(tobj, v, (void *)vertices[i]);
}
}
/* end polygon vertices for tessellation */
gluEndPolygon(tobj);
/* delete the tessellation object */
gluDeleteTess(tobj);
}
If you just use regular convex polygon drawing without tessellation as in the following sample code, then your dinosaur will be incorrectly drawn as shown in the figure below.
void ConvexPolygon(polygon_type polygon, int num_of_vertices) {
int i;
glBegin(GL_POLYGON);
for (i = 0; i < num_of_vertices; i++) {
glVertex2f( polygon[i][0], polygon[i][1] );
}
glEnd();
}
void nonConvexPolygon(polygon_type polygon, int num_of_vertices) {
GLUtesselator *tobj; /* tessellation object */
GLdouble v[3]; /* passed to gluTessVertex, prototype used 3d */
int i;
/* create a new tessellation object */
tobj = gluNewTess();
/* specify function callback for starting of a primitive */
gluTessCallback(tobj, GLU_TESS_BEGIN, (GLvoid (*)())glBegin);
/* specify function callback used for vertices */
gluTessCallback(tobj, GLU_TESS_VERTEX, (GLvoid (*)())glVertex2fv);
/* specify function callback for ending a primitive */
gluTessCallback(tobj, GLU_TESS_END, (GLvoid (*)())glEnd);
/* begin polygon vertices for tessellation */
gluTessBeginPolygon(tobj, NULL);
gluTessBeginContour(tobj);
{
for (i = 0; i < num_of_vertices; i++) {
/* send vertex for tessellation, it expects 3d array of double */
v[0] = polygon[i][0];
v[1] = polygon[i][1];
v[2] = 0.0;
gluTessVertex(tobj, v, (void *)polygon[i]);
}
}
/* end polygon vertices for tessellation */
gluTessEndContour(tobj);
gluTessEndPolygon(tobj);
/* delete the tessellation object */
gluDeleteTess(tobj);
}