Quaternion Rotation

  • (5 Pages)
  • +
  • 1
  • 2
  • 3
  • Last »

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

#1 rex64  Icon User is offline

  • D.I.C Head

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

Quaternion Rotation

Posted 19 July 2012 - 05:04 PM

I wanted to use a Quaternion for rotation (someone from here suggested I try it). Anyways, things are rotating crazy. What is the W on the Quaternion? Is the X, Y, and Z for the X, Y, and Z rotations?


Here is how I init it:
public Quaternion rotationQuaternion=Quaternion.Identity;



Here is how I adjust it.
rotationQuaternion.X = MathHelper.ToRadians(-90);



Here is how I display it:
                    effect.World = transforms[mesh.ParentBone.Index] *
                         Matrix.CreateScale(scaleRatio, scaleRatio, scaleRatio) *
                         Matrix.CreateFromQuaternion(quaternionRotation)*
                         Matrix.CreateTranslation(modelPosition);


This post has been edited by Atli: 19 July 2012 - 06:06 PM
Reason for edit:: Replaced the [quote] tags with [code] tags.


Is This A Good Question/Topic? 0
  • +

Replies To: Quaternion Rotation

#2 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 20 July 2012 - 09:15 AM

I'm actually planning on building a camera class (maybe this weekend) using quaternions in XNA. They have some advantages over orientation matrices and vectors for keeping track of orientation.

One of the problems you avoid is duplicate headings, or facings. For example, when you're storing orientation as Euler Angles you have the oppurtunity to define 3 rotations that are all the exact same thing with three different number. If you "yaw", or turn around the Y axis, by 360 degrees you have the exact same facing as someone who yaws about the Y axis 720 degrees as well as the same facing as someone who yaws about the Y axis by -720 degrees. If you need to compare their facings you have an infinite number of facings to compare to 360. You can, of course, use some math to force the yaw to only be recorded as values between -180 degrees and +180 degrees no matter how many times it rotates (720 degrees is actually 2 full circles).

And you avoid a problem called Gimbal Lock which is related to that. The whole story behind Gimbal Lock is actually kind of interesting. Before you can understand what Gimbal "Lock" is you have to understand what a gimbal is. The Apollo 11 incident is something that I find kind of fascinating.

http://en.wikipedia....iki/Gimbal_lock

Anyway, quaternions avoid Gimbal Lock because they solve a 3 dimensional problem in 4 dimensional space.

I've also heard that quaternions are better at Spherical Interpolation, when you get ready to do that (I've never worked with SLERP myself).

Anyway, back to the point. Quaternions.

I'm telling you you're making a huge mistake trying to understand them. ;-)

I've been trying to understand them for at least half a decade. I'm getting closer, but I'm still not there yet. But I can share with you what I do know.

Quaternions are vaguely similar to 4 dimensional vectors. They're not 4 dimensional vectors, not in the standard sense of an arrow with a tail and a head. They are "hypercomplex" numbers. I think you're going to start seeing real quick why trying to understand may cause your head to explode here:

To have any hope of understanding hypercomplex numbers you have to understand complex numbers because they are basically the same thing in 2 dimensions with what a quaternion is in 4 dimensions. Complex numbers are usually enough to short circut most people's brains. I totally understand how to use Complex numbers mathematically, and I "think" I "basically" get what they are in the real world.

Complex numbers are real numbers combined with imaginary numbers. And by the way, imaginary numbers are real things! LOL That alone is generally enough to short circuit most peoples' brains.

http://en.wikipedia..../Complex_number

My understanding of Complex numbers is that they are a way of representing 2 dimensions in 1 dimension. All of the real numbers are one dimensional; they are all on a number line in 1D space. You can think of that as an X axis where no Y axis or Z axis exists.

You "could" just add a dimension and have an X,Y or an X,Z axis but instead complex numbers provide a way for positions in 2 dimensional space to "exist" as 1 dimensional equivilants.

The real number part is any part of the number that exists in 1D space, in other words - on the number line. The "imaginary" part of the number (generally written as the number i) represents the part of the number that exists in 2D space away from that number line (so it's not in real number space. It's not on the number line but in the second dimension.) Because complex numbers are 2D they can rotate (you can't really rotate a 1D number. All you can do is flip it back and forth between positive and negative.)

Anyway, that's basically what complex numbers are: a real number combined with an imaginary number to make a "2D" number in 1D space.

If your brain isn't totally fried yet, hypercomplex numbers are 1D numbers in higher dimensional space.


http://en.wikipedia....rcomplex_number

Quaternions are one type of hypercomplex number. I "believe" they are 4D numbers represented in 1D space.

http://en.wikipedia....wiki/Quaternion

So now, not only do you have a "real" part (a normal number) combined with an "imaginary" part ( a multidimensional component represented by the number/variable i) but you also have two more imaginary parts (multidimensional components that are all in completly seperate dimensions represented by the numbers/variables j and k).

I think you can see why quaternions are so confusing to people. I only have a vague concept of what they really are (imaging anything in a 4th dimension is really rough). However, that really doesn't matter for game programmers.

As far as I can tell, game programmers never use any quaternion except one very special quaternion known as the "unit" quaternion. The unit quaternion is a special case of a quaternion where the length, or magnitude, of the quaternion is forced to always be one. This one type of quaternion has some special properties that allow it to store rotation/orientation information.

I "think" I'm starting to actually understand unit quaternions (although not all quaternions) based on "Visualizing the Space of Rotations"
here:

http://en.wikipedia....patial_rotation

Believe it or not, that kind of makes sense to me.

So if I'm understanding that correctly, that means that w,i,j, & k are circles on the sphere produced by a unit quaternion. Three of them represent rotations in quaternion space (which is not 3D space but a conversion from 3D rotations). The fourth component adjusts to keep the other three on the surface of the sphere, because if any one of them changes (or all 3) it will force the quaternion to become a non-unit quaternion. So, at least once component must adjust to maintain the quaternion's magnitude at one or the whole thing comes apart.

Ultimately what that means is that you are basically not going to find anything in normal understanding to equate w,i,j, & k to. You can't just say "W is this and i,j,k are rotation values". They are components of a 4 Dimensional number, not rotations in 3D, not vectors, not angles, and not just about anything you can imagine outside of pretty much the examples given. Most people try and "figure them out" in terms of what they have previously been working with such as angles and vectors, and they simply are not directly related. You can run your Euler Angle orientations through a bit of math and convert them to be stored as quaternions, but they aren't Euler Angles in any shape form or fashion.

So the good news is: you don't need to know pretty much any of the stuff I've said so far. You probably don't know how all the circuitry in your house works, but you use the light switch every day. You probably don't understand how your FM radio "magically" converts sounds from far away places and recreates those same sounds in your car, but you probably listen to the radio. Likewise, you don't need to know what a quaternion is or why a unit quaternion can be used to rotate things. All you really need to know is how to make them do "their thing" the same way that you learn to press the buttons on the radio. For examples of that google "Quaternion Rotation Tutorial" or check out Riemer's coverage of the subject:

http://www.riemers.n..._kinematics.php

This post has been edited by BBeck: 20 July 2012 - 09:40 AM

Was This Post Helpful? 1
  • +
  • -

#3 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 20 July 2012 - 09:30 AM

View Postrex64, on 19 July 2012 - 05:04 PM, said:

I wanted to use a Quaternion for rotation (someone from here suggested I try it). Anyways, things are rotating crazy. What is the W on the Quaternion? Is the X, Y, and Z for the X, Y, and Z rotations?


Yes. They will rotate about crazily if you treat the dimensions of a hypercomplex number as if they are rotations. ;-)

My "understanding" is that w is the number that when combined with i, j, k (probably represented by X,Y,Z) will result in the quaternion having a magnitude of one. If that sounds like it's basically meaningless, it's because it probably is for the purpose of programming in XNA. I think it's best not to ask what they are but how do feed correct values into them. People often make the mistake of trying to make w,i,j, & k into something that they already are familiar with, but I'm afraid that's basically impossible without delving deep into the subject of hypercomplex numbers and what they are in the "real world".

Hope that helps. :-)

I'm actually hoping to write a camera game component this weekend using quaternions. I "think" I'm finally ready for them after strugling to understand them for at least half a decade. (The conclusion I finally came to was you don't need to understand them, you only need to know how to use them to do rotations. So find some code that makes them do their "magic" and use it. XNA seems to have some very nice methods that help you with that such as the ability to just simply "create" a quaternion knowing nothing but the rotation you want to represent.)


Oh. I should of mentioned that quaternions are a WHOLE lot like rotation matrices in that you load them up and combine them with your matrices. Just be aware that a single quaternion can hold a rotation that would require an X,Y, and Z rotation matrix and that quaternion rotations are "relative" which makes them work a bit differently than Euler Angles.

Anyway, maybe I can give you some more specifics about how to write them in XNA code after I dig into them (hopefully this weekend).
Was This Post Helpful? 1
  • +
  • -

#4 rex64  Icon User is offline

  • D.I.C Head

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

Re: Quaternion Rotation

Posted 21 July 2012 - 02:39 PM

I almost got them to work in my camera system. The X axis is rotating backwards though, not sure about the others.

I am using the Quaterian.FromYawPitchRoll (or something like that)


effect.World = transforms[mesh.ParentBone.Index] *
                         Matrix.CreateScale(scaleRatio, scaleRatio, scaleRatio) *
                         Matrix.CreateFromQuaternion(quaternionRotation) *
                         Matrix.CreateTranslation(modelPosition);


Was This Post Helpful? 1
  • +
  • -

#5 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 July 2012 - 04:08 PM

I don't know if this helps: but you store the orientation in a quaternion and then store a rotational change in a quaternion and then multiply them to get a new quaternion with a new rotation. Not sure if you knew that or not.

I've just about got my camera implemented and I didn't find anywhere where I thought a quaternion was right for the job. It could be either my inexperience using quaternions or it could be just the type of camera I'm doing.

I'm doing a camera class family. And the first child was supposed to kind of imitate the view of a person walking.

Maybe I need to go study some camera implementations that others have done with quaternions.

I'm thinking I might just make one child a pure quaternion camera, just to try it.
Was This Post Helpful? 0
  • +
  • -

#6 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 July 2012 - 04:35 PM

Don't know if you saw this, but it looks like a pretty good article on the subject and might help you iron out the issue you're having.


http://azerdark.word...xna-quaternion/
Was This Post Helpful? 0
  • +
  • -

#7 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 22 July 2012 - 04:15 PM

Ok. My understanding of Quaternions and how to use them is still... let's say "evolving". But I'm working on implementing my quaternion camera now.

I'm looking at MSDN, and I see two overloads for declaring Quaternions.

public Quaternion (
Vector3 vectorPart,
float scalarPart
)

This is the first one. Mind you, these are XNA classes and not necessarily "actual" quaternions. In this case it takes a vector and an angle as input. I "believe" the vector is the 3D vector being stored inside the Quaternion and that the angle is the angle to rotate around that vector in radians. Just don't get confused and think that what's inside the quaternion actually looks like those values. You pass them as parameters and that data is converted to quaternion data.

To further illustrate that, you have another Constructor for the same class.

public Quaternion (
float x,
float y,
float z,
float w
)

In this case, I'm not absolutly certain, but I believe the parameters are (i,j,k,w) and not a vector with a rotation. That's a bit confusing because the two are VERY different. I,J,K,& W are the parameters of a quaternion. Where w, as an angle, and x,y,z as a vector is no different thant the other constructor but just broken down into components. If it is a vector and a rotation, then that's just input parameters that will be converted into a quaternion and not actual components of the quaternion. If it's components of the quaternion then anything you try and put in for those values is going to make no sense whatsoever at all unless you know all about hypercomplex numbers.

As usual, Microsoft provides absolutely ZILCH in the way of documentation to explain these constructors and their parameters.

Anyway, those are my thoughts while looking at this. I'll let you know what I find as I play around.

This post has been edited by BBeck: 22 July 2012 - 04:16 PM

Was This Post Helpful? 0
  • +
  • -

#8 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 22 July 2012 - 07:19 PM

Well, I'm still obviously not getting "something". My quaternion camera is working but not exactly like I would expect.

I figured out how to get it to move forward, yaw, and to a limited extent roll. The roll is weird. It looks wrong to me, but if you start doing all the controls simultaneously like flying an airplane it starts looking "right" for some reason. Anyway, it all works with what I've got except the strafe is actually roll and not strafe.

I can't figure out how to strafe or move in a give direction, so far. I mean I could probalby adjust the camera position but that would be axis aligned and not relative to the current facing. I don't know, it's getting late. I'll have to work on it later.

But here's what I've got for the whole camera class/component:
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;


namespace DrawTiles
{
    /// This is a game component that implements IUpdateable.
    public abstract class Camera : Microsoft.Xna.Framework.GameComponent
    {
        protected Matrix View;            //ViewMatrix
        protected Matrix Projection;      //Projection Matrix
        protected Vector3 Handle;         //Used to control the camera's "position".
        protected Vector3 HandleFacing;   //Direction Handle of camera faces.
        protected float Velocity;       //Speed that the camera is moving at.
        protected float Yaw;                //Rotational velocity of the camera.


        public Matrix ViewMatrix
        {
            get { return View; }
        }


        public Matrix ProjectionMatrix
        {
            get {return Projection;}

        }


        //public Vector3 PushHandle
        //{
        //    get { return Handle; }
        //}


        public virtual float VelocityPerFrame
        {
            get { return Velocity; }
            set { Velocity = value; }
        }


        public float YawPerFrame
        {
            get { return Yaw; }
            set { Yaw = value; }
        }


        public Camera(Game game)
            : base(game)
        {
            Handle = new Vector3(0f, 0f, 0f);
            HandleFacing = new Vector3(0f, 0f, 1f);
            Velocity = 0f;
            Yaw = 0f;
        }


        public abstract void StrafeLeft();


        public abstract void StrafeRight();


        public abstract void RollToPort();


        public abstract void RollToStarboard();


        public abstract void LookUp();


        public abstract void LookDown();


        public override void Initialize()
        {
            base.Initialize();
        }


        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);
        }
    }



    public class HumanCamera : Camera
    {
        private float EyeLevel = 1.75f;
        private float Pitch = 0f;   //Used to pitch the view up and down.


        public HumanCamera(Game game) : base(game)
        {
        }


        public override void Initialize()
        {
            Handle = new Vector3(0f, EyeLevel, 0f);
            HandleFacing = new Vector3(0f, 0F, 1f);
            View = Matrix.CreateLookAt(Handle, Handle+HandleFacing, Vector3.Up);
            Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, Game.GraphicsDevice.Viewport.AspectRatio, 0.1f, 2000f);

            base.Initialize();
        }


        public override void StrafeLeft()
        {
            Matrix YRotation = Matrix.Identity;
            Vector3 LeftFacing;


            YRotation = Matrix.CreateRotationY(MathHelper.PiOver2);     //90 Degree rotation
            LeftFacing = Vector3.Transform(HandleFacing, YRotation);
            Handle += LeftFacing * 0.01f;    //0.1 meters per frame.
        }



        public override void StrafeRight()
        {
            Matrix YRotation = Matrix.Identity;
            Vector3 RightFacing;


            YRotation = Matrix.CreateRotationY(-MathHelper.PiOver2);     //90 Degree rotation
            RightFacing = Vector3.Transform(HandleFacing, YRotation);
            Handle += RightFacing * 0.01f;    //0.1 meters per frame.
        }


        public override void RollToPort()
        {

        }


        public override void RollToStarboard()
        {

        }


        public override void LookUp()
        //===================================================================================
        // LookUp()
        //
        // Purpose: Turns the character's head upwards.
        // Parameters:
        // DependsOn: 
        // Returns: void
        //
        // Notes: 
        //===================================================================================
        {
            Pitch += 0.01f;
            if (Pitch > MathHelper.PiOver4)
            {
                Pitch = MathHelper.PiOver4;
            }
        }
        //===================================================================================


        public override void LookDown()
        //===================================================================================
        // LookDown()
        //
        // Purpose: Turns the character's head downwards.
        // Parameters:  
        // DependsOn: 
        // Returns: void
        //
        // Notes: 
        //===================================================================================
        {
            Pitch -= 0.01f;
            if (Pitch < -MathHelper.PiOver4)
            {
                Pitch = -MathHelper.PiOver4;
            }
        }
        //===================================================================================


        public override void Update(GameTime gameTime)
        {
            Matrix YRotation = Matrix.Identity;
            Matrix PitchRotation = Matrix.Identity;
            Vector3 RightFacing;
            Vector3 LookAt;


            YRotation = Matrix.CreateRotationY(Yaw);
            Handle += HandleFacing * Velocity;
            HandleFacing = Vector3.Transform(HandleFacing, YRotation);
            RightFacing = Vector3.Cross(HandleFacing, Vector3.Up);
            PitchRotation = Matrix.CreateFromAxisAngle(RightFacing, Pitch);    //Now we can pitch with the right vector.
            LookAt = HandleFacing;
            LookAt = Vector3.Transform(LookAt, PitchRotation);  //Apply Pitch rotation.
            View = Matrix.CreateLookAt(Handle, Handle + LookAt, Vector3.Up);
                        
            base.Update(gameTime);
        }
    }



    public class QuaternionCamera : Camera
    {
        Quaternion Orientation;


        public QuaternionCamera(Game game) : base(game)
        {
        }


        public new float YawPerFrame
        {
            //get { return Yaw; }
            set { Orientation *= Quaternion.CreateFromYawPitchRoll(value, 0f, 0f); }
        }


        public override void StrafeLeft()
        {
            Handle += Vector3.Transform(HandleFacing, Matrix.CreateFromQuaternion(Orientation * Quaternion.CreateFromYawPitchRoll(MathHelper.ToRadians(90), 0f, 0f))) * 0.05f;
        }


        public override void StrafeRight()
        {
            Handle += Vector3.Transform(HandleFacing, Matrix.CreateFromQuaternion(Orientation * Quaternion.CreateFromYawPitchRoll(-MathHelper.PiOver2, 0f, 0f))) * 0.05f;
        }


        public override void RollToPort()
        {
            Orientation *= Quaternion.CreateFromYawPitchRoll(0f, 0f, (float)(Math.PI / 180f));
        }


        public override void RollToStarboard()
        {
            Orientation *= Quaternion.CreateFromYawPitchRoll(0f, 0f, (float)-(Math.PI / 180f));
        }
        

        public override void LookUp()
        {
            Quaternion PitchUpQuaternion;


            PitchUpQuaternion = Quaternion.CreateFromYawPitchRoll(0f,(float) (Math.PI / 180f), 0f);  //One degree of pitch.
            Orientation *= PitchUpQuaternion;
        }


        public override void LookDown()
        {
            Quaternion PitchDownQuaternion;

            PitchDownQuaternion = Quaternion.CreateFromYawPitchRoll(0f, (float)-(Math.PI / 180f), 0f);  //One degree of pitch.
            Orientation *= PitchDownQuaternion;
        }


        public override void Initialize()
        {
            Orientation = Quaternion.Identity;  //Empty Unit Quaternion.
            Handle = new Vector3(0f, 0.5f, 0f);
            HandleFacing = new Vector3(0f, 0f, -1f);
            View = Matrix.Invert(Matrix.CreateFromQuaternion(Orientation) * Matrix.CreateTranslation(Handle));
            Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, Game.GraphicsDevice.Viewport.AspectRatio, 0.1f, 2000f);

            base.Initialize();
        }


        public override void Update(GameTime gameTime)
        {
            Handle += (Vector3.Transform(HandleFacing, Matrix.CreateFromQuaternion(Orientation)) * Velocity);
            View = Matrix.Invert(Matrix.CreateFromQuaternion(Orientation) * Matrix.CreateTranslation(Handle));

            base.Update(gameTime);
        }
    }
}



This post has been edited by BBeck: 23 July 2012 - 07:14 AM

Was This Post Helpful? 0
  • +
  • -

#9 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 July 2012 - 06:24 AM

Woo hoo! I finally figured out how to do a strafe without resorting to vectors. (Kind of defeats the purpose of using quaternions if you convert them to vectors every time you actually use them. Of course, in the end it has to be turned into a vector to add it to the position vector.) I knew there had to be a way. Now I'm not even sure why it was giving me so much trouble except that the way I've got it coded it will do the action of the left key down and the left key with shift down action which is strafe + spin. I'll have to iron that out.

The code that I posted above did a roll rather than a strafe when you chose StrafeLeft or right. But that means I've got everthing figured out for the six dimensions of movement (forward, right, up, pitch, yaw, roll).

Although, there are still a few pieces of the code that I don't exactly understand. Namely, the part of the code that sets the view matrix. I don't understand why that inversion works or really why that whole line of code works. Maybe I need to dig into the view matrix and find out what it contains or what it's elements are. I think at one time I knew what exactly went into a view matrix (at one time I had to learn the entire process of rasterization mathematically but I've forgotten all that).

Well here's the code changes to make strafe actually strafe:

(Handle is the camera position. As in "the part of the camera you grab to control it". HandleFacing is a "north" (Z axis) facing vector that never changes.)

public override void StrafeLeft()
{
  Handle += 
    Vector3.Transform(HandleFacing, 
      Matrix.CreateFromQuaternion(Orientation * 
      Quaternion.CreateFromYawPitchRoll(MathHelper.ToRadians(90), 0f, 0f))) 
      * 0.05f;
}



(Update: Ok. I've pretty much got the whole thing working. Most of the code that does the work is already posted here but I may do a link to the entire project file if anyone's interested. Of course, this is the prototype for my next tutorial. So eventually, I'll publish the whole thing anyway once it's properly coded, debugged, and commented. Still, if anyone's interested in an "advanced"/alpha copy of the code, I would be happy to provide it. Again, most of the real "guts" of the code is posted above, but it may be a little confusing if you can't see Game1.cs or get an idea of how the whole thing works together.

Anyway, this quaternion camera is actually kind of fun to "fly". :-)

It's pretty similar to flying a plane in MS Flight Simulator with a few major exceptions like the fact that it stops moving the second you let go of the forward button. Still, it's kind of fun and a good start for a flight simulator.

Oh. Almost forgot. You may want to see the edit for the roll method:

public override void RollToPort()
{
  Orientation *= Quaternion.CreateFromYawPitchRoll(0f, 0f, (float)(Math.PI / 180f));
}



Maybe I should go back and edit the post with all the code in it to give my current code now that the Quat camera is basically debugged... Yes. I think I'll do that in case someone wants to use this code.

The code is not properly commented. It's still an "alpha" version of the code or maybe pre-alpha. Please forgive. Use it to your heart's content.)

This post has been edited by BBeck: 23 July 2012 - 06:54 AM

Was This Post Helpful? 0
  • +
  • -

#10 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 July 2012 - 07:22 AM

Thought you also might like to see how the camera attaches to the keyboard. I set YawPerFrame and VelocityPerFrame at the beginning of this Update() code.

if (KBState.IsKeyDown(Keys.W) || KBState.IsKeyDown(Keys.Up)) Camera.VelocityPerFrame = Camera.VelocityPerFrame = 0.016666f;
            if (KBState.IsKeyDown(Keys.S) || KBState.IsKeyDown(Keys.Down)) Camera.VelocityPerFrame = Camera.VelocityPerFrame = -0.016666f;
            if (KBState.IsKeyDown(Keys.A) || KBState.IsKeyDown(Keys.Left) && !(KBState.IsKeyDown(Keys.LeftShift) || KBState.IsKeyDown(Keys.RightShift))) Camera.YawPerFrame = 0.01f;
            if (KBState.IsKeyDown(Keys.D) || KBState.IsKeyDown(Keys.Right) && !(KBState.IsKeyDown(Keys.LeftShift) || KBState.IsKeyDown(Keys.RightShift))) Camera.YawPerFrame = -0.01f;
            if (KBState.IsKeyDown(Keys.Q)) Camera.RollToPort();
            if (KBState.IsKeyDown(Keys.E)) Camera.RollToStarboard();
            if ((KBState.IsKeyDown(Keys.A) || KBState.IsKeyDown(Keys.Left)) && (KBState.IsKeyDown(Keys.LeftShift) || KBState.IsKeyDown(Keys.RightShift)))
            {
                Camera.StrafeLeft();
                //Camera.YawPerFrame = 0f;
            }
            if ((KBState.IsKeyDown(Keys.D) || KBState.IsKeyDown(Keys.Right)) && (KBState.IsKeyDown(Keys.LeftShift) || KBState.IsKeyDown(Keys.RightShift)))
            {
                Camera.StrafeRight();
                //Camera.YawPerFrame = 0f;
            }
            if (KBState.IsKeyDown(Keys.PageUp)) Camera.LookUp();
            if (KBState.IsKeyDown(Keys.PageDown)) Camera.LookDown();


Was This Post Helpful? 0
  • +
  • -

#11 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 24 July 2012 - 07:06 AM

So, I'm still trying to figure out this piece of code:

View = Matrix.Invert(Matrix.CreateFromQuaternion(Orientation) * Matrix.CreateTranslation(Handle)); 



It's setting the view (camera) matrix but I'm not 100% "getting" why an inverse matrix is necessary.

I did find this however:

http://3dgep.com/?p=1700

Quote

Converting between Camera Transformation and View Matrix

If you only have the camera transformation and you want to compute the view matrix that will correctly transform vertices from world-space to view-space, you only need to take the inverse of the camera transform.

If you only have the view matrix and you need to find a camera transform that can be used to position a visual representation of the camera in the scene, you can simply take the inverse of the view matrix.



That suggests that if you just have an orientation matrix for the camera, which is what we have here, then you have to use the inverse matrix to get a view matrix from it.

That makes a certain amount of sense in that the camera was always upside down before I put the inverse in there.

The CreateTranslation(Handle) part is just including the positional information for the camera as Handle is the position vector for the camera.

So, I think I pretty much have the code figured out. I pieced it together from several examples around the internet and then put it into my game component.

Anyway, I still have a bit to learn about how to use quaternions in game programming (and even more to learn about quaternions in general). But this is a good start.

Now I need to learn what all of the other Quaternion methods do. I read that the Conjugate(or Unit Quat Inverse) gives the reverse angle of the Quat's rotation. So, if the rotation is Yaw 30 degrees the Conjugate gives Yaw -30 degrees. Haven't tested it though.

I also read that the dot product gives a very similar result to the dot product of two vectors. I assume that means it projects one's length on the other.

Anyway, there are quite a few methods for the Quaternion in XNA. The next step if figuring them all out, or at least figuring out what they are useful for:

http://msdn.microsof...ternion_methods
Was This Post Helpful? 0
  • +
  • -

#12 rex64  Icon User is offline

  • D.I.C Head

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

Re: Quaternion Rotation

Posted 24 July 2012 - 01:25 PM

The Inverse matrix did not seem to work for me. It inverted the ships so they look inside out. I should be able to rotate the Z to rotate my ship from the top view, but it rotates around the Y.

Here is what I am using instead:
                    effect.World = transforms[mesh.ParentBone.Index] *
                         Matrix.CreateScale(scaleRatio, scaleRatio, scaleRatio) *
                         Matrix.CreateFromQuaternion(quaternionRotation) *
                         Matrix.CreateTranslation(modelPosition);



Here is the code that updates the rotation Quaternion.
        /// <summary>
        /// This function MUST be called every time you update the Vector3 Rotation. This will automatically generate a new Quaternion.
        /// </summary>
        public void updateQuaternionRotation()
        {
            mapInfo.rotationQuaternion = Quaternion.CreateFromYawPitchRoll(mapInfo.Rotation.Y + objectTypeRef.model.rotationVector.Y,
                mapInfo.Rotation.X + objectTypeRef.model.rotationVector.X,
                mapInfo.Rotation.Z + objectTypeRef.model.rotationVector.Z);
        }

        /// <summary>
        /// Will rotate along X, Y, Z by the amount specified in the rotate. Then automatically calls updateQuaternionRotation.
        /// </summary>
        public void rotate(Vector3 rotate)
        {
            mapInfo.Rotation += rotate;
            updateQuaternionRotation();
        }




Game code:
if (Keyboard.GetState().IsKeyDown(Keys.Right))
    ship.rotate(new Vector3(0, -2.4f * timeDifference, 0));


This post has been edited by rex64: 24 July 2012 - 01:34 PM

Was This Post Helpful? 0
  • +
  • -

#13 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 24 July 2012 - 03:33 PM

First thing, (if I understand the purpose of the Inversion matrix) you should never invert the matrix for your model. That's strictly for doing a view (camera) and seems specific to the way the camera's being used. So forget about the inversion unless you find it in a working example of model code. Almost everything else in my quaternion camera code should be roughly the same though.

I think probably the best thing for me to do is to write some example code and it will take me some time before I can do that.

You're just trying to rotate one object according to the keyboard input, right?

Oh. And the keyboard update there is not right if you're using quaternions. That should create a rotation quaternion rather than a vector.

You're using a .X model. Right? I'll see if I can come up with some code to rotate a .X model using quaternions. Maybe I can do that tonight, but no promises. Absolute worst case, I should be able to find some time to do it this weekend.

I've never done it myself. So telling you how to do it off the top of my head is difficult to say exactly how it should be coded.
Was This Post Helpful? 0
  • +
  • -

#14 rex64  Icon User is offline

  • D.I.C Head

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

Re: Quaternion Rotation

Posted 24 July 2012 - 03:43 PM

I am storing a Vector3 and a Quaternion separately. Then whenever I update the Vector3 I update the Quaternion. Then when I display the X model it is based off the Quaternion rotation. Does that make sense, or even solve the lock issue?
Was This Post Helpful? 0
  • +
  • -

#15 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 24 July 2012 - 03:53 PM

View Postrex64, on 24 July 2012 - 03:43 PM, said:

I am storing a Vector3 and a Quaternion separately. Then whenever I update the Vector3 I update the Quaternion. Then when I display the X model it is based off the Quaternion rotation. Does that make sense, or even solve the lock issue?


Maybe. Let me see if I can build a working example of rotating a .X model using Quaternions.
Was This Post Helpful? 0
  • +
  • -

  • (5 Pages)
  • +
  • 1
  • 2
  • 3
  • Last »