Chapter 4 2-D Transformations Cartesian coordinates Linear transformations, affine transformations Homogeneous coordinates Translations Scaling Rotation Reflection Combinations of transformations Animations 1 Cartesian coordinates A 2D point is represented by a 2-tuple For convenience, the 2-tuple often written as (x, y). x y . A 2-tuple can also be interpreted as a vector. The 2-tuple defines the direction and length of the vector, but not the position. (x, y) y x (x, y) y x 2 Translation A translation moves a point to a new position by adding a displacement vector to it. x' x Tx y' y T . y x' x Tx , y' y Ty Eg, The following translates the point 3 13 to 7 7 (3,13) 7 3 4 7 13 6 4 6 (7,7) 3 Linear Transformations A linear transformation moves a point to a new position by multiplying it with a non-singular matrix. x' a b x y' c d y . x' ax by, y' cx dy Eg, The following transforms the point (2, 3) to (3, 13) (3,13) 3 0 1 2 13 2 3 3 0 1 2 3 (2,3) A non-singular matrix, M, has the inverse M-1 such that MM-1 =M-1M= I. It denotes an one-to-one mapping. 4 Affine Transformations An affine transformation is a linear transformation followed by a translation. Its 2D general form is x' a b x Tx y ' c d y T y Affine transformations preserve lines. Many geometric movements of objects, eg, translations, rotations, and scalings are affine transformations. 5 Homogeneous coordinates A point in homogeneous coordinates (x, y, w), w ≠ 0, corresponds to the 2D point (x/w, y/w) in Cartesian coordinates. Conceive that the Cartesian coordinates axes lies on the plane of w = 1. The intersection of the plane and the line connecting the origin and (x, y, w) gives the corresponding Cartesian coordinates. w (x, y, w) y y (x/w, y/w, 1) x w=1 x w=0 For example, both the points (6, 9, 3) and (4, 6, 2) in the homogeneous coordinates corresponds to (2, 3) in the Cartesian coordinates. Conversely, the point (2, 1) of the Cartesian corresponds to (2, 1, 1), (4, 2, 2) or (6, 3, 3) of the homogeneous Homogeneous coordinates are used in many graphics systems because all practical transformations can be expressed as matrix multiplications. Such uniformity enhances efficiency. 7 Translation move an object to a new position (3,4) (1,3) (x’, y’) (x,y) (7,2) (5,1) (3,2) (1,1) The coord. of the new position: x’ = x + 2, In general, x’ = x + Tx, y’ = y + Ty In homogeneous coordinates x' 1 0 Tx x 1 0 2 5 7 y ' 0 1 T y . Eg, 0 1 1 1 2 y w' 0 0 1 w 0 0 1 1 1 y’ = y + 1 8 Scaling relative to the origin (changing size) (1,3) (x’, y’) (x,y) (2,3/2) (5,1) (1,1) (10,1/2) (2,1/2) The new position: x’ = 2x, y’ = y/2 In general, x’ = Sx x, y’ = Sy y In homogeneous coordinates x' S x y' 0 w' 0 0 Sy 0 0 x 2 0 y . Eg, 0 0 1 w 0 1 2 0 0 1 2 0 3 3 2 1 1 1 9 Rotation about the origin (x’,y’) r r (x,y) x=r cos The angle, , is measured from the original vector to the new one in counterclockwise. The parameters of sin() and cos() are provided in radians. radians is 180o. In Cartesian, x’ = r cos(+) = r cos cos r sin sin = x cos - y sin y’ = r sin(+) = r sin cos + r cos sin = x sin + y cos 10 Eg, to rotate 45o (/4 radian) (2.8, 4.2) (1,3) (-1.4, 2.8) (x,y) (x’, y’) (0,1.4) (5,1) (1,1) sin /4 = cos /4 = 0.7071 x’ = x cos - y sin = 0.7071 (x - y) y’ = x sin + y cos = 0.7071 (x + y) In homogeneous coordinates x' cos y ' sin w' 0 sin cos 0 0 x .707 .707 0 5 2.8 0 y . Eg, .707 .707 0 1 4.2 0 1 w 0 1 1 1 11 Conduct a sequence of transformations Translate the right-angle vertex to the origin (Tx = -1, Ty = -1) (1,3) x ' 1 0 T x x y ' 0 1 T y . y w' 0 0 1 w (5,1) (1,1) (0,2) Rotate 45o (/4 radian) sin /4 = cos /4 = 0.7071 x" cos y" sin w" 0 sin cos 0 (0,0) 0 x ' 0 y ' 1 w' (-1.4,1.4) (4,0) (2.8,2.8) x" cos sin 0 x' cos sin y" sin cos 0 y ' sin cos w" 0 0 1 w' 0 0 cos sin Tx cos T y sin x sin cos Tx sin T y cos y 0 w 0 1 0 1 0 Tx x 0 0 1 T y y 1 0 0 1 w The computation of [ ] from [ ] [ ] is called matrix multiplication. The general form is: a b e c d g f ae bg af bh h ce dg cf dh A sequence of transformations can be lumped in a single matrix via matrix multiplications 13 In OpenGL, all the model transformations are accumulated in the current transformation matrix (CTM). All vertices of an object will be transformed via this matrix before the object is drawn. Vertices * * * * * * * * * Vertices CTM Stack A system stack is provided for storing the backup copies of the CTM during execution. We usually save the CTM in the stack before the drawing of a transformed object. And restore the original CTM afterwards. 14 Vertices * * * * * * * * * Vertices CTM * * * * * * * * * .. . (before) Stack To save a copy of the CTM in the stack glPushMatrix(); Vertices * * * * * * * * * CTM (after) * * * * * * * * * Vertices * * * * * * * * * .. . Stack 15 Vertices * * * * * * * * * Vertices * * * * * * * * * * * * * * * * * * CTM (before) . . . Stack To overwrite the CTM with the top matrix in the stack glPopMatrix(); Vertices * * * * * * * * * CTM (after) Vertices * * * * * * * * * . . . Stack 16 To specify a translation glTranslatef( double Tx, double Ty, 0.0) The system first generates the matrix representing the translation. Then post multiplies this matrix with the CTM. Finally overwrites the CTM with the result. Vertices * * * * * * * * * CTM Vertices * * * * * * * * * CTM Vertices 1 0 Tx 0 1 Ty 0 0 1 Before After Vertices 17 Example //draw a white head at (0,0) glColor3f( 1.0, 1.0, 1.0); draw_head(); //draw a green head at (-2,-1) glColor3f( 0.0, 1.0, 0.0); glPushMatrix(); glTranslatef( -2.0, -1.0, 0.0); draw_head(); glPopMatrix(); Progressive Translation glColor3f( 1.0, 1.0, 1.0); //draw a title hkgluBitMapString( -1.9, 1.8, "Translation of (-2, -1)” ); 18 To specify a scaling glScalef( double Sx, double Sy, 1.0) Generate a matrix for the scaling. Post multiply it with the CTM //Scale by Sx = 1.5, Sy = 2 glPushMatrix(); glScalef( 1.5, 2.0, 1.0); draw_head(); glPopMatrix(); Progressive Scaling In general, an object moves away from the origin when scaled up, moves towards when scaled down 19 To specify a rotation glRotatef( double degree, 0.0, 0.0, 1.0) glPushMatrix(); glRotatef( 45.0, 0.0, 0.0, 1.0); draw_head(); glPopMatrix(); (Note that the angles provided to gl functions are expressed in degrees instead of radians.) Progressive Rotation 20 First to scale( Sx =1.5, Sy =2) and then translate the picture to (-2, -1). x' Sx y' 0 w' 0 x" 1 y" 0 w" 0 Vertices 0 x Sy 0 y 0 1 z 0 Tx x' 1 0 Tx Sx 0 0 x 1 Ty y ' 0 1 Ty 0 Sy 0 y 0 1 z ' 0 0 1 0 0 1 z 0 * * * * * * * * * CTM Vertices 1 0 Tx 0 1 Ty 0 0 1 Sx 0 0 0 Sy 0 0 0 1 Note that the transformations are specified in reverse order: first call glTranslatef(...), and then glScalef(…) The program glPushMatrix(); glTranslatef( -2.0, -1.0, 0.0); glScalef( 1.5, 2.0, 1.0); draw_head(); glPopMatrix(); Progressive (Scaling + Translation) 22 Scaling relative to a fix point (xf, yf) //Scaling relative to the //apex of the nose at (xf, yf) glPushMatrix(); glTranslatef( xf, yf, 0.0); glScalef( sx, sy, 1); glTranslatef( -xf, -yf, 0); draw_head(); glPopMatrix(); Scaling relative to a fix point 23 Rotation about a pivot point (xf, yf) //Rotate 90 degree about //the apex of the nose glPushMatrix(); glTranslatef( xf, yf, 0.0); glRotatef( 90., 0.0, 0.0, 1.0); glTranslatef( -xf, -yf, 0); draw_head(); glPopMatrix(); Rotation about a pivot point 24 Reflection about the x axis (x,y) x' 1 0 0 x y ' 0 1 0 y . w' 0 0 1 w (x,-y) The transformation matrix is the same as scaling matrix with Sx = 1 and Sy = 1. Thus, the reflection about the x axis can be achieved by calling glScalef( 1.0, -1.0, 1.0) Similarly, the reflection about the y axis is achieved by calling glScalef( -1.0, 1.0, 1.0) 25 Example glPushMatrix(); glScalef( 1, -1, 1); draw_head(); glPopMatrix(); Reflection about x-axis 26 y =mx+b Reflection along a line Translate (0, -b) so that the line passes through the origin Rotate the line onto the x axis by -o Reflect about the x axis Backward rotate backward translate b tan1 (m) (Be reminded that these operations must be specified in reverse order.) 27 // To draw the reflection of the head about y = 2x + 0.5 // (we need to convert theta from radians to degrees) double m = 2.0, b = .5, theta = atan(m)*180.0/3.1416; glPushMatrix(); glTranslatef( 0, b, 0.); glRotatef( theta, 0.0, 0.0, 1.0); glScalef( 1, -1, 1); //Reflect glRotatef( -theta, 0.0, 0.0, 1.0); glTranslatef( 0, -b, 0.); draw_head(); glPopMatrix(); 28 line Reflection against an arbitrary