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 Y-axis 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 named Euler, 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 the normal 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 are rotating, 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
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.
Luckily for you, many math geniuses have dealt with this problem. There was a famous man named Euler, 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 the normal 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 are rotating, 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
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.
Left
Handed *
|
Right
Handed *
|
||||||||||||||||||||||||||||||||
|
|
Where
c = cos (theta), s = sin (theta), t = 1-cos (theta), and <X,Y,Z>
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
the
axis/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.
No comments:
Post a Comment
if You Need Any Help Then Write Us:We Come Back With Solution