4

Am I doing the following right?

Well obviously not cause otherwise I wont be posting a question here, but I'm trying to do a Quaternion rotation of a model around another model.

Lets say I have a box model that has a vector3 position and a float rotation angle. I also have a frustum shaped model that is pointing towards the box model, with its position lets say 50 units from the box model. The frustum also has a vector3 position and a Quaternion rotation.

In scenario 1, the box and frustum are "unrotated". This is all fine and well. In scenario 2, I rotate the box only and I want the frustum to rotate with it (kinda like a chase camera) with the frustum always pointing directly at the box and at the same distance from the box as in the unrotated distance. Obviously if I just rotate the model and the frustum by using Matrix.CreateRotationY() for both the box and the frustum, the frustum is slightly offset to the side.

So I thought a Quaternion rotation of the frustum around the box would be best? To this end I have tried the following, with no luck. It draws my models on the screen, but it also draws what looks like a giant box to the screen and no matter how far away I move the camera the box is always in the way

For the purpose of testing, I have 3 boxes and their 3 associated frustums In my Game1 class I initialize the box[0] with positions and rotations

boxObject[0].Position = new Vector3(10, 10, 10);
boxObject[1].Position = new Vector3(10, 10, 10);
boxObject[2].Position = new Vector3(10, 10, 10);

boxObject[0].Rotation = 0.0f;
boxObject[1].Rotation = 45.0f;
boxObject[2].Rotation = -45.0f;

So all 3 boxes drawn at the same position but at different angles. Then to do the frustums, I initiate their position:

float f = 50.0f;
frustumObject[0].Position = new Vector3(boxObject[0].Position.X,
            boxObject[0].Position.Y, boxObject[0].Position.Z + f);
frustumObject[1].Position = new Vector3(boxObject[1].Position.X,
            boxObject[1].Position.Y, boxObject[1].Position.Z + f);
frustumObject[2].Position = new Vector3(boxObject[2].Position.X,
            boxObject[2].Position.Y, boxObject[2].Position.Z + f);

And then try and rotate around their associated box model:

frustumObject[0].ModelRotation = new Quaternion(boxObject[0].Position.X,
            boxObject[0].Position.Y, boxObject[0].Position.Z + f, 0);
frustumObject[0].ModelRotation = new Quaternion(boxObject[0].Position.X,
            boxObject[0].Position.Y, boxObject[0].Position.Z + f, 45);
frustumObject[0].ModelRotation = new Quaternion(boxObject[0].Position.X,
            boxObject[0].Position.Y, boxObject[0].Position.Z + f, -45);

And finally, to draw the models, I Draw() them in my GameModel class which also has:

public Model CameraModel { get; set; }
public Vector3 Position { get; set; }
public float Rotation { get; set; }
public Quaternion ModelRotation { get; set; }

public void Draw(Matrix view, Matrix projection)
    {
        transforms = new Matrix[CameraModel.Bones.Count];
        CameraModel.CopyAbsoluteBoneTransformsTo(transforms);

        // Draw the model
        foreach (ModelMesh myMesh in CameraModel.Meshes)
        {
            foreach (BasicEffect myEffect in myMesh.Effects)
            {
                // IS THIS CORRECT?????
                myEffect.World = transforms[myMesh.ParentBone.Index] *
                    Matrix.CreateRotationY(Rotation) * Matrix.CreateFromQuaternion(ModelRotation) * Matrix.CreateTranslation(Position);

                myEffect.View = view;
                myEffect.Projection = projection;

                myEffect.EnableDefaultLighting();
                myEffect.SpecularColor = new Vector3(0.25f);
                myEffect.SpecularPower = 16;
            }

            myMesh.Draw();
        }
    }

Can anyone spot where I am going wrong? Is it because I am doing 2 types of rotations n the Draw()?

myEffect.World = transforms[myMesh.ParentBone.Index] * Matrix.CreateRotationY(Rotation) * Matrix.CreateFromQuaternion(ModelRotation) * Matrix.CreateTranslation(Position);

7
  • 1
    Without delving deeply into the code, the first thing that strikes me (which could be stupid) is the order of the matrices; I think the quaternion should be after the translation. This probably won't fix it, but it's worth a try. Commented Apr 25, 2012 at 1:35
  • Thanks, Ill give this a try and let you know how I get on. Commented Apr 25, 2012 at 8:45
  • Nope, sorry that didnt do the trick either. Think I will try 2 different Draw() methods, one for the box and one for the frustum (normal rotation in the box Draw and Quartenion rotation in the frustum Draw) and see how that goes. Commented Apr 25, 2012 at 9:15
  • Where you rotate fusturms (set their quaternions), did you only forget to change the indices here or is this also present in your code. Also please edit you question to include what is happening when you draw these three boxes. Commented Apr 25, 2012 at 11:08
  • What makes you think that you can create a quaternion by plugging in position component values? Commented Apr 25, 2012 at 13:04

1 Answer 1

5
+100

From a quick glance, it would be best to create your Quaternions using a static create method such as Quaternion.CreateFromAxisAngle(Vector3. UnitY, rotation). The values of X,Y,Z and W of a Quaternion do not relate to position in any way. The handy static methods take care of the tricky math.

In your situation it appears as though you want to keep the frustum pointing at the same side of the box as the box rotates, therefore rotating the frustum about the box. This requires a slightly different approach to the translation done in your draw method.

In order to rotate an object about another, you first need to translate the object so that the centre of the desired rotation is at the origin. Then rotate the object and translate it back by the same amount as the first step.

So in you situation, something like this should do it (untested example code to follow);

// Construct the objects

boxObject.Position = new Vector3(10, 10, 10);
boxObject.Rotation = 45.0f;

frustumObject.Position = new Vector3(0, 0, 50f); // Note: this will be relative to the box (makes the math a bit simpler)
frustumObject.TargetPosition = boxObject.Position;
frustumObject.ModelRotation = Quaternion.CreateFromAxisAngle(Vector3. UnitY, boxObject.Rotation); // Note: this rotation angle may need to be in radians.


// Box Draw()
// Draw the box at its position, rotated about its centre.
myEffect.World = transforms[myMesh.ParentBone.Index] * Matrix.CreateTranslation(Position) * Matrix.CreateRotationY(Rotation);

// Frustum Draw()
// Draw the frustum facing the box and rotated about the boxes centre.
myEffect.World = transforms[myMesh.ParentBone.Index] * Matrix.CreateTranslation(Position) * Matrix.CreateFromQuaternion(ModelRotation) * Matrix.CreateTranslation(TargetPosition);

Assumptions:

  • The box rotates about its own centre
  • The frustum stays facing the box and rotates around the boxes centre

Hope this helps.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.