Rotating a Vector in 3D Space

2019-01-12 18:56发布

问题:

I am making an android project in opengl es that uses accelerometer to calculate change in specific axes and my aim is to rotate my spacecraft-like object's movement vector. The problem is that i can't understand the math behind rotation matrices. Default movement vector is 0,1,0 , means +y, so the object looks upward in the beginning. and i am trying to rotate its movement vector so i can move the object where it points. I can gather rotation changes in phone. x-axis : rotate[0], y-axis : rotate[1], z-axis : rotate[2]. How can i rotate my movement vector using rotation matrix ?

回答1:

If you want to rotate a vector you should construct what is known as a rotation matrix.

Rotation in 2D

Say you want to rotate a vector or a point by θ, then trigonometry states that the new coordinates are

    x' = x cos θ − y sin θ
    y' = x sin θ + y cos θ

To demo this, let's take the cardinal axes of X and Y; when we rotate the X-axis 90° counter-clockwise, we should end up with the X-axis transformed into Y-axis. X-axis as a unit-vector is

    unit vector along X axis = <1, 0>
    x' = 1 cos 90 − 0 sin 90 = 0
    y' = 1 sin 90 + 0 cos 90 = 1
    New coordinates of the vector = <x', y'> = <0, 1> => Y-axis.

When you understand this, creating a matrix to do this becomes simple. A matrix is just a mathematical tool to perform this in a comfortable, generalized way so that various transformations like rotation, scale and translation (moving) can be combined and performed in a single step, using one common method. From linear algebra, to rotate a point or vector in 2D, the matrix to be built is

    |cos θ   −sin θ| |x| = |x cos θ − y sin θ| = |x'|
    |sin θ    cos θ| |y|   |x sin θ + y cos θ|   |y'|

Rotation in 3D

That works in 2D, while in 3D we need to take in to account the third axis. Rotating a vector around the origin (a point) in 2D simply means rotating it around the Z-axis (a line) in 3D; since we're rotating around Z-axis its coordinates should kept constant i.e. 0° (the rotation happens on the XY plane in 3D). In 3D rotating around the Z-axis would be

    |cos θ   −sin θ   0| |x|   |x cos θ − y sin θ|   |x'|
    |sin θ    cos θ   0| |y| = |x sin θ + y cos θ| = |y'|
    |  0       0      1| |z|   |        z        |   |z'|

around the Y-axis would be

    | cos θ    0   sin θ| |x|   | x cos θ + z sin θ|   |x'|
    |   0      1       0| |y| = |         y        | = |y'|
    |−sin θ    0   cos θ| |z|   |−x sin θ + z cos θ|   |z'|

around the X-axis would be

    |1     0           0| |x|   |        x        |   |x'|
    |0   cos θ    −sin θ| |y| = |y cos θ − z sin θ| = |y'|
    |0   sin θ     cos θ| |z|   |y sin θ + z cos θ|   |z'|

Note that the axis around which rotation is done has no sin or cos elements in the matrix. I hope this makes the rotation case clear.

Composition

The aforementioned matrices rotate an object as if the object is at a distance r = √(x² + y²) from the origin; lookup polar coordinates to know why. This rotation will be with respect to the world space origin. Usually we need to rotate an object around its own frame/pivot and not around the world's. Since not all objects are at the world origin, rotating using these matrices will not give the desired result of rotating around the object's own frame. Hence you need to learn about translation too. You'd first translate (move) the object to world origin (so that the object's origin would align with the world's, thereby making r = 0), perform the rotation with one (or more) of these matrices and then translate it back again to its previous location. The order in which the transforms are applied matters.

I urge you to read about linear and affine transformations and their composition to perform multiple transformations in one shot, before playing with transformations in code. Without understanding the basic maths behind it, debugging transformations would be a nightmare. I found this lecture video to be a very good resource. Another resource is this tutorial on transformations that aims to be intuitive and illustrates the ideas with animation.

Note: This method of performing rotations follows the Euler angle rotation system, which is simpler to teach and to grasp. This works perfectly fine for 2D and for simple 3D cases; but when rotation needs to be performed around all three axes at the same time then Euler angles are not sufficient for this due to an inherent deficiency in this system which manifests itself as Gimbal lock. People resort to Quaternions in such situations, which is more advanced than this but doesn't suffer from Gimbal locks when used correctly.



回答2:

Reference docs here: http://developer.android.com/reference/android/opengl/Matrix.html

  1. Build a rotation matrix
  2. Transform the vector with the matrix

You don't need to understand the math, the library functions will get the job done.