XNA Creators Club Online
Page 1 of 1 (13 items)
Sort Posts: Previous Next

Creating Rotation Matrix from Direction?

Last post 9/30/2008 11:00 AM by bobber131. 12 replies.
  • 6/20/2008 12:15 AM

    Creating Rotation Matrix from Direction?

    I am trying to find a way to create a rotation matrix from a direction normal. I have an object moving over a custom 3D Path object and all I know at any given point is the old position and the new position which gives me its direction, now I want to take this direction knowing that this should always be the up vector of my matrix and orient my object to match. Here is the function I am currently using but the transform that is happening sometimes messes with other aspects of the matrix causing the missile object to look flat, or distorted... does anyone out there have a better solution?

     

    Vector3 up = Vector3.Normalize(vel);  
    Vector3 forward = Vector3.Normalize(Vector3.Reflect(realTransform.Forward, up));  
    Vector3 right = Vector3.Normalize(Vector3.Cross(up, forward));  
     
    Matrix matrix = realTransform;  
    matrix.Up = up;  
    matrix.Forward = forward;  
    matrix.Left = right;  
     
    realTransform = matrix; 

     

    To help clarify what I am talking about here is a picture. Both sides of the picture are using the above method to transform the missile along the path, the right side (the bad side) shows the missile as it is following part of the curve; it turns into a flat plane for a while then goes back to normal as it continues its course; does anyone know why this could be?

     

  • 6/20/2008 3:55 AM In reply to

    Re: Creating Rotation Matrix from Direction?

    One way would be to get the angle between the two vectors (see here), then use Matrix.CreateFromAxisAngle() to create the matrix.

     

  • 6/20/2008 9:36 AM In reply to

    Re: Creating Rotation Matrix from Direction?

    surely it is not the solution, but first to all, verifies that aspect ratio in the camera is really float, I to have the same problem witch the rotations and the solution was there, is necessary to do cast in width / height
  • 6/20/2008 10:58 AM In reply to

    Re: Creating Rotation Matrix from Direction?

    shaKu:

     

    Vector3 up = Vector3.Normalize(vel);  
    Vector3 forward = Vector3.Normalize(Vector3.Reflect(realTransform.Forward, up));  
    Vector3 right = Vector3.Normalize(Vector3.Cross(up, forward));  
     
    Matrix matrix = realTransform;  
    matrix.Up = up;  
    matrix.Forward = forward;  
    matrix.Left = right;  
     
    realTransform = matrix; 

     

    To help clarify what I am talking about here is a picture. Both sides of the picture are using the above method to transform the missile along the path, the right side (the bad side) shows the missile as it is following part of the curve; it turns into a flat plane for a while then goes back to normal as it continues its course; does anyone know why this could be?

     

    =============================================

    I'm assuming that your rocket is modeled so that when sitting in an identity matrix, its nose is pointing up Y, and you want it to fly nose first so you are using Up as your direction.

    I'm just guessing here, but when it flattens, you are losing information either in your Forward or Right vectors.  At some point either this line or the next is probably returning a vector full of NaN

     

    Vector3 forward = Vector3.Normalize(Vector3.Reflect(realTransform.Forward, up));  
    Vector3 right = Vector3.Normalize(Vector3.Cross(up, forward));  

     

    which would occur if your forward calculation was somehow creating a vector the same direction as Up.  That is, your realTransform.Forward reflects straight up off of Up.

    Try something like..

    Up = target - position

    Up.Normalize()

    Right = Vector3.Cross(Up, forward_vector_last_frame)

    Right.Normalize

    Forward = Vector3.Cross(Up,Right)

    Forward.Normalize.

    Unless you make a seriously sharp turn that ought to work ok.   You could also put in an "if" to check whether one direction ever equals another.

    Up = Vector3.Normalize(target - position)

    if ( Vector3.Dot (Up, forward_vector_last_frame) > .999)

        {  compute forward first, then right because UP == forward and right = NaN if you try it now}

    else

     { go ahead and compute right because forward != right}

     

     

     

     

     

     

     

     

     

    ..shaders make you feel... powerful, or very very stupid.
    http://drjbn.spaces.live.com/
  • 6/20/2008 11:09 AM In reply to

    Re: Creating Rotation Matrix from Direction?

    The easiest way (albeit not the fastest) is probably to do the folowing


        Vector3 forward = Vector3.Normalize(nextPosition - currentPosition);                     
        rotation = Matrix.Invert(Matrix.CreateLookAt(currentPosition, forward, up)); 
        up = rotation.Up; 
    Assuming you've set up good good start values for upvector, currentPosition and nextPosition, then you can just keep evaluating your spline.
  • 6/20/2008 3:56 PM In reply to

    Re: Creating Rotation Matrix from Direction?

    I wanted to see if NaN values were the problem so I changed my code to what is shown below and I get no exceptions... could there be another cause?

     

    if ((float.IsNaN(vel.X)) || (float.IsNaN(vel.Y)) || (float.IsNaN(vel.Z)))  
         throw new Exception("NAN!");  
     
    Vector3 up = Vector3.Normalize(vel);  
    Vector3 forward = Vector3.Normalize(Vector3.Reflect(realTransform.Forward, up));  
    Vector3 right = Vector3.Normalize(Vector3.Cross(up, forward));  
     
    if ((float.IsNaN(up.X)) || (float.IsNaN(up.Y)) || (float.IsNaN(up.Z)))  
         throw new Exception("NAN!");  
    if ((float.IsNaN(forward.X)) || (float.IsNaN(forward.Y)) || (float.IsNaN(forward.Z)))  
         throw new Exception("NAN!");  
    if ((float.IsNaN(right.X)) || (float.IsNaN(right.Y)) || (float.IsNaN(right.Z)))  
         throw new Exception("NAN!");  
     
    if ((forward == up) || (up == right) || (forward == right))  
         throw new Exception("Invalid Vector"); 
  • 6/20/2008 4:51 PM In reply to

    Re: Creating Rotation Matrix from Direction?

     
    shaKu:

    I wanted to see if NaN values were the problem so I changed my code to what is shown below and I get no exceptions... could there be another cause?

     

    I guess there would have to be! 

    Each of the first three rows of the matrix contain rotation and scale information.  You are clearly normalizing them all, so that won't be the issue so the only thing left I can think of with respect to constructing the matrix is orthogonality.  Somewhere, sometimes, you may have a vector creeping in that isn't orthoganal to the other two.     The only place I can see where that might be is in the calculation of your forward.   In a matrix without rotations the third element of the third row ( where the negative of Forward is inserted) is used for scaling in the Z dimension which I guess given your model's orientation would cause it to flatten.  That would again make it seem like your forward vector calculation contains the culprit.

    Have it check the dot product of each vector with each other and throw the exception if they come up other than zero.  Or, set a breakpoint on a keystroke so you can go in and investigate it with watches when it happens.

    Good luck

    Byron

    ..shaders make you feel... powerful, or very very stupid.
    http://drjbn.spaces.live.com/
  • 6/20/2008 6:50 PM In reply to

    Re: Creating Rotation Matrix from Direction?

    I did a key stroke break on a frame where the bug was happening... here are the values for the vectors...

    up {X:0.09553008 Y:0.1789631 Z:-0.9792069} Microsoft.Xna.Framework.Vector3

    forward {X:-0.1870874 Y:-0.3504838 Z:0.9176925} Microsoft.Xna.Framework.Vector3

    right {X:-0.8821828 Y:0.4709071 Z:2.155036E-09} Microsoft.Xna.Framework.Vector3

  • 6/20/2008 8:37 PM In reply to

    Re: Creating Rotation Matrix from Direction?

    Your code problem is that the vector you generate are not orthogonal. You need to orthonormalize the matrix you generate. In general, you do this by generating the other vectors through a cross product.

    The main problem you're having is that your problem is under-specified. You need two axes to specify an orientation, and you only have one (forward). If you assume some second axis (say, global Y) as the second axis, then you have singularities when your "forward" is in the same direction as the assumed axis.

    I actually like the idea of the axis/angle rotation a lot. It only has a singularity when your target matrix is 180 degrees rotated to have "up" point "down," and you can detect this case and fix it up.

    The following code generates a well-conditioned matrix that rotates your "up" to head in your "direction" (well, you have to apply right/up/backwards to the matrix yourself :-) However, it has some singularities where the orientation around the "direction" axis will have a discontinuity. You can only get rid of that kind of discontinuity by having some way of coming up with a well-defined second axis yourself.

    Vector3 right, up, backward;
    up = Vector3.Normalize(direction); // singularity when velocity is 0
    if (up.X > up.Y + 0.1 || up.Y > up.X + 0.1) right = new Vector3(up.Y, up.X, up.Z);
    else right = new Vector3(up.Y + 1, up.X, up.Z); // generate an independent vector
    backward = Vector3.Normalize(Vector3.Cross(right, up));
    right = Vector3.Cross(up, backward);
    // verify assumptions
    System.Diagnostics.Debug.Assert(Math.Abs(Vector3.Dot(right, up)) < 0.001);
    System.Diagnostics.Debug.Assert(Math.Abs(Vector3.Dot(up, backward)) < 0.001);
    System.Diagnostics.Debug.Assert(Math.Abs(Vector3.Dot(backward, right)) < 0.001);

    Jon Watte, Direct3D MVP
    Tweets, occasionally
    kW X-port 3ds Max .X exporter
    kW Animation source code
  • 6/21/2008 4:22 PM In reply to

    Re: Creating Rotation Matrix from Direction?

    Hey jwatte that works great to stop the paper effect of the object as it travels the path; the only problem I have now is when it is coming around the curve and making a severe direction change it twitches the rotation a bit; it is always pointing in the perfect direction but I can see the fins of my missle twitch as though it were rotating around the shaft of the missile. I understand why this is because of the lack of our second vector but I am not sure about ways to correct this. You said you liked the axis/angle rotation concept; do you know of a good resource which implements this or do you have a sample?
  • 6/21/2008 6:14 PM In reply to

    Re: Creating Rotation Matrix from Direction?

    I suppose it would look something like this:

      // "start" could be just the identity matrix 
      public static Matrix AxisAngleRotationFromMatrixAndDirection( 
        Matrix start, Vector3 newUp) 
      { 
        // verify assumptions -- newUp must be normalized 
        newUp = Vector3.Normalize(newUp); 
        // figure out whether straight up or straight down 
        float y = Vector3.Dot(start.Up, newUp); 
        if (y >= 1) return Matrix.Identity; 
        if (y <= -1) return Matrix.CreateRotationZ((float)Math.Pi); 
        // because it's not straight, the cross must be non-zero 
        // so use that as rotation axis 
        Vector3 axis = Vector3.Normalize(Vector3.Cross(start.Up, newUp)); 
        // now construct a linearly independent axis based on up and rotation axis 
        Vector3 right = Vector3.Cross(axis, start.Up); 
        // measure the detent "right" along that axis 
        float x = Vector3.Dot(right, newUp); 
        // use Atan2(), but rotate the coordinate system to make 0 == up 
        return Matrix.CreateFromAxisAngle(axis, (float)Math.Atan2(x, -y)); 
      } 

    Jon Watte, Direct3D MVP
    Tweets, occasionally
    kW X-port 3ds Max .X exporter
    kW Animation source code
  • 6/28/2008 7:52 AM In reply to

    Re: Creating Rotation Matrix from Direction?

    Another option is to use Matrix.CreateLookAt(). Rmember you may need to transpose your matrix afterwards.

     

  • 9/30/2008 11:00 AM In reply to

    Re: Creating Rotation Matrix from Direction?

    Hi all.


    I’m not sure the LookAt approach would work.  In essence you would have the same problem if the forward vector of the missile (almost) aligns with the world-up-vector. (In fact, you create a look-at matrix by a number of cross-products, just like shown above).

Page 1 of 1 (13 items) Previous Next