# Rotating a model AND translating it forward in XNA

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.

• 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? – zacharmarz Apr 26 '12 at 14:15
• What's your exactly question? I couldn't spot any. – Gustavo Maciel Apr 26 '12 at 18:11

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);
}

• With that code, the enemy faces away from the player position, and If I apply the code relating to moving the mesh, it disappears. – user8017 Apr 27 '12 at 18:52
• 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... – Blau Apr 27 '12 at 20:12
• For translating the world forward, I'm using translation*= Matrix.CreateTranslation(this.GetWorld().Backward); – user8017 Apr 27 '12 at 20:49
• 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... – Blau Apr 27 '12 at 21:05
• 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 – Blau Apr 28 '12 at 7:48

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.

• I can rotate the enemy to face it's target just fine. – user8017 Apr 25 '12 at 7:17

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;


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.