1
\$\begingroup\$

I have this enemy class, and I want it to

1) Spawn at a certain place Vector3 pos

2) Rotate to face my player position

3) Move forward

As this code is now, it will appear at it's specified place: pos, and attempt to rotate to face it's target: targetShip. It fails to correctly face it's target, because of this offset.

If I remove the code that assigns a value to translation, or if I normalize pos then the model will appear at the origin and rotate to face it's target correctly.

If I try to move it at all using any of the comment out code regarding translation, It appears to start someplace else and I never can find it.

However, if I remove the code relating to rotation, and uncomment the code relating to translation, then I can get it to move forward.

The trick is doing it all together.

    class Enemy : BasicModel
    {


        Matrix rotation = Matrix.Identity;
        Matrix translation = Matrix.Identity;
        public Vector3 pos, up, right, targetShip,dir;

        public Enemy(Model m, Vector3 pos)
            : base(m)
        {
            up = Vector3.Up;
            //sets the position to the Vector3 as it's spawn point.
            translation = Matrix.CreateTranslation(pos);

        }

        public override void Update()
        {
            //Glo is a global class, where I store the player world.
            targetShip = Glo.world.Translation;
            targetShip.Normalize();

          pos = transform.Translation;

          rotation = RotateToFace(targetShip, pos, Vector3.Up);
          //Attempt at moving the model forward. Causes it to go out of view
          //translation *= Matrix.CreateTranslation(this.GetWorld().Backward);
          //translation *= Matrix.CreateTranslation(pos);
        }

        public override Matrix GetWorld()
        {
            return rotation * world * translation ;

        }

        /*Params: O = Our target
         * P = Our position
         * U = up.
         * 
         * Code from some site I googled up.
          */
        Matrix RotateToFace(Vector3 O, Vector3 P, Vector3 U)
        {

            //The direction we're facing.
            Vector3 D = (O - P);
            //Our relative Right.
            Vector3 Right = Vector3.Cross(U, D);
            Vector3.Normalize(ref Right, out Right);
            //Our back
            Vector3 Backwards = Vector3.Cross(Right, U);
            Vector3.Normalize(ref Backwards, out Backwards);
            //Our relative up
            Vector3 Up = Vector3.Cross(Backwards, Right);
            //Make a matrix out of all of these.
            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;
        }



    }
}

----


This is fixed now, and all this code is mostly obsolete.

\$\endgroup\$
2
  • \$\begingroup\$ I think your translation computation looks weird: translation *= Matrix.CreateTranslation(this.GetWorld().Backward); translation *= Matrix.CreateTranslation(pos); If you get this: this.GetWorld().Backward, it calculates with current translation. Than you take result and multiplies translation with it (again). First of all: Shouldn't you reset translation somewhere? Is all that multiplication right? \$\endgroup\$
    – zacharmarz
    Commented Apr 26, 2012 at 14:15
  • \$\begingroup\$ What's your exactly question? I couldn't spot any. \$\endgroup\$ Commented Apr 26, 2012 at 18:11

4 Answers 4

1
\$\begingroup\$
Matrix PlayerAbsoluteTransform;


void UpdatePlayer( Vector3 EnemyPosition, float PlayerVelocity, float Seconds)
{
     Vector3 PlayerPosition = PlayerAbsoluteTransform.Translation;
     Vector3 Forward = EnemyPosition - PlayerPosition;
     Forward.Normalize();

     // This moves your player towars the enemy
     PlayerPosition += Forward * PlayerVelocity * Seconds; 

     // This create the transform matrix for your model, 
     // note that maybe you have to rotate the model before to face right
     PlayerAbsoluteTransform = Matrix.CreateWorld(PlayerPosition, Forward, PlayerUp);
}
\$\endgroup\$
9
  • \$\begingroup\$ With that code, the enemy faces away from the player position, and If I apply the code relating to moving the mesh, it disappears. \$\endgroup\$
    – user8017
    Commented Apr 27, 2012 at 18:52
  • \$\begingroup\$ maybe you are not applying transform right... because I'm sure that if data is right, matrix.CreateWorld returns a right worldmatrix for the object... facing in the forward direction... \$\endgroup\$
    – Blau
    Commented Apr 27, 2012 at 20:12
  • \$\begingroup\$ For translating the world forward, I'm using translation*= Matrix.CreateTranslation(this.GetWorld().Backward); \$\endgroup\$
    – user8017
    Commented Apr 27, 2012 at 20:49
  • \$\begingroup\$ lol... that is bad done... you have to add the translation... and you are multiplying it... you have to think that when you move an object you "add" a translation offset... you should learn some basic algebra before going to make a 3d game... \$\endgroup\$
    – Blau
    Commented Apr 27, 2012 at 21:05
  • \$\begingroup\$ It's moving for sure... but you are scaling the position... not very useful and a strange math for translating... I hope you will realize soon... As you can see in this video... I know how it can be done... youtube.com/watch?v=2WuC60U6z4s&feature=plcp \$\endgroup\$
    – Blau
    Commented Apr 28, 2012 at 7:48
0
\$\begingroup\$

You can try to use other way: if you know direction of enemy and position of ship, you can compute angle between current direction of enemy and new direction (ShipPosition - EnemyPosition): angle = acos(dot(dir,newdir)), dir and newdir should be normalized. Also compute "up vector" of this rotation by cross product: up = cross(dir, newdir).

Then try to make rotation matrix according to this page in section Rotation matrix from axis and angle.

\$\endgroup\$
1
  • \$\begingroup\$ I can rotate the enemy to face it's target just fine. \$\endgroup\$
    – user8017
    Commented Apr 25, 2012 at 7:17
0
\$\begingroup\$

Some remarks which won't fit in a comment; low quality answer here because it's bed time.

That code looks nearly right.

I don't like the manual matrix creation (especially if you got it from an OpenGL website: OpenGL uses a different 'hand' for the co-ordinate system to DirectX): instead use the built-in Matrix.CreateLookAt.

You might try fiddling with the order of multiplication of the matrices: a * b != b * a with matrices.

In addition you are not looking for Backward, instead Matrix.Invert(). However, again, it doesn't work like elementary algebra so a * b * c * Inverse(a) != b * c - so you will need to recalculate the entire chain of matrices again. Camera classes usually have this information baked in, which you should find extremely useful for your entity class. Basically:

// Fiddle with the order; it should give you the general idea though, you 
// can't simply UNDO multiplication in matrices.
var world = Matrix.LookAt(pos, up, ...) * Matrix.Translate(translation, ...) * Matrix.Scale(...);
var wvp = world * view * projection;
\$\endgroup\$
1
0
\$\begingroup\$

The model's position was coming up as invalid because it's position, {0,0,0} was being normalized.

Also, I changed the RotateToFace method to return a Quaternion.

\$\endgroup\$

You must log in to answer this question.