transformation doc

Upload: nishant-goel

Post on 04-Apr-2018

215 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/30/2019 Transformation Doc

    1/4

    The way presented for doing rotations in the last tutorial wasn't really a good one. It works just fine in

    two dimensions, but as soon as you want to rotate around the X or Y-axes, it becomes more difficult.

    Sure, it's easy to make equations that will represent a rotation on any one of those axes, but just go

    ahead and try to make equations that will represent changes on three axes at once. If you manage to

    pull that off, make sure to let us know. Meanwhile, I'll present a way to do the rotations with matrices.

    Matrices might seem scary, especially to someone who has never used them before. However, they

    really aren't too difficult to use. They're also very powerful. The first thing to note is that it is possible

    to use a vector to specify a point in 3d space. Basically, every point is a displacement from the origin by

    a certain amount, which is described by the vector. Vectors are useful for lots of other things as well,

    and perhaps someday I'll write about some of those. Meanwhile, we'll just use them for storing points.

    A vector can be multiplied by a matrix, and after the multiplication, you'll get a new vector. This may

    seem useless, but when you multiply the vector by the right matrix, you'll get a point that has been

    transformed by the matrix. This can mean rotated on any axis (including arbitrary ones! that will come

    later), translated, or both. You see, the thing with matrices is this: If you have one matrix representing

    rotation on the X axis, and another matrix representing rotation on the Y axis, you can multiply them

    together to get a new matrix which represents the rotation on both axes. However, in case you didn't

    catch this in any tutorials you read about matrices, please note that if A and B are matrices, A*B != B*A.

    This will cause us some problems later, but for now, just keep it in the back of your mind.

    I'm not going to derive these matrices that I'm about to give you here. One reason is that it's been done

    other places. Another reason is that it would involve me explaining a lot of things that have also been

    explained better elsewhere. The most important reason is because I can't. However, that doesn't

    matter. You don't need to be able to derive these matrices; you just need to know how to use them.

    You'll also need to know which coordinate system you're using: left-handed or right-handed. OpenGL

    uses right-handed coordinates; DirectX uses left-handed coordinates. This is also explained in detail

    elsewhere, so I won't go into it. If you're not using OpenGL or DirectX, either figure out what your API

    uses, or if you're writing your own or something, pick one and stick with it. There will be no turning

    back.

    Where (phi) represents the rotation about the X axis, (theta) represents the rotation about the Y axis,

    and (psi) represents the rotation about the Z axis

    Those really aren't as complicated as they look. And for those of you wondering why I didn't store all of

    those in 3*3 matrices, just hold on ;) That's coming later. For the purposes of this tutorial, I'm going to

    try to avoid picking a coordinate system, so that it will be equally useful for both OpenGL and DirectXprogrammers. We'll call the rotation matrix for the X axis matRotationX, the rotation matrix for the Y

    axis matRotationY, and the rotation matrix for the Z axis matRotationZ.

    By multiplying the vector representing a point by one of these matrices (with the values properly filled

    in), you can rotate the point around any axis. However, you'll probably want to allow rotation about all

  • 7/30/2019 Transformation Doc

    2/4

    three axes. You could multiply the vector by one matrix, then multiply it by the next matrix, then

    multiply it by the next matrix... but that would produce some very slow code, because you would be

    performing far too many operations for each point. Matrices can be combined, which will save you

    some very valuable time in your code. We'll call the matrix which represents all your rotations

    matRotationTotal, and here's the way to generate it:

    matRotationTotal = matRotationX * matRotationY * matRotationZ

    After that, you can simply transform each point with matRotationTotal, and the point will be rotated

    about all three axes. When you need to change the amount of rotation, rebuild matRotationX,

    matRotationY, and matRotationZ, and then multiply them together to get the new matRotationTotal.

    Pretty easy, and it gets points rotating around in three dimensions. (Note: If you don't know how to

    multiply matrices, or if you don't know how to multiply a vector by a matrix, consult a basic tutorial and

    matrix math. To give you a hint, a vector can be represented by a 1*4 matrix...).

    ROTATION ABOUT ANY AXIS

    The previous method of doing the rotations is called using Euler angles. It's probably the simplest way

    of doing rotations, but it has some problems. The biggest problem is called gimbal lock. You may or

    may not have already encountered this if you wrote code according to the last tutorial. If you

    encountered it and noticed it, without knowing what it was, you may have spent hours trying to figure

    out where you went wrong in your code, carefully comparing every line of your code to the tutorial,trying to find the difference. If that happened, I'm sorry. There is nothing wrong with your code; there

    is something wrong with the math. If you'll recall, I told you two very important things, which you

    probably didn't connect in the last tutorial. 1) Matrix multiplication is not commutative. A*B != B*A. 2)

    We generated matRotationTotal by doing matRotationX * matRotationY * matRotationZ. If there was

    nothing wrong with the math, you should have been able to do

    matRotationY*matRotationZ*matRotationX, or any other order, and gotten exactly the same results.

    But you wouldn't. This problem is the root cause of gimbal lock. Trying to visualize this might blow your

    mind, so if you don't understand the next paragraph, don't worry too much. Just remember that Gimbal

    Lock happens when one axis gets rotated before another axis, and the axes are no longer mutually

    perpendicular. It can be a large problem, or it can go unnoticed, depending on the application.

    We multiplied our matrices in the order matRotationX * matRotationY * matRotationZ. It seemed to

    work, and for the most part, it did. But if you think about it carefully, you'll realize that, as you move an

    object in 3d space, all three axes change at once. They remain mutually perpendicular to one another.

    In the program, however, we're rotating the object over the X-axis first. That rotates the Y and Z-axes.

    Then we rotate over the Y axis, but since we've already rotated over the X-axis, the rotation on the Yaxis

  • 7/30/2019 Transformation Doc

    3/4

    only changes the location of the Z-axis. The rotation of the Z-axis does not change the location of either

    of the other two axes. Huge problem if you need to rotate on all three axes, because one axis can

    literally end up on top of another axis! (Just in the math. It can't do that in real life, meaning our

    representation is not accurate)

    Luckily for you, many math geniuses have dealt with this problem. There was a famous man namedEuler, whom you'll hear mentioned in Calculus. He determined that any series of rotations in three

    dimensional space can be represented as a single rotation over an arbitrary axis. For this

    representation, called angle/axis representation, you'll need to store the arbitrary axis about which you

    are rotating, and the amount by which you are rotating.

    Now for the cameo by Charles, who was kind enough to write the following section for me: Arbitrary

    axis rotation by Charles Thibault

    I am going to describe the calculations I perform in order to perform rotations about an arbitrary axis.

    These calculations are NOT the matrix form of the rotations. Up to this point you know you can

    combine matrices into a single transformation. The single transformation matrix involves about 29

    multiplication operations and 9 addition operations, whereas completely rotating a vector using my

    transformations (meaning calling my RotateVector function TWICE, once over the Y axis then once over

    the Strafe vector) entails about ten percent more multiplications and about twice as many addition

    operations (32 multiplications for two RotateVector calls, and 18 addition operations for two

    RotateVector calls).

    How do you actually perform a rotation about an arbitrary axis? Well firstly you must understand

    rotations in two dimensions, because the concept stays the same on an arbitrary plane. I'm going to

    make this as short and sweet as possible. Instead of rotating the X and Y components of a vector, the X

    is really the component of the vector you are trying to rotate Perpendicular to the vector that is thenormal to the plane. Likewise the Y is really the cross product between the vector you are trying to

    rotate about and the actual vector being rotated.

    Steps to rotate a vector:

    -Calculate the Perpendicular component, multiply it by the cosine of the angle you are trying to rotate

    through

    -Calculate the cross product between the vector you are trying to rotate about and the vector you arerotating, multiply it by the sine of the angle

    -Add the results together

    -Add the component of the vector you are trying to rotate that is parallel to the vector you are rotating

    about

  • 7/30/2019 Transformation Doc

    4/4

    Note it is not totally necessary to calculate the parallel component if the vector you are rotating and the

    vector you are rotating about are already orthogonal. I do it in all cases anyway to avoid any mishaps

    and make sure it is mathematically correct, but it seems to work both ways. Plus, by leaving it in the

    code you can rotate vector A about vector P even if A and P are not orthogonal. (orthogonal means

    mutually perpendicular to one another)

    The rest of this will, once again, be written by me (Confuted).

    There's still the problem of performing the actual rotation about your arbitrary axis. Luckily, this can

    also be done with a matrix. Again, I'm not going to derive it, I'm going to spoon feed it to you. You can

    thank me later.

    Where c = cos (theta), s = sin (theta), t = 1-cos (theta), and is the unit vector representing the

    arbitrary axis

    Now, you can replace matRotationTotal with this matrix, and completely eliminate matRotationX,

    matRotationY, and matRotationZ. Of course, there is extra math involved elsewhere. But by using theaxis/angle representation for your rotations, it is possible to avoid gimbal lock. However, it's also

    possible to still suffer from it, if you do something incorrectly. In the next tutorial, I'll talk about some of

    the uses for the things I've been saying, and after that, brace yourself for the exciting and strange world

    of quaternions. If you don't have a headache from thinking too much yet, you probably will after the

    quaternions.