-
|
|
Local Axis Rotation: Unable to rotate about local Y axis, only world Y axis
|
Hello,
So I've got my object in the center of the world, its scale, position, and axes being represented in a matrix:
object.ScaleMatrix = Matrix.CreateScale(.7f);
object.RotationMatrix = Matrix.CreateFromYawPitchRoll(objectRotation.Y, objectRotation.X, objectRotation.Z);
object.TranslationMatrix = Matrix.CreateTranslation(objectPosition);
object.WorldMatrix = Scale * Rotation * Translation;
I have its objectRotation vector being initialized as (45,45,45).
Now in Update I have objectRotation.Y += .03f;
This setup should have the object rotate about its local Y axis, but instead it only rotates around the world Y axis.
I've looked over the code many times, and I still don't know what I did wrong or if this is what is supposed to happen with the matrices I've used.
|
|
-
-
- (1398)
-
premium membership
-
Posts
583
|
Re: Local Axis Rotation: Unable to rotate about local Y axis, only world Y axis
|
Can you post your exact code please.
|
|
-
|
|
Re: Local Axis Rotation: Unable to rotate about local Y axis, only world Y axis
|
Sorry about that.
UPDATE: Sorry but I really screwed up what I was saying there. I used "world axis" wrong. In this code, the object doesn't rotate around the world Y axis of (0,1,0)
I meant that it rotates around the world Y axis like (Objectposition.X, 1, Objectposition.Z). The way I said it was like if the object was 5 units away from the origin it would rotate in circles around it, which definitely isn't what's happening. I wish I could show a video of it. Also, the same things that are happening on the Y axis are happening to the X now too when I change the line ObjectRotation.Y += .03f to ObjectRotation.X += .03f. I just hadn't noticed until I changed the initial Objectrotation.Z to something other than 0. Still, when I change that same line to ObjectRotation.Z += .03f, rotating locally on that axis works fine.
| using System; |
| using System.Collections.Generic; |
| using System.Linq; |
| using Microsoft.Xna.Framework; |
| using Microsoft.Xna.Framework.Audio; |
| using Microsoft.Xna.Framework.Content; |
| using Microsoft.Xna.Framework.GamerServices; |
| using Microsoft.Xna.Framework.Graphics; |
| using Microsoft.Xna.Framework.Input; |
| using Microsoft.Xna.Framework.Media; |
| using Microsoft.Xna.Framework.Net; |
| using Microsoft.Xna.Framework.Storage; |
| using WindowsGame2.Free_Camera; |
| |
| namespace WindowsGame2 |
| { |
| /// <summary> |
| /// This is the main type for your game |
| /// </summary> |
| public class Game1 : Microsoft.Xna.Framework.Game |
| { |
| GraphicsDeviceManager graphics; |
| SpriteBatch spriteBatch; |
| FreeCamera Camera;//FreeCamera is just the class I use to create the fly-around camera to look at the scene. |
| |
| GameObject Object = new GameObject();//GameObject is just a class for holding an object's scale, rotation, |
| //and transformation matrices. |
| Vector3 ObjectRotation = new Vector3(MathHelper.ToRadians(45), MathHelper.ToRadians(45), MathHelper.ToRadians(45)); |
| Vector3 ObjectPosition = Vector3.Zero; |
| |
| public Game1() |
| { |
| graphics = new GraphicsDeviceManager(this); |
| Content.RootDirectory = "Content"; |
| Camera = new FreeCamera(this, new Vector3(0, 0, 50), Vector3.Zero, 2f, 2f); |
| Components.Add(Camera); |
| } |
| |
| /// <summary> |
| /// LoadContent will be called once per game and is the place to load |
| /// all of your content. |
| /// </summary> |
| protected override void LoadContent() |
| { |
| // Create a new SpriteBatch, which can be used to draw textures. |
| spriteBatch = new SpriteBatch(GraphicsDevice); |
| |
| Object.model = Content.Load<Model>("character"); |
| |
| // TODO: use this.Content to load your game content here |
| } |
| |
| /// <summary> |
| /// UnloadContent will be called once per game and is the place to unload |
| /// all content. |
| /// </summary> |
| |
| /// <summary> |
| /// Allows the game to run logic such as updating the world, |
| /// checking for collisions, gathering input, and playing audio. |
| /// </summary> |
| /// <param name="gameTime">Provides a snapshot of timing values.</param> |
| protected override void Update(GameTime gameTime) |
| { |
| // Allows the game to exit |
| if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) |
| this.Exit(); |
| |
| ObjectRotation.Y += 0.03f; |
| //I don't know why, but running this code makes the object rotate around the world axis, not |
| //the local one. |
| //ObjectRotation.X += .03f and ObjectRotation.Z += .03f worked correctly |
| |
| Object.ScaleMatrix = Matrix.CreateScale(.7f); |
| Object.TranslationMatrix = Matrix.CreateTranslation(ObjectPosition); |
| Object.RotationMatrix = Matrix.CreateFromYawPitchRoll(ObjectRotation.Y, ObjectRotation.X, ObjectRotation.Z); |
| Object.WorldMatrix = Object.ScaleMatrix * Object.RotationMatrix * Object.TranslationMatrix; |
| |
| // TODO: Add your update logic here |
| |
| base.Update(gameTime); |
| } |
| |
| /// <summary> |
| /// This is called when the game should draw itself. |
| /// </summary> |
| /// <param name="gameTime">Provides a snapshot of timing values.</param> |
| protected override void Draw(GameTime gameTime) |
| { |
| GraphicsDevice.Clear(Color.CornflowerBlue); |
| |
| foreach (ModelMesh mesh in Object.model.Meshes) |
| { |
| foreach (BasicEffect effect in mesh.Effects) |
| { |
| effect.World = Object.WorldMatrix; |
| effect.EnableDefaultLighting(); |
| effect.PreferPerPixelLighting = true; |
| effect.Projection = Camera.cameraProjectionMatrix; |
| effect.View = Camera.cameraViewMatrix; |
| } |
| mesh.Draw(); |
| } |
| |
| // TODO: Add your drawing code here |
| |
| base.Draw(gameTime); |
| } |
| } |
| } |
| |
|
|
-
-
- (1035)
-
premium membership
-
Posts
690
|
Re: Local Axis Rotation: Unable to rotate about local Y axis, only world Y axis
|
I'm not sure I'm understanding your question/description. CreateFromYawPitchRoll always rotates the object about the world axis.. not the local axis. So I'm not sure what you are asking but here is my two cents worth:
If you want it to rotate around the local axis, I think you would be best off eliminating the matrix 'object.rotationMatrix' & the vector 'objectRotation' since the vector is tied to world space data & you want to work your rotations about local space axis. You can just use the object.worldMatrix to store the orientation (you are already doing that) and use that matrix's basis axis to perform your local rotations since the worldMatrix basis vectors are world space representations of local space vectors;
//setup
object.worldMatrix = Matix.Identity * object.scaleMatrix * Matrix.CreateFromYawPitchRoll(0.707f, 0.707f, 0.707f);// .707 == 45 degrees
//that sets up your object similar to how your code set it up but now you don't need to worry about applying the scale each frame.
//then in update
float yawAmountThisFrame = ??.??; // whatever amount you want it to rotate this frame
object.worldMatrix.Translation = vector3.zero;
object.worldMatrix *= matrix.CreateFromAxisAngle(object.worldMatrix.Up, yawAmountThisFrame)
object.worldMatrix.Translation = objectPosition;
I don't see a need in game1 class or the gameObject class for the vector3 objectRotation or the matrix 'rotationMatrix'. Is there one?
Steve H
|
|
-
|
|
Re: Local Axis Rotation: Unable to rotate about local Y axis, only world Y axis
|
Can't blame you for having a tough time getting the "description", but, still, that's exactly what I was looking for. It goes to show I still have a long way to go with matrices. First of all, I didn't have an idea that CreateFromYawPitchRoll always rotates around the world axis, which is great to know. I also didn't get CreateFromAxisAngle until now, so I've got to learn about that and the rest of the Matrix methods. Anyways, that worked great and I think I can do that correctly with all the axes.
Still, I do have a couple of questions:
When defining object.worldMatrix in the setup, why do you (and most other people I see) place Matrix.Identity at the beginning of the formula?
and
In Update, you change the worldMatrix.Translation to Vector3.Zero and then back to objectPosition. Why is that? (I think I have a theory where it's because you want to multiply the CreateFromAxisAngle only by the parts of the worldMatrix not including the Translation Vector, but I'm not sure. Please explain.)
And I guess I don't need the Rotation Matrix and Vector3s. I don't know why I really was using the Matrix but I guess I was using the Vector to keep the rotation variables together, but now that seems pretty unecessary.
|
|
-
-
- (1035)
-
premium membership
-
Posts
690
|
Re: Local Axis Rotation: Unable to rotate about local Y axis, only world Y axis
|
Matt Richard:place Matrix.Identity at the beginning of the formula?
It is a safe way of making sure the model has a matrix that works. Also, if you initially set it this way your model will render in xna with the same position/orientation as it had in the 3d modeling app you built it with. Once I didn't set it to Identity and just constructed a matrix out of orthonormal vectors and had a problem until I realized that the m44 spot needed a one. So now I usually just safely set it to the identity before manipulating it.
Matt Richard:In Update, you change the worldMatrix.Translation to Vector3.Zero and then back to objectPosition. Why is that?
So your matrix is a representation of your model's position and orientation in world space. If you visualize your matrix as a tripod ( the matrix's rows 1, 2, 3, as the three basis vectors emanating out from the center of your model in orthogonal directions) and that point where they all come together is the 4th row (the matrix's Translation vector) which is its position (location) in the world. That tripod is sitting out there in the 3d world where ever your model is placed. Now fade the model away from the picture in your mind's eye so its not distracting. Anytime you apply a rotation to a matrix, it will rotate around the world's origin. So if your matrix is out there somewhere & you rotate it, it will orbit the world origin like the moon orbits the earth (as it rotates, its position changes too). Often times (like in your case) you just want the matrix to be out there and rotate in place with out changing position (translation). Since all rotations occur about the world origin, you must move the matrix to the world origin (translation = Vector3.Zero), apply the rotation, then move it back. Now the end result effect was that it just rotated a little in place.
Matt Richard:I guess I was using the Vector to keep the rotation variables together, but now that seems pretty unecessary.
It is very intuitive to think of an object's orientation as " my model faces so many degrees about the world X, so many about the world Y, and so many about the world Z". This is a legitimate way to represent an orientation. The vector3 is a convenient storage object to store that data and it's easy to understand. When you want to alter it, you just add or subtract some from the appropriate value. What could be simpler, right? For many folks it's the first way they learn to express an orientation. But more often than not, you need to work in object (local) space to apply rotations to your objects and this method of representing orientations does not easily lend itself to working with object space rotation axis. When you store your orientation/position as a matrix, you have very convenient access to the object space vectors and you still have just a easy access the the world space vetors too. If you download projects that advanced folks create (like jigLibX, the samples on the education page, ect..) nobody sticks with the 3 angle representations (its also called Euler angle representation). Mostly it's just for getting your feet wet in 3d programming and then you graduate into using Matrices and quaternions to represent your orientations. It's probably time for you to move to that level too.
Steve H
|
|
-
|
|
Re: Local Axis Rotation: Unable to rotate about local Y axis, only world Y axis
|
Thanks for answering all of those. Each answer's easy to understand and I think I've got a good grasp on them now.
See ya
|
|
|