Subject: Re: Transformations with respect to an object
Date: Sun, 16 Feb 1992 23:47:24 GMT (Gary McTaggart) writes:

In a video game context, I have run into the problem of non-commutitivity of the 3d transformations used for rotation of an object. I want to be able to rotate an object with respect to itself and not the world. I got some decent results by using one vector to represent the direction that the "ship" is pointing with respect to the world and a scalar for rotation about that vector as an axis. When I want to rotate the object with respect to itself, I do the following: (PHILLIPS C J) replies:

You were off to a good start by using a vector for the ship 'forward' direction. I would strongly sugest that you store another vector for the ship's 'up' direction, and do all your rotations by vector arithmetic, and stay far far away from inverse trig functions. A 'sideways' vector for the ship may easily be found from the other two by a cross product. This gives you a 3d coordinate system aligned with the ship. Call these three vectors p,q,r. To perform a rotation in ship coordinates, (eg around the p axis) simply perform

        p' := p*cos(x)-q*sin(x)
        q' := p*sin(x)+q*cos(x)

Similar eqns used for other rotations.

As a general rule, I find vector arithmetic a hell of a lot saner to use than trig; It avoids most of the horrible singularities and multi-valued inverse problems that you get with atn's etc.

I too have been working on a similar problem and after many hours I was finally guided to CG&A (FEB 1984 pg 31). In short, it talks about the rotation of a vector about another. To save you the trouble:

        [v] = [vx, vy, vz]      the vector to be rotated.
        [l] = [lx, ly, lz]      the vector about rotation
              | 1  0  0|
        [i] = | 0  1  0|           the identity matrix        
              | 0  0  1|
              |   0  lz -ly |
        [L] = | -lz   0  lx |
              |  ly -lx   0 |

        d = sqrt(lx*lx + ly*ly + lz*lz)
        a                       the angle of rotation


   matrix operations gives:

    [v] = [v]x{[i] + sin(a)/d*[L] + ((1 - cos(a))/(d*d)*([L]x[L]))} 

Therefore if you wish to rotated you ship left, you would rotated the forward dirction vector about the up vector. If you wish to pull up, you would rotate the direction vector and the up vector about their cross product (the normal).

Newsgroups: sci.math,,
From: (Tom Davis)
Subject: Re: How do you do a 3-D rotation about an arbitrary vector?
Date: Thu, 22 Apr 93 15:36:45 GMT (Mike Guttman) writes:

I have an arbitrary plane in 3-space, which can be described by

	-   ^
	p . n + D = 0 ,

where 'p' is a given point on the plane and 'n' is the normal vector. (This is analogous to Ax+By+Cz+D=0, where A^2+B^2+C^2=1.)

Now, I wish to rotate the plane by angle theta about a normal vector passing through the plane at point 'p'. I suppose this vector can be expressed as

	-   -    ^
	v = p + sn ,	

where 's' is a scalar.

We all know the matrices to use for rotation about the x, y or z-axes, but what matrix or series of matrices can I use for rotation about an arbitrary axis, such as 'v' above?

First translate to the origin, rotate about the origin as described below, and then translate back.

To rotate about an arbitrary axis around the origin, assume that the axis is normalized (has length = 1), and is given by v = (x, y, z)^T. ("^T" means "transpose").

Construct the matrix S:

    S = [  0 -z  y ]
        [  z  0 -x ]
        [ -y  x  0 ]

Now create the matrix R:

    R = v*v^T + cos(T)*(I - v*v^T) + sin(T)*S

T is the angle of rotation; I is a 3x3 identity matrix, and "*" represents scalar or matrix multiplication, as appropriate.

If you fill out a 4x4 matrix as follows:

    [       0 ]
    [   R   0 ]
    [       0 ],
    [ 0 0 0 1 ]

it will serve as the rotation matrix.

Newsgroups: sci.math,,
From: (Karl Hahn)
Subject: Re: How do you do a 3-D rotation about an arbitrary vector?
Date: Wed, 28 Apr 1993 22:52:38 GMT (Mike Guttman) writes:

We all know the matrices to use for rotation about the x, y or z-axes, but what matrix or series of matrices can I use for rotation about an arbitrary axis, such as 'v' above?

Another, conceptually easier way to rotate about an arbitrary axis that passes through the origin is the method of quaternions. This system is not taught much, except in robotics and mechanics classes, but it really is quite elegant.

The quaternion system is a system of 3 complex planes that share a common real axis. Thus, a quaternion is a 4-vector, with components I will call r, i, j, and k. For the purposes of vector rotation, it is better to think of it as an object containing a scalar part (r) and a vector part (i, j, and k). The i, j, and k refer respectively to the x, y, and z components of a 3-vector.

Quaternions add like any other vectors. Multiplication is where it gets interesting. If we denote a quaternion as <S, V> where R is the scalar part and V is the vector part, the product is defined as follows:

      <S1, V1> * <S2, V2> = < (S1*S2) - (V1 dot V2),
                              (S1*V2) + (S2*V1) + (V1 cross V2) >

Note that this operation is NOT commutative but IS associative.

We also define COMP<S, V> = <S, -V>.

If a 3-vector is represented by a homogeneous quaternion, that is one whose scalar part is zero, then to rotate a vector <0, V> through an angle theta about an axis vector A, do the following:

    let Q = < -cos(theta/2), A * sin(theta/2) >

    rotated vector = Q * <0, V> * COMP Q

The two beautiful things about this are a) vectors and operators (Q is an operator in this case) are represented the same way, and b) Q is formed easily from the axis vector and the angle.

For those interested, I have code I can share in both C and C++ that manipulates quaternions.