Download presentation
Presentation is loading. Please wait.
1
1 Transformation Jeff Parker, 2011 Based on lectures by Ed Angel
2
2 Objectives Introduce standard transformations Rotation Translation Scaling Shear Learn to build arbitrary transformation matrices from simple transformations Look at some 2 dimensional examples, with an excursion to 3D We start with a simple example to motivate this
3
3 Using transformations void display() {... setColorBlue(); drawDisc(); setColorRed(); glTranslatef(8,0,0); drawDisc(); setColorGreen(); glTranslatef(-3,2,0); glScalef(2,2,2); drawDisc(); glFlush(); }
4
4 General Transformations Transformation maps points to other points and/or vectors to other vectors Q=T(P) v=T(u)
5
5 Non-Rigid Transformations
6
6 Ocean Sunfish The Ocean Sunfish is the world's heaviest known bony fish Adapted from Thomas D'Arcy's On Growth and Form
7
7 How many ways? Although we can move a point to a new location in infinite ways, when we move many points there is usually only one way objecttranslation: every point displaced by same vector
8
8 Pipeline Implementation transformationrasterizer u v u v T T(u) T(v) T(u) T(v) vertices pixels frame buffer
9
9 Affine Transformations We want our transformations to be Line Preserving Characteristic of many physically important transformations Rigid body transformations: rotation, translation Scaling, shear Importance in graphics is that we need only transform endpoints of line segments Let implementation draw line segment between the transformed endpoints
10
10 Translation Move (translate, displace) a point to a new location Displacement determined by a vector d P’=P+d P P’ d
11
11 Not Commutative While often A x B = B x A, transformations are not usually commutative If I take a step left, and then turn left, not the same as Turn left, take a step left This is fundamental, and cannot be patched or fixed.
12
12 Rotations in 2D We wish to take triplets (x, y) and map them to new points (x', y') While we will want to introduce operations that change scale, we will start with rigid body translations Translation (x, y) (x + deltaX, y) Translation (x, y) (x + deltaX, y + deltaY) Rotation (x, y) ? Insight: fix origin, and track (1, 0) and (0, 1) as we rotate through angle a
13
13 Rotations Any point (x, y) can be expressed in terms of (1, 0), (0, 1) e.g. (12, 15) = 12*(1,0) + 15*(0, 1) These unit vectors form a basis The coordinates of the rotation of T(1, 0) = (cos(a), sin(a)) The coordinates of the rotation of T(0, 1) = (-sin(a), cos(a)) The coordinates of T (x, y) = (x cos(a) + y sin(a), -x sin(a) + y cos(a)) Each term of the result is a dot product (x, y) ( cos(a), sin(a)) = (x cos(a) - y sin(a)) (x, y) (-sin(a), cos(a)) = (x sin(a) + y cos(a))
14
14 Matrices Matrices provide a compact representation for rotations, and many other transformation T (x, y) = (x cos(a) - y sin(a), x sin(a) + y cos(a)) To multiply matrices, multiply the rows of first by the columns of second
15
15 Determinant If the length of each column is 1, the matrix preserves the length of vectors (1, 0) and (0, 1) We also will look at the Determinant. Determinant of a rotation is 1.
16
16 3D Matrices Can act on 3 space T (x, y, z) = (x cos(a) + y sin(a), -x sin(a) + y cos(a), z) This is called a "Rotation about the z axis" – z values are unchanged
17
17 3D Matrices Can rotate about other axes Can also rotate about other lines through the origin… Can perform rotations in order Any rotation is the produce of three of these rotations Euler Angles Not unique Euler Angles Wikipedia
18
18 Euler Angles The Euler Angles for a rotation are not unique Euler Angles Wikipedia
19
19 Scaling S = S(s x, s y, s z ) = x’=s x x y’=s y x z’=s z x p’=Sp Expand or contract along each axis (fixed point of origin)
20
20 Reflection Reflection corresponds to negative scale factors Example below sends (x, y, z) (-x, y, z) Note that the product of two reflections is a rotation original s x = -1 s y = 1 s x = -1 s y = -1 s x = 1 s y = -1
21
21 Limitations We cannot define a translation in 2D space with a 2x2 matrix There are no choices for a, b, c, and d that will move the origin, (0, 0), to some other point, such as (5, 3) in the equation above Further, we will see that perspective can not be handled by a matrix operation alone We will find ways to get around each of these problems
22
22 Image Formation We can describe movement with a matrix Or implicitly, as below Ask for what we want… glTranslatef(8,0,0); glTranslatef(-3,2,0); glScalef(2,2,2); There are still some surprises
23
23 Using transformations void display() {... setColorBlue(); drawDisc(); setColorRed(); glTranslatef(8,0,0); drawDisc(); setColorGreen(); glTranslatef(-3,2,0); glScalef(2,2,2); drawDisc(); glFlush(); }
24
24 Absolute vs Relative move void display() {... setColorBlue(); glLoadIdentity(); drawDisc(); setColorRed(); glLoadIdentity(); /* Not really needed... */ glTranslatef(8,0,0); drawDisc(); setColorGreen(); glLoadIdentity(); /* Return to known position */ glTranslatef(5,2,0); glScalef(2,2,2); drawDisc(); glFlush(); } void display() {... setColorRed(); glTranslatef(8,0,0);... glTranslatef(-3,2,0); glScalef(2,2,2); drawDisc(); With absolute placement, don't need to remember where we were before
25
25 Order of Transformations Note that matrix on the right is the first applied to the point p Mathematically, the following are equivalent p’ = ABCp = A(B(Cp)) We use column matrices to represent points. In terms of row matrices p ’T = p T C T B T A T That is, the "last" transformation is applied first. We will see that the implicit transformations have the same order property
26
26 Rotation About a Fixed Point other than the Origin Move fixed point to origin Rotate Move fixed point back M = T(p f ) R( ) T(-p f )
27
27 Instancing In modeling, we often start with a simple object centered at the origin, oriented with the axis, and at a standard size We apply an instance transformation to its vertices to Scale Orient (rotate) Locate (translate)
28
28 Example void display() {... setColorGreen(); glLoadIdentity(); glTranslatef(5,2,0); glRotatef(45.0, 0.0, 0.0, 1.0); /* z axis */ glScalef(2,4,0); drawDisc();... }
29
29 Match image to code setColorGreen(); glLoadIdentity(); glRotatef(45.0, 0.0, 0.0, 1.0); /* z axis */ glTranslatef(5,2,0); glScalef(2,4,0); drawDisc(); setColorGreen(); glLoadIdentity(); glTranslatef(5,2,0); glRotatef(45.0, 0.0, 0.0, 1.0); glScalef(2,4,0); drawDisc(); setColorGreen(); glLoadIdentity(); glTranslatef(5,2,0); glScalef(2,4,0); glRotatef(45.0, 0.0, 0.0, 1.0); drawDisc(); The most recently applied transformation works first
30
30 Proper Order setColorGreen(); glLoadIdentity(); glRotatef(45.0, 0.0, 0.0, 1.0); /* z axis */ glTranslatef(5,2,0); glScalef(2,4,0); drawDisc(); setColorGreen(); glLoadIdentity(); glTranslatef(5,2,0); glRotatef(45.0, 0.0, 0.0, 1.0); glScalef(2,4,0); drawDisc(); setColorGreen(); glLoadIdentity(); glTranslatef(5,2,0); glScalef(2,4,0); glRotatef(45.0, 0.0, 0.0, 1.0); drawDisc();
31
Example Be sure to play with Nate Robin's Transformation example
32
Matrix Stack It is useful to be able to save the current transformation We can push the current state on a stack, and then Make new scale, translations, rotations transformations Then pop the stack and return to status quo ante
33
Example
34
Image is made up of subimages
35
Rings void display() { int angle; glClear(GL_COLOR_BUFFER_BIT); for (angle = 0; angle < 360; angle = angle + STEP) { glPushMatrix(); /* Remember current state */ glRotated(angle, 0, 0, 1); glTranslatef(0.0, 0.75, 0.0); glScalef(0.15, 0.15, 0.15); drawRing(); glPopMatrix(); /* Restore orignal state */ } glFlush(); }
36
Rings /* Draw 12 rings */ void display() { int angle; // glClear(GL_COLOR_BUFFER_BIT); for (angle = 0; angle < 360; angle = angle + STEP) { glPushMatrix(); /* Remember current state */ glRotated(angle, 0, 0, 1); glTranslatef(0.0, 0.75, 0.0); glScalef(0.15, 0.15, 0.15); drawRing(); glPopMatrix(); /* Restore orignal state */ } glFlush(); }
37
drawRing /* Draw 12 triangles to form one ring */ void drawRing() { int angle; for (angle = 0; angle < 360; angle = angle + STEP) { glPushMatrix(); /* Remember current state */ glRotated(angle, 0, 0, 1); glTranslatef(0.0, 0.75, 0.0); glScalef(0.2, 0.2, 0.2); glColor3f((float)angle/360, 0, 1.0-((float)angle/360)); drawTriangle(); glPopMatrix(); /* Restore orignal state */ } glFlush(); }
38
Tree This is harder to do from scratch Jon Squire's fractalgl uses the Matrix Stack
39
39 Shear Helpful to add one more basic transformation Equivalent to pulling faces in opposite directions
40
40 Shear Matrix Consider simple shear along x axis x’ = x + y cot y’ = y z’ = z H( ) =
41
41 3D Rotation example // Vertices of a unit cube centered at origin point4 vertices[8] = { point4( -0.5, -0.5, 0.5, 1.0 ), point4( -0.5, 0.5, 0.5, 1.0 ), point4( 0.5, 0.5, 0.5, 1.0 ), point4( 0.5, -0.5, 0.5, 1.0 ), point4( -0.5, -0.5, -0.5, 1.0 ), point4( -0.5, 0.5, -0.5, 1.0 ), point4( 0.5, 0.5, -0.5, 1.0 ), point4( 0.5, -0.5, -0.5, 1.0 ) };
42
42 Cube corners // generate 12 triangles: 36 vertices and 36 colors void colorcube() { quad( 1, 0, 3, 2 ); quad( 2, 3, 7, 6 ); quad( 3, 0, 4, 7 ); quad( 6, 5, 1, 2 ); quad( 4, 5, 6, 7 ); quad( 5, 4, 0, 1 ); }
43
43 Colors // RGBA olors color4 vertex_colors[8] = { color4( 0.0, 0.0, 0.0, 1.0 ), // black color4( 1.0, 0.0, 0.0, 1.0 ), // red color4( 1.0, 1.0, 0.0, 1.0 ), // yellow color4( 0.0, 1.0, 0.0, 1.0 ), // green color4( 0.0, 0.0, 1.0, 1.0 ), // blue color4( 1.0, 0.0, 1.0, 1.0 ), // magenta color4( 1.0, 1.0, 1.0, 1.0 ), // white color4( 0.0, 1.0, 1.0, 1.0 ) // cyan };
44
44 Mixing color and corner // Vertices of a unit cube centered at origin point4 vertices[8] = { point4( -0.5, -0.5, 0.5, 1.0 ),... // RGBA olors color4 vertex_colors[8] = { color4( 0.0, 0.0, 0.0, 1.0 ), // black... // quad generates two triangles for each face // and assigns colors to the vertices int Index = 0; void quad( int a, int b, int c, int d ) { colors[Index] = vertex_colors[a]; points[Index] = vertices[a]; Index++;
45
45 Mixing color and corner // quad generates two triangles for each face // and assigns colors to the vertices int Index = 0; void quad( int a, int b, int c, int d ) { colors[Index] = vertex_colors[a]; points[Index] = vertices[a]; Index++; colors[Index] = vertex_colors[b]; points[Index] = vertices[b]; Index++; colors[Index] = vertex_colors[c]; points[Index] = vertices[c]; Index++; colors[Index] = vertex_colors[a]; points[Index] = vertices[a]; Index++; colors[Index] = vertex_colors[c]; points[Index] = vertices[c]; Index++; colors[Index] = vertex_colors[d]; points[Index] = vertices[d]; Index++; }
46
46 Spin GLfloat Theta[NumAxes] = { 0.0, 0.0, 0.0 }; GLuint theta;// The location of the "theta" // shader uniform variable... theta = glGetUniformLocation( program, "theta" );... void display( void ) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUniform3fv( theta, 1, Theta ); glDrawArrays( GL_TRIANGLES, 0, NumVertices ); glutSwapBuffers(); }
47
47 Delta Spin void idle( void ) { Theta[Axis] += 0.01; if ( Theta[Axis] > 360.0 ) { Theta[Axis] -= 360.0; } glutPostRedisplay(); } int main( int argc, char **argv ) {... glutIdleFunc( idle );
48
48 Change axis // Array of rotation angles for each axis GLfloat Theta[NumAxes] = { 0.0, 0.0, 0.0 }; enum { Xaxis = 0, Yaxis = 1, Zaxis = 2, NumAxes = 3 }; int Axis = Xaxis; void mouse( int button, int state, int x, int y ) { if ( state == GLUT_DOWN ) { switch( button ) { case GLUT_LEFT_BUTTON: Axis = Xaxis; break; case GLUT_MIDDLE_BUTTON: Axis = Yaxis; break; case GLUT_RIGHT_BUTTON: Axis = Zaxis; break; } The Euler Angles do not give the rotations you might expect
49
49 Change axis void mouse( int button, int state, int x, int y ) { if ( state == GLUT_DOWN ) { switch( button ) { case GLUT_LEFT_BUTTON: Axis = Xaxis; break; case GLUT_MIDDLE_BUTTON: Axis = Yaxis; break; case GLUT_RIGHT_BUTTON: Axis = Zaxis; break;... // One button alternative void mouse( int button, int state, int x, int y ) { if ( state == GLUT_DOWN ) { Axis = Axis + 1; if (Axis == NumAxes) Axis = Xaxis; }
50
50 Main Program int main( int argc, char **argv ) { glutInit( &argc, argv ); glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH ); glutInitWindowSize( 512, 512 ); glutCreateWindow( "Color Cube" ); init(); glutDisplayFunc( display ); glutKeyboardFunc( keyboard ); glutMouseFunc( mouse ); glutIdleFunc( idle ); glutMainLoop(); return 0; }
51
51 Fragment Shader varying vec4 color; void main() { gl_FragColor = color; }
52
52 Vertex Shader attribute vec4 vPosition; attribute vec4 vColor; varying vec4 color; uniform vec3 theta; void main() { // Compute sines and cosines of theta for each of // the three axes in one computation. vec3 angles = radians( theta ); vec3 c = cos( angles ); vec3 s = sin( angles );
53
53 Rotation mat4 rx = mat4( 1.0, 0.0, 0.0, 0.0, 0.0, c.x, s.x, 0.0, 0.0, -s.x, c.x, 0.0, 0.0, 0.0, 0.0, 1.0 ); mat4 ry = mat4( c.y, 0.0, -s.y, 0.0, 0.0, 1.0, 0.0, 0.0, s.y, 0.0, c.y, 0.0, 0.0, 0.0, 0.0, 1.0 );... mat4 rz = mat4( c.z, -s.z, 0.0, 0.0, s.z, c.z, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ); color = vColor; gl_Position = rz * ry * rx * vPosition; } Euler Angles Wikipedia
54
54 Alternative timing void spinCube() { theta[axis] += 1.0; if( theta[axis] > 360.0 ) theta[axis] -= 360.0; glutPostRedisplay(); } static void timerCallback (int value) { /* Do timer processing */ spinCube(value); /* call back again after elapsedUSecs have passed */ glutTimerFunc (50, timerCallback, value); } /* Main program */ int main(int argc, char **argv) {... glutTimerFunc (50, timerCallback, 1); Current scheme depends on speed of cpu This one defines a timer…
55
55 Fractals - Snowflake curve The Koch Snowflake was discovered by Helge von Koch in 1904. Start with a triangle inscribed in the unit circle To build the level n snowflake, we replace each edge in the level n-1 snowflake with the following pattern The perimeter of each version is 4/3 as long Infinite perimeter, but snowflake lies within unit circle, so has finite area We will use Turtle Geometry to draw the snowflake curve Also what Jon Squire used for Fractal Tree
56
56 Recursive Step void toEdge(int size, int num) { if (1 >= num) turtleDrawLine(size); else { toEdge(size/3, num-1); turtleTurn(300); toEdge(size/3, num-1); turtleTurn(120); toEdge(size/3, num-1); turtleTurn(300); toEdge(size/3, num-1); }
57
57 Turtle Library /** Draw a line of length size */ void turtleDrawLine(GLint size) glVertex2f(xPos, yPos); turtleMove(size); glVertex2f(xPos, yPos); } int turtleTurn(int alpha) { theta = theta + alpha; theta = turtleScale(theta); return theta; } /** Move the turtle. Called to move and by DrawLine */ void turtleMove(GLint size) { xPos = xPos + size * cos(DEGREES_TO_RADIANS * theta); yPos = yPos + size * sin(DEGREES_TO_RADIANS * theta); }
58
58 Dragon Curve The Dragon Curve is due to Heighway One way to generate the curve is to start with a folded piece of paper We can describe a curve as a set of turtle directions The second stage is simply Take one step, turn Right, and take one step The next stage is Take one step, turn Right, take one step Turn Right Perform the original steps backwards, or Take one step, turn Left, take one step Since the step between turns is implicit, we can write this as RRL The next stage is …
59
59 Dragon Curve The Dragon Curve is due to Heighway One way to generate the curve is to start with a folded piece of paper We can describe a curve as a set of turtle directions The second stage is simply Take one step, turn Right, and take one step The next stage is Take one step, turn Right, take one step Turn Right Perform the original steps backwards, or Take one step, turn Left, take one step Since the step between turns is implicit, we can write this as RRL The next stage is RRL R RLL
60
60 How can we program this? We could use a large array representing the turns RRL R RLL To generate the next level, append an R and walk back to the head, changing L’s to R’s and R’s to L’s and appending the result to end of array But there is another way. Start with a line At every stage, we replace the line with a right angle We have to remember which side of the line to decorate (use variable “direction”) One feature of this scheme is that the “head” and “tail” are fixed RRLRRLL
61
61 Dragon Curve void dragon(int size, int level, int direction, int alpha) { /* Add on left or right? */ int degree = direction * 45; turtleSet(alpha); if (1 == level) { turtleDrawLine(size); return; } size = size/scale; /* scale == sqrt(2.0) */ dragon(size, level - 1, 1, alpha + degree); dragon(size, level - 1, -1, alpha - degree); }
62
62 Dragon Curve When we divide an int (size) by a real (sqrt(2.0)) there is roundoff error, and the dragon slowly shrinks The on-line version of this program precomputes sizes per level and passes them through, as below int sizes[] = {0, 256, 181, 128, 90, 64, 49, 32, 23, 16, 11, 8, 6, 4, 3, 2, 2, 1, 0};... dragon(sizes[level], level, 1, 0);... void dragon(int size, int level, int direction, int alpha) {... /* size = size/scale; */ dragon(size, level - 1, 1, alpha + degree); dragon(size, level - 1, -1, alpha - degree); }
63
63 Pen And Paper Write routines to decide if a circle intersects a line or a line segment How much harder would it be to find the point of intersection?
64
64 Task Write a program that displays an image, and uses user input to update the image. Don't worry about logic behind the display
65
65 From Previous class Alex Chou's Pac Man
66
66 Sample Projects From last class
67
67 Summary We have played with transformations Spend today looking at movement in 2D In OpenGL, transformations are defined by matrix operations In new version, glTranslate, glRotate, and glScale are deprecated We have seen some 2D matrices for rotation and scaling You cannot define a 2x2 matrix that performs translation A puzzle to solve The most recently applied transformation works first You can push the current matrix state and restore later Turtle Graphics provides an alternative
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.