geQuaternion

Description: Quaternion mathematical system interface

Source file: …\genis3d\OpenSource\Source\Math\quatern.h

Contents:

API Functions: Copy, Normalize, SetFromAxisAngle, ToMatrix

Other Functions: Add, Compare, Exp, FromMatrix, Get, GetAxisAngle, GetVec3d, Inverse, IsUnit, IsValid, Ln, Magnitude, Multiply, Rotate, Scale, Set, SetNoRotation, SetVec3d, Slerp, SlerpNotShortest, Subtract,

Types: geQuaternion

Constants: QUATERNION_PI

Notes: view

Changes for Genesis3D v1.6: None

 

Types:

geQuaternion;

typedef struct{
   geFloat W;
   geFloat   X,Y,Z;
    // geVec3d   QuatV;
} geQuaternion;

  • Return to Contents


  • Constants:

    QUATERNION_PI;

    #define QUATERNION_PI (GE_PI)

    Return to Contents

    Functions:

    void GENESISCC geQuaternion_Add(const geQuaternion* Q1, const geQuaternion* Q2, geQuaternion* QSum);

    This function adds Q1 to Q2 returning the result in QSum.

    Returns: nothing.

    Notes:
        from QUATERN.H: QSum = Q1 + Q2  (result is not generally a unit quaternion!)


    Return to Contents

    geBoolean GENESISCC geQuaternion_Compare(geQuaternion* Q1, geQuaternion* Q2, geFloat Tolerance);

    This function checks whether Q1 and Q2 differ by no more than Tolerance.  The check is done element by element, if anyone element differs by more than tolerance then GE_FALSE is returned.

    Returns: GE_TRUE if Q1 and Q2 differ by no more than Tolerance, otherwise GE_FALSE.

    Notes:
        from QUATERN.H: return GE_TRUE if quaternions differ elementwise by less than Tolerance.


    Return to Contents

    GENESISAPI void GENESISCC geQuaternion_Copy(const geQuaternion* QSrc, geQuaternion* QDst);

    This function copies the contents of QSrc in QDst.  QDst must not be BasetypesIndexed.htm - NULLNULL.

    Returns: nothing.

    Notes:
        from QUATERN.H: copies quaternion QSrc into QDst


    Return to Contents

    void GENESISCC geQuaternion_Exp(const geQuaternion* Q, geQuaternion* ExpQ);

    This function calculates eQ.  Q.W must equal 0.0.

    Returns: nothing.

    Notes:
        from QUATERN.H: exp(Q) for pure quaternion only!  (zero scalar part (W))


    Return to Contents

    void GENESISCC geQuaternion_FromMatrix(const geXForm3d * RotationMatrix, geQuaternion* QDest);

    This function sets up QDest from the transformat RotationMatrix.  The resulting quaternion will only have the rotational transform part of the transformation matrix.

    Returns: nothing.

    Notes:
        from QUATERN.H: takes upper 3 by 3 portion of matrix (rotation sub matrix) and generates a quaternion.


    Return to Contents

    void GENESISCC geQuaternion_Get(const geQuaternion* Q, geFloat* W, geFloat* X, geFloat* Y, geFloat* Z);

    This function returns the components of Q in (W,X,Y,Z).

    Returns: nothing.

    Notes:
        from QUATERN.H: get quaternion components into W,X,Y,Z


    Return to Contents

    geBoolean GENESISCC geQuaternion_GetAxisAngle(const geQuaternion* Q, geVec3d* Axis, geFloat* Theta);

    This function returns the rotational transformation represented by Q as an angle Theta and axis of rotation Axis.

    Returns: GE_TRUE on success, GE_FALSE otherwise.

    Notes:
        from QUATERN.H: gets an axis and angle of rotation around the axis from a quaternion.  returns GE_TRUE if there is an axis. returns GE_FALSE if there is no axis (and Axis is set to 0,0,0, and Theta is 0)


    Return to Contents

    void GENESISCC geQuaternion_GetVec3d(const geQuaternion* Q, geFloat* W, geVec3d* V);

    This function returns the components of Q as a scalar W and a vector V.

    Returns: nothing.

    Notes:
        from QUATERN.H: get quaternion components into W and V


    Return to Contents

    void GENESISCC geQuaternion_Inverse(const geQuaternion* Q, geQuaternion* QInv);

    This function calculates the inverse of Q and returns it as QInv.

    Returns: nothing.

    Notes:
        from QUATERN.H: sets QInv to the inverse of Q.


    Return to Contents

    geBoolean GENESISCC geQuaternion_IsUnit(const geQuaternion* Q);

    This function checks to see the Q is a unit quaternion.

    Returns: GE_TRUE of Q is a unit quaternion, GE_FALSE otherwise.

    Notes:
        from QUATERN.H: returns GE_TRUE if q is a unit quaternion.  GE_FALSE otherwise.


    Return to Contents

    geBoolean GENESISCC geQuaternion_IsValid(const geQuaternion* Q);

    This function checks that all the elements of Q are real numbers.

    Returns: GE_TRUE of Q is valid, GE_FALSE otherwise.

    Notes:
        from QUATERN.H: return GE_TRUE if Q is non null and for has no NAN's in its components

    Return to Contents

    void GENESISCC geQuaternion_Ln(const geQuaternion* Q, geQuaternion* LnQ);

    This function calculates the natural logarithm of Q returning the result in LnQ.  Q must be a unit quaternion.

    Returns: nothing.

    Notes:
        from QUATERN.H: ln(Q) for unit quaternion only!


    Return to Contents

    geFloat GENESISCC geQuaternion_Magnitude(const geQuaternion* Q);

    This function calculates the Magnitude of Q and returns it.

    Returns: The magnitude of Q.

    Notes:
        from QUATERN.H: returns Magnitude of Q.

    Questions:
       What does the Magnitude of a Quaternion represent?  What is it useful for?

    Return to Contents

    void GENESISCC geQuaternion_Multiply(const geQuaternion* Q1, const geQuaternion* Q2, geQuaternion* QProduct);

    This function multiplies Q1 by Q2 returning the result in QProduct.

    Returns: nothing.

    Notes:
        from QUATERN.H: multiplies q1* q2, and places the result in q.  No failure.  Renormalization not automatic


    Return to Contents

    GENESISAPI geFloat GENESISCC geQuaternion_Normalize(geQuaternion* Q);

    This function normalizes Q and returns its original magnitude.  Q is modified by the resulting normalization.

    Returns: the inital magnitude of Q.

    Notes:
        from QUATERN.H: normalizes q to be a unit quaternion.  returns original magnitude of q


    Return to Contents

    void GENESISCC geQuaternion_Rotate(const geQuaternion* Q, const geVec3d* V, geVec3d* VRotated);

    This function rotates a vector V by the quaternion Q returning the resulting rotated vector in VRotated.

    Returns: nothing.

    Notes:
        from QUATERN.H: Rotates V by the quaternion Q, places the result in VRotated.


    Return to Contents

    void GENESISCC geQuaternion_Scale(const geQuaternion* Q, geFloat Scale, geQuaternion* QScaled);

    This function scales the quaternion Q by Scale returning the result in QScaled.

    Returns: nothing.

    Notes:
        from QUATERN.H: Q = Q* Scale  (result is not generally a unit quaternion!)


    Return to Contents

    void GENESISCC geQuaternion_Set(geQuaternion* Q, geFloat W, geFloat X, geFloat Y, geFloat Z);

    This function sets the components of Q to (W,X,Y,Z).

    Returns: nothing.

    Notes:
        from QUATERN.H: set quaternion components.  Doesn't normalize.


    Return to Contents

    GENESISAPI void GENESISCC geQuaternion_SetFromAxisAngle(geQuaternion* Q, const geVec3d* Axis, geFloat Theta);

    This function sets up the quaternion Q to a rotation about the axis Axis by the angle Theta.

    Returns: nothing.

    Notes:
        from QUATERN.H: set a quaternion from an axis and a rotation around the axis


    Return to Contents

    void GENESISCC geQuaternion_SetNoRotation(geQuaternion* Q);

    This function sets Q to be a quaternion with NO rotation.

    Returns: nothing.

    Notes:
        from QUATERN.H: sets Q to be a quaternion with no rotation (like an identity matrix)


    Return to Contents

    void GENESISCC geQuaternion_SetVec3d(geQuaternion* Q, geFloat W, const geVec3d* V);

    This function sets the components of Q using the scalar W and the vector V.

    Returns: nothing.

    Notes:
        from QUATERN.H: set quaternion components.  Doesn't normalize


    Return to Contents

    void GENESISCC geQuaternion_Slerp(const geQuaternion* Q0, const geQuaternion* Q1, geFloat T, geQuaternion* QT);

    This function uses spherical interpolation to interpolate betwen Q0 and Q1 at T (0 <= T <= 1) returning the result in QT.  At T=0 QT=Q0, at T=1 QT=Q1.  QT will always be returned with a positive W (this implies that the route taken is always the shortest through the positive W domain).

    Returns: nothing.

    Notes:
        from QUATERN.H: Spherical interpolation between q0 and q1. 0<=t<=1 resulting quaternion is 'between' q0 and q1 with t==0 being all q0, and t==1 being all q1. returns a quaternion with a positive W - always takes shortest route through the positive W domain.


    Return to Contents

    void GENESISCC geQuaternion_SlerpNotShortest(const geQuaternion * Q0, const geQuaternion * Q1, geFloat T, geQuaternion* QT);

    This function uses spherical interpolation to interpolate betwen Q0 and Q1 at T (0 <= T <= 1) returning the result in QT.  I'm not sure exactly how this differs from the standard Slerp above.

    Returns: nothing.

    Notes:
        from QUATERN.H: spherical interpolation between q0 and q1. 0<=t<=1 resulting quaternion is 'between' q0 and q1 with t==0 being all q0, and t==1 being all q1.


    Return to Contents

    void GENESISCC geQuaternion_Subtract(const geQuaternion* Q1, const geQuaternion* Q2, geQuaternion* QDifference);

    This function subtracts Q2 from Q1 returning the result in QDifference.

    Returns: nothing.

    Notes:
        from QUATERN.H: QDifference = Q1 - Q2  (result is not generally a unit quaternion!)


    Return to Contents

    GENESISAPI void GENESISCC geQuaternion_ToMatrix(const geQuaternion* Q, geXForm3d* RotationMatrixDest);

    This function calculates the transformation matrix RotationMatrixDest resulting from the quaternion Q.

    Returns: nothing.

    Notes:
        from QUATERN.H: takes a unit quaternion and makes RotationMatrixDest an equivelant rotation xform. (any translation in RotationMatrixDest will be lost)

    Return to Contents

    Notes:

    Return to Contents

    KDTOP Notes:

    Quaternions were extremely confusing when I first encountered them. I read "an extension of complex numbers" and thought, "forget it!" I was reasonably good at college math, but I've forgotten much of it. And who needs them anyway? I didn't --at least at first.

    Then I ran into the problem of trying to create a rotation matrix that would rotate an actor around an arbitrary axis. I knew how to rotate about the world's X, Y, or Z axis, but how could I rotate about some other axis? I was simulating a ball that my actor could throw. I thought, "wouldn't it be cool if, upon landing, it rolled like a real ball?" But what a headache to figure out a matrix that would do that! So I started reading graphics-for-games books, and guess what I found? You guessed it, quaternions.

    So here is the overview of what I've learned about quaternions:

    LOOK AT THIS... Here is a great page that helped me understand: view

    Note: some of these these quanternion functions are not part of the Genesis3d API (notice the lack of GENESISAPI in front of some functions.) So to get access to the full library, the code must be included in one's project.

    Here's a great little function that uses quaternions to rotate a matrix about any arbitrary axis. view

     

    Now, here are some original notes...

    (The following was ripped from the Genesis 3D header file quatern.h)

    The quatern module contains basic support for a quaternion object.

    Quaternions are an extension of complex numbers that allows an expression for rotation that can be easily interpolated.  geQuaternions are also  more numericaly stable for repeated rotations than matrices.

    A quaternion is a 4 element 'vector'  [w,x,y,z] where:

    q = w + xi + yj + zk
    i*i = -1
    j*j = -1
    k*k = -1
    i*j = -j*i = k
    j*k = -k*j = i
    k*i = -i*k = j
    q' (conjugate) = w - xi - yj - zk
    ||q|| (magnitude) = sqrt(q*q') = sqrt(w*w + x*x + y*y + z*z)
    unit quaternion ||q|| == 1; this implies  q' == qinverse
    quaternions are associative (q1*q2)*q3 == q1*(q2*q3)
    quaternions are not commutative  q1*q2 != q2*q1
    qinverse (inverse (1/q) ) = q'/(q*q')

    Q can be expressed by w + xi + yj + zk or [w,x,y,z] or as in this implementation (s,v) where s=w, and v=[x,y,z].

    Quaternions can represent a rotation.  The rotation is an angle t, around a unit vector u.   q = (s,v);  s = cos(t/2);   v =  u*sin(t/2).

    Quaternions can apply the rotation to a point.  Let the point be p [px,py,pz] and let P be a quaternion(0,p).  Protated = q*P*qinverse (Protated = q*P*q' if q is a unit quaternion)
    Concatenation of rotations is similar to matrix concatenation.  Given two rotations q1 and q2, to rotate by q1, then q2:  let qc = (q2*q1), then the combined rotation is given by qc*P*qcinverse (= qc*P*qc' if q is a unit quaternion)

    Multiplication:

    q1 = w1 + x1i + y1j + z1k
    q2 = w2 + x2i + y2j + z2k
    q1*q2 = q3 = (w1*w2 - x1*x2 - y1*y2 - z1*z2)        {w3}
                        (w1*x2 + x1*w2 + y1*z2 - z1*y2)i      {x3}
                        (w1*y2 - x1*z2 + y1*w2 + z1*x2)j      {y3}
                        (w1*z2 + x1*y2 + y1*x2 + z1*w2)k    {z3}

    Also,

    q1 = (s1,v1) = [s1,(x1,y1,z1)]
    q2 = (s2,v2) = [s2,(x2,y2,z2)]
    q1*q2 = q3 = (s1*s2 - dot_product(v1,v2),                   {s3}
                        (s1*v2 + s2*v1 + cross_product(v1,v2))   {v3}

    Interpolation - it is possible (and sometimes reasonable) to interpolate between two quaternions by interpolating each component.  This does not quarantee a resulting unit quaternion, and will result in an animation with non-linear rotational velocity.

    Spherical interpolation: (slerp) treat the quaternions as vectors find the angle between them (w = arccos(q1 dot q2) ). Given 0<=t<=1,  q(t) = q1*(sin((1-t)*w)/sin(w) + q2* sin(t*w)/sin(w).  Since q == -q, care must be taken to rotate the proper way.

    This implementation uses the notation quaternion q = (quatS,quatV) where quatS is a scalar, and quatV is a 3 element vector.

     

    Return to Contents