Transformation, Input and Interaction Hanyang University
Transformation, projection, viewing
Pipeline of transformations Standard sequence of transforms Cornell CS4620 Fall 2008 Lecture 8 3 2008 Steve Marschner
Homogeneous Coordinate System Multiple geometric transformations such as translation, rotation scaling and perspective projection can be represented as a single matrix.
The transformation pipeline The modelview matrix transforms vertex data from the object coordinates to the eye coordinates. The eye coordinates are multiplied by the projection matrix to yield clip coordinates. The transformed vertex (x, y, z) is clipped by comparing with ±w. Perspective division normalizes the range of the vertex from -1 to 1 in all 3 axes. Normalized view volume The normalized device coordinates are scaled and translated in order to fit into the rendering screen(viewport transformation).
Matrix functions void glmatrixmode(glenum mode) glmatrixmode specifies the current operation matrix. mode GL_MODELVIEW» The matrix operations are applied to the modelview matrix stack. GL_PROJECTION» The matrix operations are applied to the projection matrix stack. GL_TEXTURE» The matrix operations are applied to the texture matrix stack.» This is used to transform the texture coordinates. void glloadidentity() This function loads the current matrix with the identity matrix. glmatrixmode(gl_modelview); glloadidentity();
Matrix functions void glloadmatrixf(const GLfloat *M) An arbitrary column-major matrix can be loaded into the current matrix by using this function. void glmultmatrixf(const GLfloat *M) The current matrix is multiplied with the 4x4 column-major matrix M and the result is stored into the current matrix. glmatrixmode(gl_modelview); float m[] = 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f ; glloadmatrixf(m); glmultimatrixf(m);
OpenGL matrices 4x4 column major matrices are used for 3D geometric transformation in OpenGL (homogeneous coordinate system). The current transformation matrix that is part of the state and is applied to all vertices that pass down the pipeline. The current transformation matrix is formed by multiplying together rotation, translation, and scaling matrices. Because the same transformation is applied to many vertices, the cost of forming a matrix M=ABCD is not significant compared to the cost of computing Mp for many vertices p.
Transformation functions void gltranslatef(glfloat dx, GLfloat dy, GLfloat dz) multiply the current matrix by a translation matrix. dx, dy, dz : the x, y, and z coordinates of a translation vector. C=C*T where C is the current matrix, T is the translation matrix void glscalef(glfloat sx, GLfloat sy, GLfloat sz) multiply the current matrix by a general scaling matrix. sx, sy, sz : scale factors along the x, y, and z axes, respectively. void glrotatef(glfloat angle, GLfloat x, GLfloat y, GLfloat z) multiply the current matrix by a rotation matrix. angle : the angle of rotation, in degrees. x, y, z : the x, y, and z coordinates of a vector (the axis of rotation)
Representing objects Objects represented as symbols Defined in model coordinates; transformed into world coordinates (M = TRS) glmatrixmode(gl_modelview); glloadidentity(); gltranslatef( ); glrotatef( ); glscalef( ); glutsolidcylinder( ); April 14, 2016 10
Transformation functions The last matrix specified in the program is the first applied. glmatrixmode(gl_modelview); glloadidentity(); glrotatef(45.0, 0.0, 0.0, 1.0); gltranslatef(0.5, -0.5, 0.0); glutsolidcube(0.3); glmatrixmode(gl_modelview); glloadidentity(); gltranslatef(0.707, 0.0, 0.0); glrotatef(45.0, 0.0, 0.0, 1.0); glutsolidcube(0.3);
Example modelview transformation void MyDisplay() glclear(gl_color_buffer_bit); glviewport(0, 0, 300, 300); glmatrixmode(gl_modelview); // red rectangle glcolor3f(1.0, 0.0, 0.0); glloadidentity(); glutsolidcube(0.3); // green rectangle glcolor3f(0.0, 1.0, 0.0); glloadidentity(); glrotatef(45.0, 0.0, 0.0, 1.0); gltranslatef(0.6, 0.0, 0.0); glutsolidcube(0.3); // blue rectangle glcolor3f(0.0, 0.0, 1.0); glloadidentity(); gltranslatef(0.6, 0.0, 0.0); glrotatef(45.0, 0.0, 0.0, 1.0); glutsolidcube(0.3); glflush(); int main(int argc, char** argv) glutinitdisplaymode(glut_rgba); glutinitwindowsize(300, 300); glutcreatewindow("opengl Sample Drawing"); glclearcolor(1.0, 1.0, 1.0, 1.0); glmatrixmode(gl_projection); glloadidentity(); glortho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); glutdisplayfunc(mydisplay); glutmainloop(); return 0; The final appearance of scene or object depends on the order in which the transformations are applied.
Viewport and ortho glviewport glviewport specifies the area (viewport) within the window in actual screen coordinates that OpenGL can use to draw in. glviewport(glint x, GLint y, GLsizei width, GLsizei height); x, y : specifiy the lower left corner of the viewport rectangle. width, height : specify the width and height of the viewport. EX ) glutinitwindowsize(400, 300); glviewport(100, 80, 160, 100); 400 (window width) y = 80 origin x = 100 Viewport width = 160 heigh t = 100 300 (window height)
Viewport and ortho glortho glortho sets the view cube for orthographic projection. glortho( axis GLdouble left, GLdouble right, // the range of the x- GLdouble bottom, GLdouble top, // the range of the y- axis axis ); GLdouble near, GLdouble far // the range of the z- Default setting : normalized view volume glortho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); (right, top, far) (left, bottom, near) vie w
Example source (glut) #include <gl/glut.h> void MyDisplay() glclear(gl_color_buffer_bit); glviewport(100, 100, 200, 200); glbegin(gl_quads); // red glcolor3f(1.0, 0.0, 0.0); glvertex3f(0, 0, 0.0); glvertex3f(640, 0, 0.0); glvertex3f(640, 480, 0.0); glvertex3f(0, 480, 0.0); // gray glcolor3f(0.5, 0.5, 0.5); glvertex3f(160, 120, 0.0); glvertex3f(480, 120, 0.0); glvertex3f(480, 360, 0.0); glvertex3f(160, 360, 0.0); glend(); glflush(); int main(int argc, char** argv) glutinitdisplaymode(glut_rgb); glutinitwindowsize(640, 480); glutinitwindowposition(0, 0); glutcreatewindow("opengl Drawing Example"); // Red, Green, Blue, Alpha glclearcolor(1.0, 1.0, 1.0, 1.0); glmatrixmode(gl_projection); // GL_MODELVIEW, GL_PROJECTION glloadidentity(); glortho(0.0, 640.0, 0.0, 480.0, -1.0, 1.0); glutdisplayfunc(mydisplay); glutmainloop(); return 0;
1 6 Input and Interaction Setting the area within the window and 3D space to draw. Setting various callback functions to make interactive programs, animations Reshape Callback Keyboard Callback SpecialKey Callback Mouse Callback Menu Callback Timer Callback
Example Source #include <gl/glut.h> GLint TopLeftX, TopLeftY, BottomRightX, BottomRightY; void MyDisplay() glviewport(0, 0, 300, 300); glclear(gl_color_buffer_bit); glcolor3f(0.5, 0.5, 0.5); glbegin(gl_polygon); glvertex3f(topleftx / 300.0, (300 - TopLeftY) / 300.0, 0.0); glvertex3f(topleftx / 300.0, (300 - BottomRightY) / 300.0, 0.0); glvertex3f(bottomrightx / 300.0, (300 - BottomRightY) / 300.0, 0.0); glvertex3f(bottomrightx / 300.0, (300 - TopLeftY) / 300.0, 0.0); glend(); glflush(); An example to draw a rectangle by clicking and dragging the left button of mouse
Example Source (cont d) void MyMouseClick(GLint Button, GLint State, GLint X, GLint Y) if(button == GLUT_LEFT_BUTTON && State == GLUT_DOWN) TopLeftX = X; TopLeftY = Y; void MyMouseMove(GLint X, GLint Y) BottomRightX = X; BottomRightY = Y; glutpostredisplay(); // marks the current window as needing to be redisplayed. int main(int argc, char** argv) glutinitwindowsize(300, 300); glutcreatewindow("opengl Drawing Example"); glclearcolor(1.0, 1.0, 1.0, 1.0); glmatrixmode(gl_projection); glloadidentity(); glortho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0); glutdisplayfunc(mydisplay); glutmousefunc(mymouseclick); glutmotionfunc(mymousemove); glutmainloop(); return 0;
glortho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0); => =>!= Map window coordinate into OpenGL coordinate v1x = TopLeftX / 300; v1y = (300 - TopLeftY) / 300; v2x = TopLeftX / 300; v2y = (300 - BottomRightY) / 300; v3x = BottomRightX / 300; v3y = (300 - BottomRightY) / 300; v4x = BottomRightX / 300; v4y = (300 - TopLeftY) / 300;
Compiling GLUT apps Linux (debian) sudo apt-get install freeglut3-dev Windows Download freeglut windows MSVC binary Mac sudo port install freeglut (or you can use brew instead) Use the CMakeLists.txt the same way as we compiled GLFW apps.
# -*- mode: cmake; -*- project(ogrefltk) CMakeLists.txt if(unix) set(cmake_c_flags_debug "$CMAKE_C_FLAGS_DEBUG -D_DEBUG -Wall") set(cmake_cxx_flags_debug "$CMAKE_CXX_FLAGS_DEBUG -D_DEBUG -Wall") else() include_directories( $OgreFltk_SOURCE_DIR/freeglut/include ) endif() add_executable(ogrefltk "practice3_1.cpp" ) if(unix) target_link_libraries(ogrefltk GL GLU glut ) else() target_link_libraries(ogrefltk OpenGL32.lib glu32.lib "$OgreFltk_SOURCE_DIR/lib/freeglut.lib" ) endif()
Matrix stacks OpenGL maintains stacks for each type of matrix. It is able to save the current transformation state and then restore it after some objects have been placed. It is useful for traversing hierarchical data structures (scene graph or tree) void glpushmatrix () Pushes the current matrix onto the stack. void glpopmatrix () Pops the matrix off the stack.
Example Solar system Solar system animation using timer callback function
Example Solar system (cont d) #include <gl/freeglut.h>jj #include <gl/glu.h> #include <gl/gl.h> static int Day = 0, Time = 0; void MyDisplay() glclear(gl_color_buffer_bit GL_DEPTH_BUFFER_BIT); glenable(gl_depth_test); glmatrixmode(gl_modelview); glloadidentity(); gltranslatef(0.0, 0.0, -2.0); /***The earth***/ glpushmatrix(); // 지구의공전 glrotatef((float)day, 0.0, 1.0, 0.0); gltranslatef(0.7, 0.0, 0.0); // 지구의자전 glrotatef((float)time, 0.0, 1.0, 0.0); glcolor3f(0.5, 0.6, 0.7); glutsolidsphere(0.1, 30, 8); /***The moon***/ glpushmatrix(); // 달의공전 glrotatef((float)time, 0.0, 1.0, 0.0); gltranslatef(0.2, 0.0, 0.0); glcolor3f(0.9, 0.8, 0.2); glutsolidsphere(0.04, 30, 8); glpopmatrix(); glpopmatrix(); /***The sun***/ glcolor3f(1.0, 0.3, 0.4); glutsolidsphere(0.2, 30, 16); glutswapbuffers(); void MyTimer(int value) Day = (Day + 10) % 360; Time = (Time + 5) % 360; gluttimerfunc(100, MyTimer, 1); glutpostredisplay(); int main(int argc, char** argv) glutinit(&argc, argv); glutinitdisplaymode(glut_double GLUT_RGB GLUT_DEPTH); glutinitwindowsize(500, 500); glutcreatewindow("solar system"); glclearcolor(0.0, 0.0, 0.0, 0.0); glmatrixmode(gl_projection); glloadidentity(); glortho(-1.0, 1.0, -1.0, 1.0, -1.0, 3.0); glutdisplayfunc(mydisplay); gluttimerfunc(100, MyTimer, 1); glutmainloop(); return 0;
Example - Rotate an object using mouse
#include <gl/glut.h> bool bdrag = false; float g_fdistance = -300.0f; float g_fspinx = 0.0f; float g_fspiny = 0.0f; int ptlastmousepositx, ptlastmouseposity; int ptcurrentmousepositx, ptcurrentmouseposity; void ChangeSize(GLsizei width, GLsizei height) GLfloat faspect = (GLfloat)width/(GLfloat)height; GLfloat nrange = height/4.0; if(height == 0) height = 1; glviewport(0, 0, width, height); glmatrixmode(gl_projection); glloadidentity(); if (width <= height) glortho (-nrange, nrange, -nrange/faspect, nrange/faspect, -nrange*4.0f, nrange*4.0f); else glortho (-nrange*faspect, nrange*faspect, -nrange, nrange, -nrange*4.0f, nrange*4.0f); glmatrixmode(gl_modelview); glloadidentity(); void MyMouseClick(GLint Button, GLint State, GLint X, GLint Y) if(button == GLUT_LEFT_BUTTON ) if (State == GLUT_DOWN) ptlastmousepositx = ptcurrentmousepositx = X; ptlastmouseposity = ptcurrentmouseposity = Y; bdrag = true; else if (State == GLUT_UP) bdrag = false;
void MyMouseMove(GLint X, GLint Y) ptcurrentmousepositx = X; ptcurrentmouseposity = Y; if( bdrag ) g_fspinx -= (ptcurrentmousepositx - ptlastmousepositx); g_fspiny -= (ptcurrentmouseposity - ptlastmouseposity); ptlastmousepositx = ptcurrentmousepositx; ptlastmouseposity = ptcurrentmouseposity; glutpostredisplay(); void RenderScene(void) glclear(gl_color_buffer_bit GL_DEPTH_BUFFER_BIT); glpushmatrix(); gltranslatef(0.0f, 0.0f, g_fdistance); glrotatef( -g_fspiny, 1.0f, 0.0f, 0.0f ); glrotatef( -g_fspinx, 0.0f, 1.0f, 0.0f ); glcolor3f(0.0f, 1.0f, 0.0f); glutwireteapot(100.0); glpopmatrix(); glutswapbuffers(); int main(int argc, char *argv[]) glutinit(&argc, argv); glutinitdisplaymode(glut_double GLUT_RGB GLUT_DEPTH); glutinitwindowsize(600, 600); glutcreatewindow( Rotate an object using mouse"); glutreshapefunc(changesize); glutmousefunc(mymouseclick); glutmotionfunc(mymousemove); glutdisplayfunc(renderscene); glutmainloop(); return 0;
Orthographic projection Projectors are orthogonal to projection surface. void glortho(gldouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble znear, GLdouble zfar) frustum far plane near plane image plane
Perspective projection Projectors converge at center of projection. frustum near plane far plane viewpoint image plane
Perspective projection void glfrustum(gldouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble znear, GLdouble zfar) void gluperspective(gldouble fovy, GLdouble aspect, GLdouble znear, GLdouble zfar)
Example orthogonal and perspective projections Orthogonal projection Perspective projection
Example orthogonal and perspective projections (cont d) #include <gl/glut.h> static GLfloat xrot = 0.0f; static GLfloat yrot = 0.0f; static int width, height; bool bperspective = true; void SetProjection() GLfloat faspect = (GLfloat)width/(GLfloat)height; GLfloat nrange = height/4.0; if(height == 0) height = 1; glviewport(0, 0, width, height); glmatrixmode(gl_projection); glloadidentity(); if (bperspective) gluperspective(60.0f, faspect, 1.0, 400.0); else if (width <= height) glortho (-nrange, nrange, -nrange/faspect, nrange/faspect, -nrange*4.0f, nrange*4.0f); else glortho (-nrange*faspect, nrange*faspect, -nrange, nrange, -nrange*4.0f, nrange*4.0f); glmatrixmode(gl_modelview); glloadidentity();
Example orthogonal and perspective projections (cont d) void ChangeSize(GLsizei w, GLsizei h) width = w; height = h; SetProjection(); void SpecialKeys(int key, int x, int y) if(key == GLUT_KEY_UP) if(key == GLUT_KEY_DOWN) if(key == GLUT_KEY_LEFT) if(key == GLUT_KEY_RIGHT) xrot-= 5.0f; xrot += 5.0f; yrot -= 5.0f; yrot += 5.0f; xrot = (GLfloat)((const int)xrot % 360); yrot = (GLfloat)((const int)yrot % 360); if (key == GLUT_KEY_F1) bperspective =!bperspective; SetProjection(); glutpostredisplay();
Example orthogonal and perspective projections (cont d) void RenderScene(void) glclear(gl_color_buffer_bit GL_DEPTH_BUFFER_BIT); glpushmatrix(); gltranslatef(0.0f, 0.0f, -300.0f); glrotatef(xrot, 1.0f, 0.0f, 0.0f); glrotatef(yrot, 0.0f, 1.0f, 0.0f); glcolor3f(1.0f, 0.0f, 0.0f); glutwirecube(100.0); glpopmatrix(); glutswapbuffers(); int main(int argc, char *argv[]) glutinit(&argc, argv); glutinitdisplaymode(glut_double GLUT_RGB GLUT_DEPTH); glutinitwindowsize(600, 600); glutcreatewindow("perspective Projection"); glutreshapefunc(changesize); glutspecialfunc(specialkeys); glutdisplayfunc(renderscene); glutmainloop(); return 0;
The LookAt function void glulookat(gldouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy, Gldouble upz) Eye : the position of the eye point. Center : the position of the reference point. Up : the direction of the up vector. glulookat creates a viewing matrix derived from an eye point, a reference point indicating the center of the scene, and an UP vector. center x, center y, center z
Camera object example Reference http://titan.cs.ukzn.ac.za/opengl/opengl-d7/2006notes/camera_class_%20for_opengl.ppt Camera object The transformation matrix is formed by up, forward, along vector and position. Not using glulookat, glrotate, gltranslation up, forward, along vectors are orthogonal. up, forward, along vectors are updated when camera is moved.
Camera object example (cont d) struct Vector3D float x; float y; float z; ; class Camera private: Vector3D Position; Vector3D Along; Vector3D Up; Vector3D Forward; public: theta); theta); ; void Pitch(GLfloat void Yaw(GLfloat theta); void Roll(GLfloat void Update();...
Practice HW1 Modify practice3_2_smooth.cpp to add the Mars Assume (without scientific basis) that The Mars are twice as far as the Earth from the Sun The Mars self-rotates twice faster than the Earth The Mars has two times longer orbital period than the Earth Color the Sun yellow, the Mars red, and the Earth blue You probably need to extend the size of the view volume Submit the entire set of sources and CMakeLists.txt to teddysiah@naver.com E-mail title: your student id::your name Practice HW1 Please strictly obey the title format. Otherwise, it might not be evaluated.