Original: http://oviliazhang.diandian.com/post/2012-05-19/40027878859
As most of the current display is two-dimensional, to control the rotation of three-dimensional objects appear less straightforward. Arcball is a method of mapping two-dimensional mouse position changes to three-dimensional object rotation, allowing the user to control the rotation of the object in a very intuitive way.
Online related methods are still many, including:
Http://rainwarrior.thenoos.net/dragon/arcball.html
http://nehe.gamedev.net/tutorial/arcball_rotation/19003/
Of course, Nehe's example is still very difficult to understand, always feel that the algorithm is very good people code readability is too poor, may be the pursuit of the efficiency of the code, suffering the reader.
I think the clearest thing to say is this http://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Arcball.
Let's start with Arcball's thoughts.
Word, is to think of the screen as a ball, drag the mouse is in the rotation of the ball.
Four steps to control Http://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Arcball:
1. First press the mouse and drag the mouse coordinates as q1,q2,x and y respectively by the screen size to zoom to [-1, 1]. such as: Q1 (+), Q2 (800, 600), screen size 1000x800. The P1 ( -0.8, -0.25), P2 (0.6,-0.5) are scaled. The reason to do this mapping is to facilitate the calculation of the future, that is Nehe said happy coinsidence~
C + + language: highlighted code provided by the germination NET//map (x, y) to [-1.0, 1.0]
Vec. x = 2.0 * x/width-1.0;
Y is set to being opposite since the coordinates of screen and
OpenGL is different
Vec. y = 1.0-2.0 * y/height;
2. Turn the two-dimensional coordinates into three-dimensional, this is the most critical. Now we can think of the screen as a sphere of XYZ, which is [-1, 1], where the sphere is (0, 0, 0).
For example, A and B are two mouse map points, from the front view, a on the ball "(the correct understanding here is the ball shell, not the inside of the sphere); B is outside the sphere. The reason that a is on the ball shell is that we are supposed to do it in order to correspond to the rotation of the sphere. Since a is on the shell, we have the corresponding z-values (x, y, z squared sum of 1, because on the spherical shell) based on the X, Y value, and for B, we move it "nearest" to the spherical shell, so what is the nearest point to B on the shell? It should look like this from a front view:
So we think the z coordinate of point C is 0.
So the three-dimensional coordinate calculation method:
C + + language: The highlighted code is provided by the germination net double square = Vec. X * VEC. x + VEC. Y * Vec. Y
if (square <= 1.0) {
if (x, y) is within the circle of radius 1
Calculate z So, the modulus of vector is 1
Vec. z = qsqrt (1.0-square);
} else {
If is out of the circle, do nomarlization
This vector was the nearest position on the circle
So, Z is 0
Double length = qsqrt (square);
Vec. x/= length;
Vec. Y/= length;
Vec. z = 0.0;
}
3. Next, the rotation angle is obtained. We know that vector a-point multiplication vector b=| a| | B|cos (Alpha) where alpha is the vector angle. According to the first two steps, we can get the mouse down position A and drag the current position on the ball coordinate B, now we want to find out the angle of the vector OA and OB. Then happy coinsidence, because the radius of the ball is 1, so | oa|=| Ob|=1. So Alpha=arccos (dot product of A and B).
C + + language: The highlighted code is provided by the germination net double arcball:: Getrotateangle (Vector3D vec1, Vector3D vec2)
{
Return Qacos (vec1 dotProduct (VEC2));
}
4. We know that Glrotatex requires three parameters: a rotation angle and three coordinates for a rotating axis. So then we're going to ask for the axis of rotation. Now that the dot product has played a role, this time we are going to let the fork take the limelight. The result of the vector A and B cross-multiplication is the normal vector of their plane, which means the axis of rotation we require.
With the rotation angle and rotation axis, is it glrotatex to solve the problem?
But since we only calculated the position of the mouse and the current position of the mouse rotation effect, so the last rotation of the effect of the second time when the mouse was lost. It is obviously not a good idea to record the rotation angle and rotation axis for each time, since the number of rotations is so much that it is not appropriate to call very many glrotatex each frame. So we record the rotation matrix for each rotation, and then we use matrix multiplication to achieve the cumulative rotation effect.
The rotational angle and rotation axes are known to be rotated by: http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle
There are many other places on the Internet has this formula, but the actual effect is reversed, I can not think of its solution, today tried to transpose this matrix, unexpectedly, but do not know what is the reason, is not the right hand system of the relationship.
Here, we will solve the three-dimensional rotation with the Arcball two-dimensional control.
Here are a few ways to record the amount of rotation:
1. Rotation angle and rotation axis: rotate an angle around an axis
Rotation matrix:
2. Euler angle: The angle of rotation around the three axes respectively, note that the axis is rotated three times, not once. It's like saying, go around the y-axis 30 degrees, then rotate around the x-axis by 20 degrees, then rotate 50 degrees around the z-axis. It takes three times to use Glrotatex. The order of rotation is also relevant, and in case of bad choice, will cause the universal lock phenomenon.
Rotation matrix:
3. As for the $ four, I have not made myself clear.
"Reprint" Arcball two-dimensional control three-dimensional rotation