CS 445 / 645 Introduction to Computer Graphics Lecture 5 Assignment 1 3D Primitives and Transformations Lecture 5 Assignment 1 3D Primitives and Transformations
Assignment 1 We’ve hit a snag with assignment 1 Due date extended one week – Sept. 26 thDue date extended one week – Sept. 26 th I’m creating an intermediate programming assignmentI’m creating an intermediate programming assignment Visual Studio 7 isn’t ready for dept. release yet We’re revamping for Visual Studio 6We’re revamping for Visual Studio 6 You can set things up for yourself, but we are trying to simplify the process for youYou can set things up for yourself, but we are trying to simplify the process for you We’ve hit a snag with assignment 1 Due date extended one week – Sept. 26 thDue date extended one week – Sept. 26 th I’m creating an intermediate programming assignmentI’m creating an intermediate programming assignment Visual Studio 7 isn’t ready for dept. release yet We’re revamping for Visual Studio 6We’re revamping for Visual Studio 6 You can set things up for yourself, but we are trying to simplify the process for youYou can set things up for yourself, but we are trying to simplify the process for you
Assignment 1 – more details Assignment 1 uses FLTK, GLUT, Boost The source for each tool is accessible onlineThe source for each tool is accessible online –You can download the source and compile the needed libraries yourself (contact TA for Boost details) To simplify and standardizeTo simplify and standardize –We are compiling the source into libraries for you and putting them in a shared location (that’s the snag) You can start on this right now, but you may have to tweak your project files to work with our released librariesYou can start on this right now, but you may have to tweak your project files to work with our released libraries Assignment 1 uses FLTK, GLUT, Boost The source for each tool is accessible onlineThe source for each tool is accessible online –You can download the source and compile the needed libraries yourself (contact TA for Boost details) To simplify and standardizeTo simplify and standardize –We are compiling the source into libraries for you and putting them in a shared location (that’s the snag) You can start on this right now, but you may have to tweak your project files to work with our released librariesYou can start on this right now, but you may have to tweak your project files to work with our released libraries
Intermediate Assignment Assignment 0 – not graded but checked Set up your class account on blue.unix.virginia.eduSet up your class account on blue.unix.virginia.edu –Instructions to follow Experiment with FLTKExperiment with FLTK – s2002/assignments/assignment1/ Experiment with OpenGLExperiment with OpenGL – Exercises/assignment2.htm Assignment 0 – not graded but checked Set up your class account on blue.unix.virginia.eduSet up your class account on blue.unix.virginia.edu –Instructions to follow Experiment with FLTKExperiment with FLTK – s2002/assignments/assignment1/ Experiment with OpenGLExperiment with OpenGL – Exercises/assignment2.htm
Assignment 0 Due Tuesday, Sept 17 th at 5:00 p.m. me ASAP if your blue.unix account doesn’t exist me ASAP if your blue.unix account doesn’t exist Turn in:Turn in: –Create directory on blue: /courses/cs/Students/username/Assignment0 –Complete the FLTK tutorial and leave an executable in your directory called assign0.exe that accomplishes what’s described in “Adding Basic Components to a Window” in the Wisconsin tutorial Optional – play with last year’s firetruck demoOptional – play with last year’s firetruck demo Due Tuesday, Sept 17 th at 5:00 p.m. me ASAP if your blue.unix account doesn’t exist me ASAP if your blue.unix account doesn’t exist Turn in:Turn in: –Create directory on blue: /courses/cs/Students/username/Assignment0 –Complete the FLTK tutorial and leave an executable in your directory called assign0.exe that accomplishes what’s described in “Adding Basic Components to a Window” in the Wisconsin tutorial Optional – play with last year’s firetruck demoOptional – play with last year’s firetruck demo
Assignment 0 Setting up your directory on blue.unix.virginia.edu Log on to blueLog on to blue ‘cd /courses/cs/445_brogan/Students’‘cd /courses/cs/445_brogan/Students’ ‘mkdir username’ where username is your UVA username‘mkdir username’ where username is your UVA username ‘mkdir username/Assignment0’‘mkdir username/Assignment0’ Next week I’ll lock things down and protect file read permissions Setting up your directory on blue.unix.virginia.edu Log on to blueLog on to blue ‘cd /courses/cs/445_brogan/Students’‘cd /courses/cs/445_brogan/Students’ ‘mkdir username’ where username is your UVA username‘mkdir username’ where username is your UVA username ‘mkdir username/Assignment0’‘mkdir username/Assignment0’ Next week I’ll lock things down and protect file read permissions
Assignment 0 Location of VC7 libraries/includes blue.unix:/courses/cs/445_brogan/Sources/VC7blue.unix:/courses/cs/445_brogan/Sources/VC7 Future location of VC6 libraries/includes blue.unix:/courses/cs/445_brogan/Sources/VC6blue.unix:/courses/cs/445_brogan/Sources/VC6 I’ll send an to reiterate/clarify If you’re auditing class, make sure I have your If you’re auditing class, make sure I have your Location of VC7 libraries/includes blue.unix:/courses/cs/445_brogan/Sources/VC7blue.unix:/courses/cs/445_brogan/Sources/VC7 Future location of VC6 libraries/includes blue.unix:/courses/cs/445_brogan/Sources/VC6blue.unix:/courses/cs/445_brogan/Sources/VC6 I’ll send an to reiterate/clarify If you’re auditing class, make sure I have your If you’re auditing class, make sure I have your
Goals of these assignments Get the programming environment up and runningGet the programming environment up and running Get practice with matrix compositionGet practice with matrix composition Get practice with line/surface equationsGet practice with line/surface equations Get practice building GUIs quicklyGet practice building GUIs quickly Get the programming environment up and runningGet the programming environment up and running Get practice with matrix compositionGet practice with matrix composition Get practice with line/surface equationsGet practice with line/surface equations Get practice building GUIs quicklyGet practice building GUIs quickly
Question from last class Why does OpenGL post-multiply? No particular reasonNo particular reason –Are you transforming the point (bottom up) –Are you transforming the coordinate system (top down) OpenGL authors prefer the latterOpenGL authors prefer the latter If you don’t like it….If you don’t like it…. –Transpose the matrices and premultiply them Why does OpenGL post-multiply? No particular reasonNo particular reason –Are you transforming the point (bottom up) –Are you transforming the coordinate system (top down) OpenGL authors prefer the latterOpenGL authors prefer the latter If you don’t like it….If you don’t like it…. –Transpose the matrices and premultiply them
OpenGL: Front/Back Rendering Each polygon has two sides, front and back OpenGL can render the two differently The ordering of vertices in the list determines which is the front side: When looking at the front side, the vertices go counterclockwiseWhen looking at the front side, the vertices go counterclockwise –This is basically the right-hand rule –Note that this still holds after perspective projection Each polygon has two sides, front and back OpenGL can render the two differently The ordering of vertices in the list determines which is the front side: When looking at the front side, the vertices go counterclockwiseWhen looking at the front side, the vertices go counterclockwise –This is basically the right-hand rule –Note that this still holds after perspective projection
OpenGL: Specifying Geometry Geometry in OpenGL consists of a list of vertices in between calls to glBegin() and glEnd() A simple example: telling GL to render a triangleA simple example: telling GL to render a triangleglBegin(GL_POLYGON); glVertex3f(x1, y1, z1); glVertex3f(x2, y2, z2); glVertex3f(x3, y3, z3); glEnd(); Usage: glBegin( geomtype ) where geomtype is:Usage: glBegin( geomtype ) where geomtype is: –Points, lines, polygons, triangles, quadrilaterals, etc... Geometry in OpenGL consists of a list of vertices in between calls to glBegin() and glEnd() A simple example: telling GL to render a triangleA simple example: telling GL to render a triangleglBegin(GL_POLYGON); glVertex3f(x1, y1, z1); glVertex3f(x2, y2, z2); glVertex3f(x3, y3, z3); glEnd(); Usage: glBegin( geomtype ) where geomtype is:Usage: glBegin( geomtype ) where geomtype is: –Points, lines, polygons, triangles, quadrilaterals, etc...
OpenGL: Drawing Triangles You can draw multiple triangles between glBegin(GL_TRIANGLES) and glEnd() : float v1[3], v2[3], v3[3], v4[3];...glBegin(GL_TRIANGLES); glVertex3fv(v1); glVertex3fv(v2); glVertex3fv(v3); glVertex3fv(v1); glVertex3fv(v3); glVertex3fv(v4); glEnd(); Each set of 3 vertices forms a triangle How much redundant computation is happening?How much redundant computation is happening? You can draw multiple triangles between glBegin(GL_TRIANGLES) and glEnd() : float v1[3], v2[3], v3[3], v4[3];...glBegin(GL_TRIANGLES); glVertex3fv(v1); glVertex3fv(v2); glVertex3fv(v3); glVertex3fv(v1); glVertex3fv(v3); glVertex3fv(v4); glEnd(); Each set of 3 vertices forms a triangle How much redundant computation is happening?How much redundant computation is happening?
OpenGL: Triangle Strips An OpenGL triangle strip primitive reduces this redundancy by sharing vertices: glBegin(GL_TRIANGLE_STRIP);glVertex3fv(v0);glVertex3fv(v1);glVertex3fv(v2);glVertex3fv(v3);glVertex3fv(v4);glVertex3fv(v5);glEnd(); triangle 0 is v0, v1, v2triangle 0 is v0, v1, v2 triangle 1 is v2, v1, v3 (why not v1, v2, v3?)triangle 1 is v2, v1, v3 (why not v1, v2, v3?) triangle 2 is v2, v3, v4triangle 2 is v2, v3, v4 triangle 3 is v4, v3, v5 (again, why not v3, v4, v5)triangle 3 is v4, v3, v5 (again, why not v3, v4, v5) An OpenGL triangle strip primitive reduces this redundancy by sharing vertices: glBegin(GL_TRIANGLE_STRIP);glVertex3fv(v0);glVertex3fv(v1);glVertex3fv(v2);glVertex3fv(v3);glVertex3fv(v4);glVertex3fv(v5);glEnd(); triangle 0 is v0, v1, v2triangle 0 is v0, v1, v2 triangle 1 is v2, v1, v3 (why not v1, v2, v3?)triangle 1 is v2, v1, v3 (why not v1, v2, v3?) triangle 2 is v2, v3, v4triangle 2 is v2, v3, v4 triangle 3 is v4, v3, v5 (again, why not v3, v4, v5)triangle 3 is v4, v3, v5 (again, why not v3, v4, v5) v0v0 v2v2 v1v1 v3v3 v4v4 v5v5
OpenGL: More Examples Example: GL supports quadrilaterals: glBegin(GL_QUADS); glVertex3f(-1, 1, 0); glVertex3f(-1, -1, 0); glVertex3f(1, -1, 0); glVertex3f(1, 1, 0); glEnd(); This type of operation is called immediate-mode rendering; each command happens immediatelyThis type of operation is called immediate-mode rendering; each command happens immediately Example: GL supports quadrilaterals: glBegin(GL_QUADS); glVertex3f(-1, 1, 0); glVertex3f(-1, -1, 0); glVertex3f(1, -1, 0); glVertex3f(1, 1, 0); glEnd(); This type of operation is called immediate-mode rendering; each command happens immediatelyThis type of operation is called immediate-mode rendering; each command happens immediately
Primitive Types GL_POINTSGL_LINE {S | _STRIP | _LOOP}{S | _STRIP | _LOOP}GL_TRIANGLE {S | _STRIP | _FAN}{S | _STRIP | _FAN}GL_QUAD {S | _STRIP}{S | _STRIP}GL_POLYGONGL_POINTSGL_LINE {S | _STRIP | _LOOP}{S | _STRIP | _LOOP}GL_TRIANGLE {S | _STRIP | _FAN}{S | _STRIP | _FAN}GL_QUAD {S | _STRIP}{S | _STRIP}GL_POLYGON
GL_POLYGON List of vertices defines polygon edges Polygon must be convex List of vertices defines polygon edges Polygon must be convex
Non-planar Polygons Imagine polygon with non-planar vertices Some perspectives will be rendered as concave polygons These concave polygons may not rasterize correctly Imagine polygon with non-planar vertices Some perspectives will be rendered as concave polygons These concave polygons may not rasterize correctly
Single Buffering ‘Buffer’ corresponds to frame buffer‘Buffer’ corresponds to frame buffer ‘Single’ corresponds to there being just one‘Single’ corresponds to there being just one Place where you write pixel color values is same place graphics hardware goes to read color values for displayPlace where you write pixel color values is same place graphics hardware goes to read color values for display Can draw on top of existing imageCan draw on top of existing image –Might be faster than redrawing whole image Can also lead to flickering and half-drawn imagesCan also lead to flickering and half-drawn images ‘Buffer’ corresponds to frame buffer‘Buffer’ corresponds to frame buffer ‘Single’ corresponds to there being just one‘Single’ corresponds to there being just one Place where you write pixel color values is same place graphics hardware goes to read color values for displayPlace where you write pixel color values is same place graphics hardware goes to read color values for display Can draw on top of existing imageCan draw on top of existing image –Might be faster than redrawing whole image Can also lead to flickering and half-drawn imagesCan also lead to flickering and half-drawn images
Double Buffering OpenGL writes raster image to separate buffer from that read for displayOpenGL writes raster image to separate buffer from that read for display ‘front’ buffer is for video signal‘front’ buffer is for video signal ‘back’ buffer is the drawing target‘back’ buffer is the drawing target After each frame is drawn, the front and back buffers swapAfter each frame is drawn, the front and back buffers swap –glxSwapBuffers (Display *dpy, Window, w) –glutSwapBuffers (void) Avoids displaying partially rendered frame bufferAvoids displaying partially rendered frame buffer Avoids flickeringAvoids flickering OpenGL writes raster image to separate buffer from that read for displayOpenGL writes raster image to separate buffer from that read for display ‘front’ buffer is for video signal‘front’ buffer is for video signal ‘back’ buffer is the drawing target‘back’ buffer is the drawing target After each frame is drawn, the front and back buffers swapAfter each frame is drawn, the front and back buffers swap –glxSwapBuffers (Display *dpy, Window, w) –glutSwapBuffers (void) Avoids displaying partially rendered frame bufferAvoids displaying partially rendered frame buffer Avoids flickeringAvoids flickering
Setting up the OpenGL Window Must clear the ‘canvas’ before drawing glClearColor (r, g, b, )glClearColor (r, g, b, ) –Specify the color to initialize canvas to –Typically set to 0.0 to make fully transparent –This is a state variable and can only be called once glClear(GL_COLOR_BUFFER_BIT)glClear(GL_COLOR_BUFFER_BIT) –Actually clear the screen –glClear could also clear the GL_DEPTH_BUFFER_BIT –We’re not worried about that now Must clear the ‘canvas’ before drawing glClearColor (r, g, b, )glClearColor (r, g, b, ) –Specify the color to initialize canvas to –Typically set to 0.0 to make fully transparent –This is a state variable and can only be called once glClear(GL_COLOR_BUFFER_BIT)glClear(GL_COLOR_BUFFER_BIT) –Actually clear the screen –glClear could also clear the GL_DEPTH_BUFFER_BIT –We’re not worried about that now
3-D Transformations We studied the details of 2-D transformations I introduced the expanded 3-D transformations We’ve got some more details… We studied the details of 2-D transformations I introduced the expanded 3-D transformations We’ve got some more details…
Scaling and Translation in 3-D Pretty much just like 2-D Just add on the z dimension to everythingJust add on the z dimension to everything Pretty much just like 2-D Just add on the z dimension to everythingJust add on the z dimension to everything TranslationTranslation ScalingScaling
Rotation in 3-D Looks similar to 2-D Case Specify arbitrray rotation as three anglesSpecify arbitrray rotation as three angles –One per coordinate axis –Called an Euler Angle –Common representation –But order of rotations matters Looks similar to 2-D Case Specify arbitrray rotation as three anglesSpecify arbitrray rotation as three angles –One per coordinate axis –Called an Euler Angle –Common representation –But order of rotations matters
3-D Rotation General rotations in 3-D require rotating about an arbitrary axis of rotation Deriving the rotation matrix for such a rotation directly is a good exercise in linear algebra Standard approach: express general rotation as composition of canonical rotations Rotations about X, Y, ZRotations about X, Y, Z General rotations in 3-D require rotating about an arbitrary axis of rotation Deriving the rotation matrix for such a rotation directly is a good exercise in linear algebra Standard approach: express general rotation as composition of canonical rotations Rotations about X, Y, ZRotations about X, Y, Z
Composing Canonical Rotations Goal: rotate about arbitrary vector A by Idea: we know how to rotate about X,Y,ZIdea: we know how to rotate about X,Y,Z –So, rotate about Y by until A lies in the YZ plane –Then rotate about X by until A coincides with +Z –Then rotate about Z by –Then reverse the rotation about X (by - ) –Then reverse the rotation about Y (by - ) Goal: rotate about arbitrary vector A by Idea: we know how to rotate about X,Y,ZIdea: we know how to rotate about X,Y,Z –So, rotate about Y by until A lies in the YZ plane –Then rotate about X by until A coincides with +Z –Then rotate about Z by –Then reverse the rotation about X (by - ) –Then reverse the rotation about Y (by - )
Composing Canonical Rotations First: rotating about Y by until A lies in YZ How exactly do we calculate ? Project A onto XZ plane (Throw away y-coordinate)Project A onto XZ plane (Throw away y-coordinate) Find angle to X:Find angle to X: = -(90° - ) = - 90 ° Second: rotating about X by until A lies on Z How do we calculate ? First: rotating about Y by until A lies in YZ How exactly do we calculate ? Project A onto XZ plane (Throw away y-coordinate)Project A onto XZ plane (Throw away y-coordinate) Find angle to X:Find angle to X: = -(90° - ) = - 90 ° Second: rotating about X by until A lies on Z How do we calculate ?
Composing Canonical Rotations Why are we slogging through all this tedium? A1: Because you’ll have to do it on the test A2: Because it will help with the assignment Computing intersection between a parabola and ground planeComputing intersection between a parabola and ground plane Why are we slogging through all this tedium? A1: Because you’ll have to do it on the test A2: Because it will help with the assignment Computing intersection between a parabola and ground planeComputing intersection between a parabola and ground plane dist = ? y+
3-D Rotation Matrices So an arbitrary rotation about A composes several canonical rotations together We can express each rotation as a matrix Composing transforms == multiplying matrices Thus we can express the final rotation as the product of canonical rotation matrices Thus we can express the final rotation with a single matrix! So an arbitrary rotation about A composes several canonical rotations together We can express each rotation as a matrix Composing transforms == multiplying matrices Thus we can express the final rotation as the product of canonical rotation matrices Thus we can express the final rotation with a single matrix!
Composing Matrices So we have the following matrices: p: The point to be rotated about A by R y : Rotate about Y by R x : Rotate about X by R z : Rotate about Z by R x -1 : Undo rotation about X by R y -1 : Undo rotation about Y by In what order should we multiply them? So we have the following matrices: p: The point to be rotated about A by R y : Rotate about Y by R x : Rotate about X by R z : Rotate about Z by R x -1 : Undo rotation about X by R y -1 : Undo rotation about Y by In what order should we multiply them?
Compositing Matrices Short answer: the transformations, in order, are written from right to left In other words, the first matrix to affect the vector goes next to the vector, the second next to the first, etc.In other words, the first matrix to affect the vector goes next to the vector, the second next to the first, etc. So in our case: p’ = R y -1 R x -1 R z R x R y p Short answer: the transformations, in order, are written from right to left In other words, the first matrix to affect the vector goes next to the vector, the second next to the first, etc.In other words, the first matrix to affect the vector goes next to the vector, the second next to the first, etc. So in our case: p’ = R y -1 R x -1 R z R x R y p
Rotation Matrices Notice these two matrices: R x : Rotate about X by R x -1 : Undo rotation about X by How can we calculate R x -1 ? Notice these two matrices: R x : Rotate about X by R x -1 : Undo rotation about X by How can we calculate R x -1 ?
Rotation Matrices Notice these two matrices: R x : Rotate about X by R x -1 : Undo rotation about X by How can we calculate R x -1 ? Obvious answer: calculate R x (- )Obvious answer: calculate R x (- ) Clever answer: exploit fact that rotation matrices are orthonormalClever answer: exploit fact that rotation matrices are orthonormal Notice these two matrices: R x : Rotate about X by R x -1 : Undo rotation about X by How can we calculate R x -1 ? Obvious answer: calculate R x (- )Obvious answer: calculate R x (- ) Clever answer: exploit fact that rotation matrices are orthonormalClever answer: exploit fact that rotation matrices are orthonormal
Rotation Matrices Notice these two matrices: R x : Rotate about X by R x -1 : Undo rotation about X by How can we calculate R x -1 ? Obvious answer: calculate R x (- )Obvious answer: calculate R x (- ) Clever answer: exploit fact that rotation matrices are orthonormalClever answer: exploit fact that rotation matrices are orthonormal What is an orthonormal matrix? What property are we talking about? Notice these two matrices: R x : Rotate about X by R x -1 : Undo rotation about X by How can we calculate R x -1 ? Obvious answer: calculate R x (- )Obvious answer: calculate R x (- ) Clever answer: exploit fact that rotation matrices are orthonormalClever answer: exploit fact that rotation matrices are orthonormal What is an orthonormal matrix? What property are we talking about?
Rotation Matrices Orthonormal matrix: orthogonal (columns/rows linearly independent)orthogonal (columns/rows linearly independent) normalized (columns/rows length of 1)normalized (columns/rows length of 1) The inverse of an orthogonal matrix is just its transpose: Orthonormal matrix: orthogonal (columns/rows linearly independent)orthogonal (columns/rows linearly independent) normalized (columns/rows length of 1)normalized (columns/rows length of 1) The inverse of an orthogonal matrix is just its transpose:
Rotation Matrix 9 DOFs must reduce to 3 Rows must be unit length (-3 DOFs) Rows must be orthogonal (-3 DOFs) Drifting matrices is very bad Numerical errors results when trying to gradually rotate matrix by adding derivativesNumerical errors results when trying to gradually rotate matrix by adding derivatives Resulting matrix may scale / shearResulting matrix may scale / shear Gram-Schmidt algorithm will re-orthogonalize your matrixGram-Schmidt algorithm will re-orthogonalize your matrix Difficult to interpolate between matrices 9 DOFs must reduce to 3 Rows must be unit length (-3 DOFs) Rows must be orthogonal (-3 DOFs) Drifting matrices is very bad Numerical errors results when trying to gradually rotate matrix by adding derivativesNumerical errors results when trying to gradually rotate matrix by adding derivatives Resulting matrix may scale / shearResulting matrix may scale / shear Gram-Schmidt algorithm will re-orthogonalize your matrixGram-Schmidt algorithm will re-orthogonalize your matrix Difficult to interpolate between matrices
Euler Angles ( x, y, z ) = R z R y R x Rotate x degrees about x-axisRotate x degrees about x-axis Rotate y degrees about y-axisRotate y degrees about y-axis Rotate z degrees about z-axisRotate z degrees about z-axis Axis order is not defined (y, z, x), (x, z, y), (z, y, x)… are all legal(y, z, x), (x, z, y), (z, y, x)… are all legal Pick onePick one ( x, y, z ) = R z R y R x Rotate x degrees about x-axisRotate x degrees about x-axis Rotate y degrees about y-axisRotate y degrees about y-axis Rotate z degrees about z-axisRotate z degrees about z-axis Axis order is not defined (y, z, x), (x, z, y), (z, y, x)… are all legal(y, z, x), (x, z, y), (z, y, x)… are all legal Pick onePick one
Euler Angles Rotations not uniquely defined ex: (z, x, y) = (90, 45, 45) = (45, 0, -45) takes positive x-axis to (1, 1, 1)ex: (z, x, y) = (90, 45, 45) = (45, 0, -45) takes positive x-axis to (1, 1, 1) cartesian coordinates are independent of one another, but Euler angles are notcartesian coordinates are independent of one another, but Euler angles are not Gimbal Lock Term derived from mechanical problem that arises in gimbal mechanism that supports a compass or a gyroTerm derived from mechanical problem that arises in gimbal mechanism that supports a compass or a gyro Rotations not uniquely defined ex: (z, x, y) = (90, 45, 45) = (45, 0, -45) takes positive x-axis to (1, 1, 1)ex: (z, x, y) = (90, 45, 45) = (45, 0, -45) takes positive x-axis to (1, 1, 1) cartesian coordinates are independent of one another, but Euler angles are notcartesian coordinates are independent of one another, but Euler angles are not Gimbal Lock Term derived from mechanical problem that arises in gimbal mechanism that supports a compass or a gyroTerm derived from mechanical problem that arises in gimbal mechanism that supports a compass or a gyro
Gimbal Lock
Occurs when two axes are aligned Second and third rotations have effect of transforming earlier rotations ex: Rot x, Rot y, Rot zex: Rot x, Rot y, Rot z –If Rot y = 90 degrees, Rot z == - Rot x Occurs when two axes are aligned Second and third rotations have effect of transforming earlier rotations ex: Rot x, Rot y, Rot zex: Rot x, Rot y, Rot z –If Rot y = 90 degrees, Rot z == - Rot x