CS559: Computer Graphics Lecture 12: OpenGL - Transformation Li Zhang Spring 2008

Embed Size (px)

DESCRIPTION

Last time

Citation preview

CS559: Computer Graphics Lecture 12: OpenGL - Transformation Li Zhang Spring 2008 Today Transformation in OpenGL Reading Chapter 3 Last time glPolygonMode(GLenum face, GLenum mode); face: GL_FRONT, GL_BACK mode: GL_POINT, GL_LINE, GL_FILL Primitive Details glPolygonMode(GL_FRONT, GL_FILL); glRectf(0, 0, 100, 100); glPolygonMode(GL_FRONT, GL_FILL); glRectf(0, 0, 100, 100); glPolygonMode(GL_BACK, GL_LINE); glRectf(0, 0, 100, 100); glPolygonMode(GL_BACK, GL_LINE); glRectf(0, 0, 100, 100); Primitive Details Determine Polygon Orientation P4P4 P3P3 P2P2 P1P1 Q4Q4 Q3Q3 Q2Q2 Q1Q1 x y Orientation == sign of the area Icosahedron Normal Vectors Icosahedron //initial icosahedron Static float t[20][3][3] = {}; void display(void) { } //initial icosahedron Static float t[20][3][3] = {}; void display(void) { } Icosahedron //initial icosahedron Static float t[20][3][3] = {}; void display(void) { //clear buffer //set up viewport and frustum if (animation) angle+=0.3; if (angle>360) angle-=360.0; glLoadIdentity(); glRotatef(angle,1,0,1); } //initial icosahedron Static float t[20][3][3] = {}; void display(void) { //clear buffer //set up viewport and frustum if (animation) angle+=0.3; if (angle>360) angle-=360.0; glLoadIdentity(); glRotatef(angle,1,0,1); } Icosahedron //initial icosahedron Static float t[20][3][3] = {}; void display(void) { //clear buffer //set up viewport and frustum if (animation) angle+=0.3; if (angle>360) angle-=360.0; glLoadIdentity(); glRotatef(angle,1,0,1); // subdivide each face of the triangle for (int i = 0; i < 20; i++) { Subdivide(t[i][0], t[i][1], t[i][2], subdiv); } //initial icosahedron Static float t[20][3][3] = {}; void display(void) { //clear buffer //set up viewport and frustum if (animation) angle+=0.3; if (angle>360) angle-=360.0; glLoadIdentity(); glRotatef(angle,1,0,1); // subdivide each face of the triangle for (int i = 0; i < 20; i++) { Subdivide(t[i][0], t[i][1], t[i][2], subdiv); } Icosahedron //initial icosahedron Static float t[20][3][3] = {}; void display(void) { //clear buffer //set up viewport and frustum if (animation) angle+=0.3; if (angle>360) angle-=360.0; glLoadIdentity (); glRotatef(angle,1,0,1); // subdivide each face of the triangle for (int i = 0; i < 20; i++) { Subdivide(t[i][0], t[i][1], t[i][2], subdiv); } glFlush(); glutSwapBuffers(); } //initial icosahedron Static float t[20][3][3] = {}; void display(void) { //clear buffer //set up viewport and frustum if (animation) angle+=0.3; if (angle>360) angle-=360.0; glLoadIdentity (); glRotatef(angle,1,0,1); // subdivide each face of the triangle for (int i = 0; i < 20; i++) { Subdivide(t[i][0], t[i][1], t[i][2], subdiv); } glFlush(); glutSwapBuffers(); } Icosahedron void Subdivide(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3], int depth) { } void Subdivide(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3], int depth) { } Icosahedron void Subdivide(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3], int depth) { if (depth == 0) { glColor3f(0.5,0.5,0.5); glBegin(GL_TRIANGLES); glVertex3fv(v1); glVertex3fv(v2); glVertex3fv(v3); glEnd(); } void Subdivide(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3], int depth) { if (depth == 0) { glColor3f(0.5,0.5,0.5); glBegin(GL_TRIANGLES); glVertex3fv(v1); glVertex3fv(v2); glVertex3fv(v3); glEnd(); } Icosahedron void Subdivide(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3], int depth) { if (depth == 0) { glColor3f(0.5,0.5,0.5); glBegin(GL_TRIANGLES); glVertex3fv(v1); glVertex3fv(v2); glVertex3fv(v3); glEnd(); } else { GLfloat v12[3], v23[3], v31[3]; for (int i = 0; i < 3; i++) { v12[i] = (v1[i]+v2[i])/2.0; v23[i] = (v2[i]+v3[i])/2.0; v31[i] = (v3[i]+v1[i])/2.0; } Normalize(v12); Normalize(v23); Normalize(v31); } void Subdivide(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3], int depth) { if (depth == 0) { glColor3f(0.5,0.5,0.5); glBegin(GL_TRIANGLES); glVertex3fv(v1); glVertex3fv(v2); glVertex3fv(v3); glEnd(); } else { GLfloat v12[3], v23[3], v31[3]; for (int i = 0; i < 3; i++) { v12[i] = (v1[i]+v2[i])/2.0; v23[i] = (v2[i]+v3[i])/2.0; v31[i] = (v3[i]+v1[i])/2.0; } Normalize(v12); Normalize(v23); Normalize(v31); } Icosahedron void Subdivide(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3], int depth) { if (depth == 0) { glColor3f(0.5,0.5,0.5); glBegin(GL_TRIANGLES); glVertex3fv(v1); glVertex3fv(v2); glVertex3fv(v3); glEnd(); } else { GLfloat v12[3], v23[3], v31[3]; for (int i = 0; i < 3; i++) { v12[i] = (v1[i]+v2[i])/2.0; v23[i] = (v2[i]+v3[i])/2.0; v31[i] = (v3[i]+v1[i])/2.0; } Normalize(v12); Normalize(v23); Normalize(v31); Subdivide(v1, v12, v31, depth-1); Subdivide(v2, v23, v12, depth-1); Subdivide(v3, v31, v23, depth-1); Subdivide(v12, v23, v31, depth-1); } void Subdivide(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3], int depth) { if (depth == 0) { glColor3f(0.5,0.5,0.5); glBegin(GL_TRIANGLES); glVertex3fv(v1); glVertex3fv(v2); glVertex3fv(v3); glEnd(); } else { GLfloat v12[3], v23[3], v31[3]; for (int i = 0; i < 3; i++) { v12[i] = (v1[i]+v2[i])/2.0; v23[i] = (v2[i]+v3[i])/2.0; v31[i] = (v3[i]+v1[i])/2.0; } Normalize(v12); Normalize(v23); Normalize(v31); Subdivide(v1, v12, v31, depth-1); Subdivide(v2, v23, v12, depth-1); Subdivide(v3, v31, v23, depth-1); Subdivide(v12, v23, v31, depth-1); } So far Fixed Camera location => Change Camera location Single object => Multiple objects Examples of multiple objects 3D Geometry Pipeline Model Space (Object Space) World Space Eye Space (View Space) Canonical View Space Screen Space (2D) Image Space (pixels) Raster Space 3D Geometry Pipeline Model Space (Object Space) World Space Eye Space (View Space) Model Transformation Screen Space (2D) View Transformation Image Space (pixels) Raster Space 3D Geometry Pipeline Model Space (Object Space) Eye Space (View Space) Model View Transformation Screen Space (2D) Image Space (pixels) Raster Space View port Transformation Projection 3D Geometry Pipeline Model Space (Object Space) Eye Space (View Space) Model View Transformation Screen Space (2D) Image Space (pixels) Raster Space View port Transformation Projection glMatrixMode(GL_MODELVIEW) glLoadIdentity(); glRotate(); glMatrixMode(GL_MODELVIEW) glLoadIdentity(); glRotate(); glMatrixMode(GL_Projection) glLoadIdentity(); glFrustum(); glMatrixMode(GL_Projection) glLoadIdentity(); glFrustum(); glViewport(); Cube.cpp Event-Driven Programming Window management library GLUT / FLTK Window management library GLUT / FLTK Events: key strokes, mouse clicks Event handlers: mouse(), display(), reshape() Event handlers: mouse(), display(), reshape() Cube.cpp int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (500, 500); glutInitWindowPosition (100, 100); glutCreateWindow (argv[0]); init (); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMainLoop(); return 0; } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (500, 500); glutInitWindowPosition (100, 100); glutCreateWindow (argv[0]); init (); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMainLoop(); return 0; } void keyboard(unsigned char key, int x, int y) { switch (key) { case 27: //correspond to ESC exit(0); break; } void keyboard(unsigned char key, int x, int y) { switch (key) { case 27: //correspond to ESC exit(0); break; } Cube.cpp int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (500, 500); glutInitWindowPosition (100, 100); glutCreateWindow (argv[0]); init (); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMainLoop(); return 0; } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (500, 500); glutInitWindowPosition (100, 100); glutCreateWindow (argv[0]); init (); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMainLoop(); return 0; } void reshape (int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0); } void reshape (int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0); } Cube.cpp int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (500, 500); glutInitWindowPosition (100, 100); glutCreateWindow (argv[0]); init (); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMainLoop(); return 0; } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (500, 500); glutInitWindowPosition (100, 100); glutCreateWindow (argv[0]); init (); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMainLoop(); return 0; } void display(void) { glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 1.0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /* clear the matrix */ /* viewing transformation */ gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glScalef(1.0, 2.0, 1.0); /* modeling transformation */ glutWireCube(1.0); glFlush(); } void display(void) { glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 1.0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /* clear the matrix */ /* viewing transformation */ gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glScalef(1.0, 2.0, 1.0); /* modeling transformation */ glutWireCube(1.0); glFlush(); } Modeling Transformation glTranslatef(float x, float y, float z) glRotatef(float angle, float x, float y, float z) glScalef(2.0, -0.5, 1.0) glScalef(float x, float y, float z) General Modeling Transform glLoadIdentify() glLoadMatrixf(float *M) glMultiMatrixf(float *M) double M[4][4]; M[2][1] corresponds to??? M[10] Matrix Chain glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMultMatrixf(N); /* apply transformation N */ glMultMatrixf(M); /* apply transformation M */ glMultMatrixf(L); /* apply transformation L */ glBegin(GL_POINTS); glVertex3f(v); /* draw transformed vertex v */ glEnd(); /* which is (N*(M*(L*v))) */ glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMultMatrixf(N); /* apply transformation N */ glMultMatrixf(M); /* apply transformation M */ glMultMatrixf(L); /* apply transformation L */ glBegin(GL_POINTS); glVertex3f(v); /* draw transformed vertex v */ glEnd(); /* which is (N*(M*(L*v))) */ Matrix Chain glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMultMatrixf(V); glMultMatrixf(R); glMultMatrixf(T); glBegin(GL_POINTS); glVertex3f(v); glEnd(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMultMatrixf(V); glMultMatrixf(R); glMultMatrixf(T); glBegin(GL_POINTS); glVertex3f(v); glEnd(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookat(); glRotatef(); glTranslatef(); glBegin(GL_POINTS); glVertex3f(v); glEnd(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookat(); glRotatef(); glTranslatef(); glBegin(GL_POINTS); glVertex3f(v); glEnd(); gluLookAt gluLookAt( float eyex, float eyey, float eyez, float px, float py, float pz, float upx, float upy, float upz ) gluLookAt( float eyex, float eyey, float eyez, float px, float py, float pz, float upx, float upy, float upz ) 1.Give eye location e 2.Give target position p 3.Give upward direction u gluLookAt glFrustum glFrustum(double left, double right, double bottom, double top, double near, double far) gluPerspective gluPerspective(double fovy, double aspect, double zNear, double zFar) gluPerspective Orthographic Projection glOrtho(double left, double right, double bottom, double top, double near, double far); Viewport Transformation glViewport(int x, int y, int width, int height); glFrustum(double left, double right, double bottom, double top, double near, double far) gluPerspective(double fovy, double aspect, double zNear, double zFar) glFrustum(double left, double right, double bottom, double top, double near, double far) gluPerspective(double fovy, double aspect, double zNear, double zFar) Revisit cube.cpp int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (500, 500); glutInitWindowPosition (100, 100); glutCreateWindow (argv[0]); init (); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMainLoop(); return 0; } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (500, 500); glutInitWindowPosition (100, 100); glutCreateWindow (argv[0]); init (); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMainLoop(); return 0; } void reshape (int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0); } void reshape (int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0); } void display(void) { glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 1.0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /* clear the matrix */ /* viewing transformation */ gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glScalef(1.0, 2.0, 1.0); /* modeling transformation */ glutWireCube(1.0); glFlush(); } void display(void) { glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 1.0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /* clear the matrix */ /* viewing transformation */ gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glScalef(1.0, 2.0, 1.0); /* modeling transformation */ glutWireCube(1.0); glFlush(); } Connecting primitives glLoadIdentity(); draw_block_A(); glTranslate(0, h, 0); Draw_block_B(); glLoadIdentity(); draw_block_A(); glTranslate(0, h, 0); Draw_block_B(); glLoadIdentity(); draw_block_A(); glTranslate(0, h, 0); glRotate(-90, 0, 0, 1); Draw_block_B(); glLoadIdentity(); draw_block_A(); glTranslate(0, h, 0); glRotate(-90, 0, 0, 1); Draw_block_B(); A B 3D Example: A robot arm Consider this robot arm with 3 degrees of freedom: Base rotates about its vertical axis by Upper arm rotates in its xy-plane by Lower arm rotates in its xy-plane by h1h1 h2h2 h3h3 Base Upper arm Lower arm Q: What matrix do we use to transform the base to the world? R_y( ) Q: What matrix for the upper arm to the base? T(0,h1,0)R_z( ) Q: What matrix for the lower arm to the upper arm? T(0,h2,0)R_z( ) z x y x y x Robot arm implementation The robot arm can be displayed by keeping a global matrix and computing it at each step: Matrix M_model; display(){... robot_arm();... } robot_arm() { M_model = R_y(theta); base(); M_model = R_y(theta)*T(0,h1,0)*R_z(phi); upper_arm(); M_model = R_y(theta)*T(0,h1,0)*R_z(phi)*T(0,h2,0)*R_z(psi); lower_arm(); } Matrix M_model; display(){... robot_arm();... } robot_arm() { M_model = R_y(theta); base(); M_model = R_y(theta)*T(0,h1,0)*R_z(phi); upper_arm(); M_model = R_y(theta)*T(0,h1,0)*R_z(phi)*T(0,h2,0)*R_z(psi); lower_arm(); } Do the matrix computations seem wasteful? How to translate the whole robot? Q: What matrix do we use to transform the base to the world? R_y( ) Q: What matrix for the upper arm to the base? T(0,h1,0)R_z( ) Q: What matrix for the lower arm to the upper arm? T(0,h2,0)R_z( ) Q: What matrix do we use to transform the base to the world? R_y( ) Q: What matrix for the upper arm to the base? T(0,h1,0)R_z( ) Q: What matrix for the lower arm to the upper arm? T(0,h2,0)R_z( ) Instead of recalculating the global matrix each time, we can just update it in place by concatenating matrices on the right: Robot arm implementation, better Matrix M_model; display(){... M_model = identity; robot_arm();... } robot_arm() { M_model *= R_y(theta); base(); M_model *= T(0,h1,0)*R_z(phi); upper_arm(); M_model *= T(0,h2,0)*R_z(psi); lower_arm(); } Matrix M_model; display(){... M_model = identity; robot_arm();... } robot_arm() { M_model *= R_y(theta); base(); M_model *= T(0,h1,0)*R_z(phi); upper_arm(); M_model *= T(0,h2,0)*R_z(psi); lower_arm(); } OpenGL maintains the model-view matrix, as a global state variable which is updated by concatenating matrices on the right. display() {... glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); robot_arm();... } robot_arm() { glRotatef( theta, 0.0, 1.0, 0.0 ); base(); glTranslatef( 0.0, h1, 0.0 ); glRotatef( phi, 0.0, 0.0, 1.0 ); lower_arm(); glTranslatef( 0.0, h2, 0.0 ); glRotatef( psi, 0.0, 0.0, 1.0 ); upper_arm(); } display() {... glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); robot_arm();... } robot_arm() { glRotatef( theta, 0.0, 1.0, 0.0 ); base(); glTranslatef( 0.0, h1, 0.0 ); glRotatef( phi, 0.0, 0.0, 1.0 ); lower_arm(); glTranslatef( 0.0, h2, 0.0 ); glRotatef( psi, 0.0, 0.0, 1.0 ); upper_arm(); } Robot arm implementation, OpenGL Hierarchical modeling Hierarchical models can be composed of instances using trees: edges contain geometric transformations nodes contain geometry (and possibly drawing attributes) How might we draw the tree for the robot arm? A complex example: human figure Q: Whats the most sensible way to traverse this tree? Human figure implementation, OpenGL figure() { torso(); glPushMatrix(); glTranslate(... ); glRotate(... ); head(); glPopMatrix(); glPushMatrix(); glTranslate(... ); glRotate(... ); left_upper_arm(); glPushMatrix(); glTranslate(... ); glRotate(... ); left_lower_arm(); glPopMatrix();... } figure() { torso(); glPushMatrix(); glTranslate(... ); glRotate(... ); head(); glPopMatrix(); glPushMatrix(); glTranslate(... ); glRotate(... ); left_upper_arm(); glPushMatrix(); glTranslate(... ); glRotate(... ); left_lower_arm(); glPopMatrix();... }