5. 2D & 3D Transformations
Brock University
COSC 3P98 Computer Graphics
Instructor: Brian Ross
2d transform composition
- the order we perform multiple transforms can matter
- eg. translate + scale can differ from scale + translate
- eg. rotate + translate can differ from translate + rotate
- eg. rotate + scale can differ from scale + rotate (when scale_x differs from scale_y)
- When does M1 + M2 = M2 + M1?
M1 |
M2 |
translate |
translate |
scale |
scale |
rotate |
rotate |
scale (sx = sy) |
rotate |
- To prove commutativity (or lack thereof), show that the composed
transformation matrices are the same (or different).
Combined form for 2d Transforms
| r11 r12 tx |
M = | r21 r22 ty |
| 0 0 1 |
- upper 2 by 2 submatrix is a composite rotation & scale matrix;
- t1 and t2 are composed translations
- precise form of matrix expressions depends upon order of transforms
Coordinate systems: Local and Global
- With no transformations, there is one global coordinate system in which objects are drawn.
- When you apply any transformation, this is equivalent to changing
the coordinate system. You are defining a local coordinate system
within the global system.
- For example, if you set the scale to 0.5, and then draw a box, that box's coordinate system is 0.5 relative to the global coordinate system.
- Thinking of transformations as changing the coordinate systems is very
useful conceptually, since in most scenes, objects transforms are defined
relative to one, but the objects themselves are drawn without regard to
the transforms applied to them.
This is most easily imagined as if they had differing coordinate
systems.
2d transforms: OpenGL implementation
- OpenGL is immediate mode: graphics
operations are applied 'instantly'
- in terms of transformations, the user gives a rotate, translate, or
scale command, and the matrix multiplication represented by that transform
is immediately applied to a global transformation matrix
- In other words, a 4 by 4 matrix of floating point values is maintained. It changes each time a single transformation is done. However, all the individual transformations used to derive these numeric values are
not retained.
2d transforms: OpenGL
- OpenGL transformation commands set up a 4 by 4 transformation matrix,
in the way shown on previous overheads
- Can use glGet(GL_MODELVIEW_MATRIX) to retrieve this matrix, and glLoadMatrix to replace it with your own matrix.
- we haven't talked about 3d transforms; however, note that homogeneous
3d transformation matrix is 4 by 4; 2D uses subset of it.
- glRotate{fd} (TYPE angle, TYPE x, TYPE y, TYPE z)
- TYPE is f or d
- rotates the current transformation matrix counterclockwise 'angle'
degrees about a ray from the origin through the point (x, y, z)
- eg. glRotatef(45.0, 0.0, 0.0, 1.0) rotates 45 degrees about
the z-axis
- (x,y,z) can be any direction. It will be automatically normalized if it isn't a
unit vector.
- glTranslate {fd} (TYPE x, y, z)
- translates by the amounts x, y, z
- note: glTranslatef(): empty argument is the identity matrix
- glScale {fd} (TYPE x, y, z)
- applies x, y, z scaling factors
- eg. glScalef(2.0, -0.5, 1.0)
OpenGL: Order of transformation operations
- When giving OpenGLtransformation commands, they are applied in
the inverse order you give them.
glScaled(1.0, 1.0, 3.0);
glRotatef(45.0, 0.0, 1.0, 0.0);
glTranslatef(3.0, 2.0, 0.0);
draw_my_triangle();
- the transformations occur in the reverse order
- This is done to reflect the algebraic
order of the matrix transforms:
S * R * T * P = S * (R * (T * P) )
2D Transformation inversions
T(dx, dy) * T(-dx, -dy) = 1
R( A) * R(- A) = 1
S(sx, sy) * S( 1/sx, 1/sy) = 1
To invert a sequence of transforms P' = M * P = (Tr1 * Tr2 * ... * TrK)
* P
M^(-1) * P = (Tr1 * Tr2 * ... * TrK)^(-1) * P = TrK^(-1) * ... * Tr2^(-1) * Tr1^(-1) * P
- note how matrix/vector notation is useful here!
OpenGL: Saving and restoring contexts
- Previously mentioned that OpenGL does not save individual transformations.
- Implies that application program must retain all the individual transformations, if one ever wants to "undo" them!
- glPushmatrix(), glPopmatrix(): save and restore transformation matrices
- you essentially modify & use top matrix on the stack
- initialize to identity matrix with: glLoadIdentity()
- Using glPushmatrix() lets you save your current local coordinate system, by copying top (current) transformation matrix onto top of stack.
- Subsequent transformations manipulate top matrix in stack.
--> Transformations compound and accumulate into one general transformation.
- glPopmatrix() then reverts back to previous local coordinate system.
- Equivalent to applying the inversions of all the transforms done in the meantime.
- Extremely useful when rendering hierarchical scenes
OpenGL Matrix Modes
- OpenGL has separate transformation matrices for different
graphics features
- glMatrixMode(GLenum mode), where mode is one of:
- GL_MODELVIEW - for manipulating model in scene (stack of them for glPushMatrix)
- GL_PROJECTION - perspective orientation
- GL_TEXTURE - texture map orientation
- Make sure you specify glMatrixMode(GL_MODELVIEW) before proceeding with model transformations
- Likewise, specify glMatrixMode(GL_PROJECTION) when you set up your perspective view (in later topic)
- glLoadIdentity(): loads a 4-by-4 identity matrix into the current matrix (whatever mode you're in)
- always initialize with the identity; don't presume it is loaded for you
- Example 2D OpenGL program: Sierpinski Triangles and example output (level=7).
- Here's the output when transformations in wrong order.
Properties of affine transformation matrix M
- lines are preserved (ie. lines remain lines after transform)
- parallelism is preserved
- proportional distances are preserved
- eg. if point P is a fraction F between points A and B before, it will
remain so after the transform
- the change in area of any object transformed is:
- (area after transform) / (area before transform) = |determinant M |
2D transforms: Shear transformations ("shearing")
| 1 a 0 | | 1 0 0 |
SHx = | 0 1 0 | SHy = | b 1 0 |
| 0 0 1 | | 0 0 1 |
x' = x + ay x' = x
y' = y y' = bx + y
- ... a proportional change in x as a function of y (and vice versa)
3D Transforms
- 3D space: add a Z coordinate (X, Y, Z)
- 3D homogeneous coordinates: 4 dimensions
- Text and OpenGL use a Right-handed rotation system: grab the Z axis with
right hand, and curl fingers from +ve X axis to +ve Y axis: thumb points
out at you, which is direction of +ve Z axis
- implies that +ve Z axis points at you when facing the screen with +ve
Y pointing up and +ve X pointing right
3D transforms
- All transformations directly extend to 3D
- Translation:
| 1 0 0 dx |
T(dx,dy,dz) = | 0 1 0 dy |
| 0 0 1 dz |
| 0 0 0 1 |
| sx 0 0 0 |
S(sx,sy,sz) = | 0 sy 0 0 |
| 0 0 sz 0 |
| 0 0 0 1 |
| 1 0 0 0 |
Rx(A) = | 0 cos A -sin A 0 |
| 0 sin A cos A 0 |
| 0 0 0 1 |
| cos A 0 sin A 0 |
Ry(A) = | 0 1 0 0 |
| -sin A 0 cos A 0 |
| 0 0 0 1 |
| cos A -sin A 0 0 |
Rz(A) = | sin A cos A 0 0 |
| 0 0 1 0 |
| 0 0 0 1 |
3d transforms
- 2D rotations is given by Z axis rotation matrix
- Note that rotation matrix about Y axis uses "different' signs
- reason: when you look down Y axis, you have this:
z' = z cos A - x sin A
x' = z sin A + x cos A (as before)
--> but when you put these in matrix form, the X and Z are in reversed
order, hence the sign change
- All these transformation matrices have inverses similar to 2D case
3D transforms
- composing 3D transforms works same as 2D: write each transformation
matrix in the order the transformation sequence is done
- translation & rotations on same axes are additive, while scaling
is multiplicative
- however, note that rotations on different axis are NOT commutative!
- general transform:
| r11 r12 r13 tx |
M = | r21 r22 r23 ty |
| r31 r32 r33 tz |
| 0 0 0 1 |
- one trick: inverse of the top-left 3 x 3 submatrix: transpose it
| r11 r12 r13 |
R = | r21 r22 r23 |
| r31 r32 r33 |
| r11 -r21 r13 |
R^(-1) = (1/Det R)* | -r12 r22 -r32 |
| r31 -r23 r33 |
3D transform properties
- lines are preserved
- parallelism is preserved
- proportional distances are preserved
- (volume after transformation) / (volume before) = | det M |
Non-affine transform: Fish-eye (angle halver)
- entire X-Y plane mapped to a circle
- phi = tan^(-1)(|P|)
- convert P to Q: Q = s * P (s = scaling factor)
- where s = tan(tan^(-1)(|P|)/2)/(|P|) = |Q|/|P| = tan(phi/2)/|P|
- Fish eye transformation setup(from [Hill 1990])
- Example transformation (from [Hill 1990])
Non-affine transforms: inversion in a unit circle
- Map point P to inverse of its distance from origin
- circles and lines that do not pass through origin map into circles
- Derivation:
- sin(A) = X/(|P|)
- so: X' = 1/(|P|) sin(A) = (1/(|P|))*(X/(|P|)) = X / (|P|^2)
- Q = 1/(|P|^2) * P
- X' = 1/(|P|^2) * X
- Y' = 1/(|P|^2) * Y
References
- Introduction to Computer Graphics , Foley, van Dam, et al, Addison Wesley, ISBN 0-201-60921-5.
- Computer Graphics, F.S. Hill Jr, Macmillan 1990, ISBN 0-02-354860-6. (Source of non-affine transformation examples.)
Back to COSC 3P98 index
COSC 3P98 Computer Graphics
Brock University
Dept of Computer Science
Copyright © 2014 Brian J. Ross (Except noted figures).
http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/2d_3d_xforms/
Last updated: October 27, 2014