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

Pointing an object towards a given point, and other cool game math!

Last post 09-03-2008 3:22 PM by Lord Ikon. 5 replies.
  • 03-25-2008 3:22 PM

    Pointing an object towards a given point, and other cool game math!

    Once a week, we see the question "How do I make one object point to face another position/object?"
    Often, the solutions offered are "subtract the position of one from the other," which only tells you the direction you want to go in, not how to actually rotate to face that direction.
    Another solution offered usually involves trigonometry, typically based on Math.Atan2(), and makes some assumptions about which direction you want to be "up".

    The problem is not as simple as "just subtract one from the other." Also, the problem does not require trig to be solved.

    Here is a different statement of the same problem:
    "I have an arrow/ship/character that is built to point down the Z axis when in Identity rotation at position P. How do I rotate it so that it points at object O, with up axis U ?"

    The actual math involved, as long as O is not linearly dependent with U, is simple.
    1) Create the vector D = (O-P).
    2) Create the vector U cross D, and normalize. Call this "Right"
    3) Create the vector Right cross U and normalize. Call this "Backwards"
    4) Create the vector Backwards cross Right. Call this "Up"
    4) Your matrix is now these three vectors written in rows (assuming row vectors on the right):

    // O is your object's position
    // P is the position of the object to face
    // U is the nominal "up" vector (typically Vector3.Y)
    // Note: this does not work when O is straight below or straight above P
    Matrix RotateToFace(Vector3 O, Vector3 P, Vector3 U)
    {
    Vector3 D = (O - P);
    Vector3 Right = Vector3.Cross(U, D);
    Vector3.Normalize(ref Right, out Right);
    Vector3 Backwards = Vector3.Cross(Right, U);
    Vector3.Normalize(ref Backwards, out Backwards);
    Vector3 Up = Vector3.Cross(Backwards, Right);
    Matrix rot = new Matrix(Right.X, Right.Y, Right.Z, 0, Up.X, Up.Y, Up.Z, 0, Backwards.X, Backwards.Y, Backwards.Z, 0, 0, 0, 0, 1);
    return rot;
    }

    If your object is modeled pointing down some axis other than positive Z, you can pre-multiply the matrix that turns the model around to face Z, and then multiply this matrix, to get the final orientation matrix. However, if you build your object in 3ds Max such that it is looking at you (you see the front), then the object is already facing positive X when you export it.

    What this does, geometrically, is:
    * Assuming the Z axis will be pointing at the object
    * Using the nominal "up" to find where the "right" (X) axis will point. This means that the above/below positions won't work, because "right" could be anything.
    * Using the calculated Z and X axes, calculate the actual "up" (Y) axis that's aligned with the initial up, but creates an orthogonal coordinate space.
    That in turn gets turned into a matrix, which ends up being the matrix you use to rotate the object.

    Math is Cool!
    Jon Watte, Direct3D MVP kW X-port 3ds Max .X exporter kW Animation source code
  • 03-25-2008 6:12 PM In reply to

    Re: Pointing an object towards a given point, and other cool game math!

    Thanks for this. Helps people like me who didn't get quite as far in math classes as we would've liked. Do you by chance have any good recommendations for books that cover some good math skills (preferrably targetting math used in game programming)? It's something I've been putting off, but as I start to play in 3D I see how helpful that will be. Thanks again!

    Nick Gravelyn -- Microsoft XNA MVP
    Blog | XNA Wiki | FX-izer | EasyZip | Current Adventures | Next-Gen
  • 03-26-2008 7:24 AM In reply to

    Re: Pointing an object towards a given point, and other cool game math!

    Nick Gravelyn:
    Thanks for this. Helps people like me who didn't get quite as far in math classes as we would've liked.

    It's also helpful for those of us that got far enough in math classes but said math classes were over 20 years ago. :(

    Nick Gravelyn:
    Do you by chance have any good recommendations for books that cover some good math skills (preferrably targetting math used in game programming)?

    Here's a couple:

    http://www.amazon.com/Mathematics-Programming-Computer-Graphics-Development/dp/1584500379

    http://www.amazon.com/Primer-Graphics-Development-Wordware-Library/dp/1556229119

    Here's a site for the 2nd book.

    Jim Perry

    Here's what I'm up to.

  • 03-27-2008 2:25 PM In reply to

    Re: Pointing an object towards a given point, and other cool game math!

    It is really a big help!:)  we don't have to delve in too much in math with that.  I hope others can give something like this, too. This will serve as a guide for us when we make such things as letting an object point towards a certain spot or direction.

    Thanks for this.


  • 05-14-2008 11:55 PM In reply to

    Re: Pointing an object towards a given point, and other cool game math!

    Here's another way of looking at this problem.  Suppose you have a 2D shape in the XY plane, whose normal, by default,  faces out of the screen.  Such a normal coincides with the z-axis, has coordinates (0,0,1), and corresponds to the constant Vector3.Backwards.

    You want to generate a rotation matrix to rotate the 2D shape out of the 2D plane around the origin so that its new normal is whatever you pass to the function.  Optionally, you may also want to translate the object to a new location after rotating it.  You can actually achieve this without the up constraint if the rotation your object has around the new normal is arbitrary (e.g. a circular shape or model such as a bullet must face the correct direction, but rotation around the direction vector is arbitrary).

    This implementation will generate an orientation matrix that will make your bullet or whatever face the desired direction centered at the specified translation vector.  This implementation also handles the the special case when the new normal is not linearly independent from the default normal (i.e. it coincides or is opposite to the default normal).

    public static class Transform
      {
        /// <summary>
        /// Calculates an orientation matrix for tilting the XY plane (i.e. the z-axis) towards a given normal vector and translating it to a new location.
        /// By default, the normal of the XY plane (and all 2D polygons in that plane) is Vector3.Backward (the z-axis).
        /// This method generates a rotation/translation matrix that can be used to rotate and translate a polygon or model's vertices
        /// around the origin so that the polygon's new normal or model's direction coincides with the vector passed as normal.
        /// </summary>
        /// <param name="translate">The new location of the shape or model.</param>
        /// <param name="normal">Specifes the desired 3D normal for a 2D shape or desired direction for a model to face once it is transformed by the resulting orientation matrix.</param>
        /// <param name="orientation">Resulting rotation/translation matrix for rotating/translating a 2D shape out of the XY plane or rotating a model around the origin, such that it has a normal whose direction is equivalent to that passed in through the normal parameter.</param>
        public static
    void RotateTowardsAndTranslate( ref Vector3 translate, ref Vector3 normal, out Matrix orientation )
        {
          Vector3 up, right, backward;
          backward = Vector3.Normalize( normal ); //ensure normal is normalized to avoid problems
          right       = Vector3.Cross( backward, Vector3.Backward ); //cross up(normal) with positive Z axis as a default;
          if (right == Vector3.Zero) //normal coincides with or is opposite to the default orientation (shape in XY plane; normal = Vector3.Backward (positive Z-axis)), so there's no rotation. Right direction is chosen arbitrarily as the default right vector.
          {
            if (backward.Z > 0) //check whether we're viewing it from the front (normal.Z > 0; no rotation)
              right = Vector3.Right;
            else
              right = Vector3.Left; //shape is facing the other way, so we'll roll it over a half turn (180 degrees). Since rotating the shape around the normal does not change the normal's direction, and that's our only constraint, the right direction is totally arbitrary.
          }
          up       = Vector3.Cross( backward, right );
          orientation
    = new Matrix( right.X, right.Y, right.Z, 0, up.X, up.Y, up.Z, 0, backward.X, backward.Y, backward.Z, 0, translate.X, translate.Y, translate.Z, 1 );
    //Setting up such a rotation and translation matrix really is this easy, you just set unit vectors for the right, up, and backward, and optionally the translation as well!
    //Use .NET Reflector to check the Right, Up, Backward, and Translation properties of the Matrix class to find the elements to which they correspond. That's how I figured out which ones to set in the line above.
        }
      }

    I find this useful for tilting a 2D shape's surface towards a particular direction.  It could be used for displaying a gamepad's analog stick, for example.
  • 09-03-2008 3:22 PM In reply to

    Re: Pointing an object towards a given point, and other cool game math!

    More XNA related game math (Vector math):

    http://xnawiki.com/index.php?title=Vector_Math

    XNA QuickStart Engine | My site
    "I'll be whatever I want to do!", Philip J. Fry
Page 1 of 1 (6 items) Previous Next