Quaternion Rotation

  • (5 Pages)
  • +
  • « First
  • 3
  • 4
  • 5

66 Replies - 4236 Views - Last Post: 23 August 2012 - 10:22 AM

#61 BBeck  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 208
  • View blog
  • Posts: 562
  • Joined: 24-April 12

Re: Quaternion Rotation

Posted 18 August 2012 - 02:17 PM

View Postrex64, on 18 August 2012 - 01:02 PM, said:

Also, I tried to change the Wood map to add underlines under the numbers, to make it more clear, but somehow everything is mirrored now?


I "think" I see what you are talking about there. I think you'll find it was always that way. You probably just now noticed it.

It was never a big enough deal for me to correct it. As long as back face culling is off both sides of the cube will draw.

Change the draw code like this:
protected override void Draw(GameTime gameTime)
        {
            RasterizerState RS = new RasterizerState();
            //DepthStencilState depthBufferState;
            GraphicsDevice.Clear(Color.Black);
            RS.CullMode = CullMode.None; 
            RS.FillMode = FillMode.Solid;



Then move the box so that you can stand inside it. Once you're inside it, look at the numbers. They'll be correct.

The problem is that the texture needs to be applied backwards to the box. In other words, the UV mapping is backwards. If you flip the UV mapping it will be correct on the outside and wrong on the inside (which is fine because normally you have back face culling on and the box would be solid so that you can't get inside of it).

This post has been edited by BBeck: 18 August 2012 - 02:18 PM

Was This Post Helpful? 0
  • +
  • -

#62 BBeck  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 208
  • View blog
  • Posts: 562
  • Joined: 24-April 12

Re: Quaternion Rotation

Posted 18 August 2012 - 02:29 PM

View Postrex64, on 18 August 2012 - 03:04 PM, said:

I need Base Model Orientation because it allows me to start the model out oriented how I would like it. I guess I could apply it on load, but I don't see why I can't do it my way. That sounds kind of selfish of myself :)


There's no problem starting the model out oriented the way you want. Any rotation done before the draw won't be seen.

You could just setup your Base Model Orientation and then multiply it times the first rotation and then continue to store it that way. So:


Quaternion BaseModelOrientation;
Quaternion ModelOrientation;


BaseModelOrientation = Quaternion.Identity;
BaseModelOrientation *= Quaternion.CreateFromYawPitchRoll(0f, 0f, MathHelper.ToRadians(23f));

ModelOrientation = BaseModelOrientation;


//Rotate about world axes
ModelOrientation = Quaternion.CreateFromYawPitchRoll(MathHelper.ToRadians(11f),0f,0f) * ModelOrientation;




Or you could do it as you propose:
Quaternion BaseModelOrientation;
Quaternion ModelOrientation;


BaseModelOrientation = Quaternion.Identity;
BaseModelOrientation *= Quaternion.CreateFromYawPitchRoll(0f, 0f, MathHelper.ToRadians(23f));


//Rotate about world axes
WorldMatrix = Matrix.CreateFromQuaternion(Quaternion.CreateFromYawPitchRoll(MathHelper.ToRadians(11f),0f,0f) * (BaseModelOrientation * ModelOrientation) );




Eitherway, you would not change BaseModelOrientation after it's set.
(And I haven't tested that. So, I'm not 100% sure that's right. But keep in mind that the order of operations matters a whole bunch.)

This post has been edited by BBeck: 18 August 2012 - 02:37 PM

Was This Post Helpful? 0
  • +
  • -

#63 BBeck  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 208
  • View blog
  • Posts: 562
  • Joined: 24-April 12

Re: Quaternion Rotation

Posted 18 August 2012 - 02:49 PM

I changed LoadContent to have an initial orientation.

 protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
            //ModelTexture = Content.Load<Texture2D>("CubeMap");   //Load the Grid texture into memory from disk.
            DotXModel = Content.Load<Model>("WoodenBlock");    //Load our .X file model for the room into memory.  WoodenBlock  herena
            ModelsOrientation = Quaternion.Identity;
            ModelsOrientation *= Quaternion.CreateFromYawPitchRoll(MathHelper.PiOver4, MathHelper.PiOver4, 0f);
            ModelsPosition = new Vector3(0f, 1f, 0f);

            //rotateBase(new Vector3(MathHelper.ToRadians(90),MathHelper.ToRadians(90),MathHelper.ToRadians(90)));  //these 2 display the same
            //rotateBase(new Vector3(MathHelper.ToRadians(90), MathHelper.ToRadians(0), MathHelper.ToRadians(0)));  //these 2 display the same

            gameFont = Content.Load<SpriteFont>("GameFont");
        }


Was This Post Helpful? 0
  • +
  • -

#64 rex64  Icon User is offline

  • D.I.C Head

Reputation: 4
  • View blog
  • Posts: 152
  • Joined: 31-January 12

Re: Quaternion Rotation

Posted 21 August 2012 - 04:36 PM

I attached the whole project if that helps you. I also inverted the UV texture map (it has a small black line here and there but at least the numbers can be easily read now).

These 2 lines of code still produce the same rotation (and I don't think they should be rotating it the same):
rotateBase(new Vector3(MathHelper.ToRadians(90),MathHelper.ToRadians(90),MathHelper.ToRadians(90)));  //these 2 display the same
//rotateBase(new Vector3(MathHelper.ToRadians(90), MathHelper.ToRadians(0), MathHelper.ToRadians(0)));  //these 2 display the same



LoadContent:
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
            //ModelTexture = Content.Load<Texture2D>("CubeMap");   //Load the Grid texture into memory from disk.
            DotXModel = Content.Load<Model>("WoodenBlock");    //Load our .X file model for the room into memory.  WoodenBlock  herena

            ModelsPosition = new Vector3(0f, 1f, 0f);

            rotateBase(new Vector3(MathHelper.ToRadians(90),MathHelper.ToRadians(90),MathHelper.ToRadians(90)));  //these 2 display the same
            //rotateBase(new Vector3(MathHelper.ToRadians(90), MathHelper.ToRadians(0), MathHelper.ToRadians(0)));  //these 2 display the same

            gameFont = Content.Load<SpriteFont>("GameFont");
        }



Declares:
        Quaternion ModelsOrientation= Quaternion.Identity;
        Quaternion BaseModelsOrientation = Quaternion.Identity;



Draw Code:
                    Shader.World = Matrix.CreateScale(0.25f) * 
                        Matrix.CreateFromQuaternion(Quaternion.CreateFromYawPitchRoll(MathHelper.ToRadians(11f),0f,0f) * (BaseModelsOrientation * ModelsOrientation) ) * 
                        Matrix.CreateTranslation(ModelsPosition);

Attached File(s)


This post has been edited by rex64: 21 August 2012 - 04:37 PM

Was This Post Helpful? 0
  • +
  • -

#65 BBeck  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 208
  • View blog
  • Posts: 562
  • Joined: 24-April 12

Re: Quaternion Rotation

Posted 21 August 2012 - 07:03 PM

LOL I'm not laughing at you. I'm laughing with you. :-)

Of course they produce the same thing. They are the same thing. This is why you use quaternions, to avoid this sort of thing.

You also left out the piece of code that defines the problem. :-)

Fortunately, you included the entire program:
public void rotateBase(Vector3 rotatePitchYawRoll)
{
  BaseModelsOrientation = Quaternion.CreateFromYawPitchRoll(rotatePitchYawRoll.Y, rotatePitchYawRoll.X, rotatePitchYawRoll.Z) * BaseModelsOrientation;
}



Notice that you're feeding "CreateFromYawPitchRoll" PitchYawRoll info there. That's confusing, but not causing a problem.

So think through the problem. Do it with your hand. Your hand is the space ship.

rotateBase(new Vector3(MathHelper.ToRadians(90),MathHelper.ToRadians(90),MathHelper.ToRadians(90)));  //these 2 display the same
//rotateBase(new Vector3(MathHelper.ToRadians(90), MathHelper.ToRadians(0), MathHelper.ToRadians(0)));  //these 2 display the same



So, do it with your hand. The first one is Pitch,Yaw,Roll. Pitch 90 degrees nose up. Yaw 90 degrees clockwise so that the top of your hand is facing left. Roll 90 degrees so that your finger tips are now facing right and your palm is down.

Now start over and do the second one with your hand. Yaw 90 degrees so that your finger tips are now facing right and your palm is down.

See any similarities? ;-)

The problem is that you're defining rotations in Euler Angles. You have to get the orientation inside the quaternion before you can make this problem even start to go away. Because your rotations need to be defined relative to your current orientation and not to the axes to make this go away.

Anyway, the two rotations are the identical orientation even though the path to get there is two different paths. But you're not defining the path here; you're defining the final orientation.

(If it's any consolation, I didn't see it until I worked through it watching my hand.) :-)

This is also happening because you're being very rigid/consistant with 90 degrees. Any other angle would probably not yield the same end result. You wouldn't run into the problem then. The problem would still be there, but you just wouldn't be running into it. The problem is with Euler Angles themselves.

You want to start with a pretty plain Jane starting orientation. Then you probably want to create the rotation quaternion using just pitch, yaw, or roll and not all three before you get them inside the quaternion. Remember that all of your changes are "supposed" to be happening inside the quaternion and not in the angles that are feeding the quaternion.

But the main thing is to visualize it with your hand or something.

Oh. Also, the black lines "may" be due to slopiness on my part putting the texture together. But primarily I think they can be removed by correcting the UV mapping. If you go into file and edit it by small fractions, I think you can probably get those out of there. If you push them off the face, they will be gone because UV mapping is per face (you won't push them on to another face).

This post has been edited by BBeck: 21 August 2012 - 07:55 PM

Was This Post Helpful? 0
  • +
  • -

#66 rex64  Icon User is offline

  • D.I.C Head

Reputation: 4
  • View blog
  • Posts: 152
  • Joined: 31-January 12

Re: Quaternion Rotation

Posted 22 August 2012 - 04:18 PM

I got my rotation in my level to work like this:
Vector3(180, 90, -90)

I guess I can make a rotation tool. But its weird, the Axis do not seem to be rotating how I would expect them to. IN this example the X rotation is working like a Z rotation (like your hand rotating if it were pointing at the screen). Does this seem normal?
Was This Post Helpful? 0
  • +
  • -

#67 BBeck  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 208
  • View blog
  • Posts: 562
  • Joined: 24-April 12

Re: Quaternion Rotation

Posted 23 August 2012 - 10:22 AM

Glad to hear that it's working.

Probably the best thing to do is to make a small test program that allows you to rotate it one degree at a time. Then you would be able to actually see what it's doing as you rotate it into place. The more simple the better. Ideally, it would be nothing but the code necessary to test how it works. You probably wouldn't even need camera code.

Rotatations that have the same end result are pretty common, especially when rotating in 90 degree increments. And Gimbal Lock is all about that. It's about getting rotated into certain positions where two axes have become aligned and therefore give you the same result when you try to rotate on either of the two axes. That's Gimbal Lock in a nutshell (two axes have become aligned and now both of them do the same thing, which prevents you from rotating in certain directions because you no longer have a way to rotate in that direction.

The solution to Gimbal Lock, and probably most of those identical orientation issues is to load a simple orientation into a quaternion, just to have a starting point. It probably shouldn't be anything more compliated than pointing straight down the Z axis. If it's more complex then that then you aren't using quaternions (you're using something else and then making the final result into a quaternion). And from then on, you just define a rotation in the quaternion as simple as possible.


As far as setting an initial orientation in the quaternion. You're setting an orientation, so it doesn't really matter how you get into that orientation, as long as it's the correct orientation. You might experiement with the other create method. Instead of using Yaw, Pitch, Roll, you might try that method for CreateFromAxisAngle (I think it's called). You'll probably have to create 3 quaternions, one for each axis, but it may give you something more like what you expect.

But I would say the main thing is to write a small test app, where you can controll it with fine control (like one degree at a time), and just observe what it's doing.
Was This Post Helpful? 0
  • +
  • -

  • (5 Pages)
  • +
  • « First
  • 3
  • 4
  • 5