Quaternion Rotation

  • (5 Pages)
  • +
  • 1
  • 2
  • 3
  • 4
  • 5

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

#31 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 560
  • View blog
  • Posts: 1,253
  • Joined: 24-April 12

Re: Quaternion Rotation

Posted 28 July 2012 - 01:09 PM

That does seem a little strange. How did you build those quaternions? What is their value?

Have you tried looking at the matrix produced to see if all the quaternions are producing the same rotation matrix? This implies that they are all producing empty rotation matrices.
Was This Post Helpful? 1
  • +
  • -

#32 rex64  Icon User is offline

  • D.I.C Head

Reputation: 6
  • View blog
  • Posts: 168
  • Joined: 31-January 12

Re: Quaternion Rotation

Posted 29 July 2012 - 06:17 PM

I think I found the 'problem' but I am not sure what to do about it. I think because I am stuck in a Gimbal lock the rotations are working fine but they do not translate into real numbers. I think all of my rotation is happening in imaginary space? The reason I think this is because I can rotate around fully with XYZ of 0 0 -1. But as soon as I rotate another axies the numbers will then all function a little bit. Then when I rotate around the numbers change SLIGHTLY. Less than 1/10 of 1 percent during a full rotation. Do you think I am stuck in 2 locks? Is there any way to get the imaginary numbers converted to real numbers? I need these numbers so I can find out what direction the ship is facing so that I can apply thrust.

By the way, it looks like my Z is locked in normal space but free in imaginary space. I tried rotating the X, Y, and Z but I can not get it unlocked.

I wrote a function for your draw tiles that displays the rotations, but it seems to work fine on your demo, you just need to add a spriteFont for this to use:
        private void drawStats()
        {
            spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend);
            Vector3 tempRotation = Vector3.Transform(Vector3.Forward, Matrix.CreateFromQuaternion(ModelsOrientation));
            
            spriteBatch.DrawString(gameFont, "X " + tempRotation.X, new Vector2(200, graphics.GraphicsDevice.Viewport.Height - 18), Color.Orange, 0, Vector2.Zero, .5f, SpriteEffects.None, 0.5f);
            spriteBatch.DrawString(gameFont, "Y " + tempRotation.Y, new Vector2(300, graphics.GraphicsDevice.Viewport.Height - 18), Color.Orange, 0, Vector2.Zero, .5f, SpriteEffects.None, 0.5f);
            spriteBatch.DrawString(gameFont, "Z " + tempRotation.Z, new Vector2(400, graphics.GraphicsDevice.Viewport.Height - 18), Color.Orange, 0, Vector2.Zero, .5f, SpriteEffects.None, 0.5f);
            
            spriteBatch.End();
        }


This post has been edited by rex64: 29 July 2012 - 06:22 PM

Was This Post Helpful? 0
  • +
  • -

#33 rex64  Icon User is offline

  • D.I.C Head

Reputation: 6
  • View blog
  • Posts: 168
  • Joined: 31-January 12

Re: Quaternion Rotation

Posted 29 July 2012 - 06:49 PM

I found some better math to do this:
http://forums.create...4574/23763.aspx

I used the post (9/8/2007 1:54 AM), but according to others there are some mistakes in it, but I tried the other posts and they seemed to have errors going left, so I stuck with that one for now. Let me know if you know any more optimized code to do this, it seems like 1 page of code is a little much for what you almost did in 1 line :)

Is there an optimized math library I should be using? Or what do you recommend?

I also found this, and it seems ok, but it does not work right either:
http://xnawiki.com/i...nion_to_Vector3

This post has been edited by rex64: 29 July 2012 - 06:53 PM

Was This Post Helpful? 0
  • +
  • -

#34 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 560
  • View blog
  • Posts: 1,253
  • Joined: 24-April 12

Re: Quaternion Rotation

Posted 30 July 2012 - 05:36 AM

View Postrex64, on 29 July 2012 - 07:17 PM, said:

I think I found the 'problem' but I am not sure what to do about it. I think because I am stuck in a Gimbal lock the rotations are working fine but they do not translate into real numbers. I think all of my rotation is happening in imaginary space? The reason I think this is because I can rotate around fully with XYZ of 0 0 -1. But as soon as I rotate another axies the numbers will then all function a little bit. Then when I rotate around the numbers change SLIGHTLY. Less than 1/10 of 1 percent during a full rotation. Do you think I am stuck in 2 locks? Is there any way to get the imaginary numbers converted to real numbers? I need these numbers so I can find out what direction the ship is facing so that I can apply thrust.

By the way, it looks like my Z is locked in normal space but free in imaginary space. I tried rotating the X, Y, and Z but I can not get it unlocked.

I wrote a function for your draw tiles that displays the rotations, but it seems to work fine on your demo, you just need to add a spriteFont for this to use:
        private void drawStats()
        {
            spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend);
            Vector3 tempRotation = Vector3.Transform(Vector3.Forward, Matrix.CreateFromQuaternion(ModelsOrientation));
            
            spriteBatch.DrawString(gameFont, "X " + tempRotation.X, new Vector2(200, graphics.GraphicsDevice.Viewport.Height - 18), Color.Orange, 0, Vector2.Zero, .5f, SpriteEffects.None, 0.5f);
            spriteBatch.DrawString(gameFont, "Y " + tempRotation.Y, new Vector2(300, graphics.GraphicsDevice.Viewport.Height - 18), Color.Orange, 0, Vector2.Zero, .5f, SpriteEffects.None, 0.5f);
            spriteBatch.DrawString(gameFont, "Z " + tempRotation.Z, new Vector2(400, graphics.GraphicsDevice.Viewport.Height - 18), Color.Orange, 0, Vector2.Zero, .5f, SpriteEffects.None, 0.5f);
            
            spriteBatch.End();
        }




In the quaternion, everything is happening in imaginary space. The only way you can convert a unit quaternion to a real number is to zero out the imaginary dimensions and set the real component to one. In other words, an empty quaternion is the only quaternion, out of an infinate number of quaternions, that can be a real number and it's real number is always 1 and can never be any other number.

It's basically like trying to turn a 3D point into a real number. You can confine it to the X axis by zeroing out Y and Z, but it might as well not be a 3D point at that point. If you further make this a unit/normalized vector, then it must have a length of one. Therefore, it can only be either 1 or -1 and nothing else because it's a unit vector confined to the X axis in order to make it a real number.

Anyway, it sounds like you are fighting both the quaternions and the vectors.

If you are thinking of vectors as 3D points, that's probably 90% of your problem. They aren't points/coordinates/vertices. They are amounts that are permenantly tied to directions... nothing more... period. It's almost a shame that you can store points/coordinate/vertices in them, because that just confuses people who are trying to learn. (Once you learn it and understand it that actually becomes a nice thing, but until then it's just confusing.)

Read my article on vectors on my website, XNA3D101.com. It's under the Fundamentals section. Until you are thinking of vectors in that way, you'll be misusing them.

It concerns me that you're constantly refering to X,Y, and Z. I'm not sure what you're doing with that. There were some cases where it sounded as if you were making X, Y, and Z angles of rotation (Euler Angles - Pitch, Yaw, Roll). But using the names X, Y, and Z "implies" that they are coordinates. That also concerns me because it suggests that you are not treating vectors as vectors but rather as coordinates, which would be both inefficient and confusing.


If you're having the same types of problems with quaternions that you had without quaternions, then maybe the problem was not Gimbal Lock at all and maybe you don't need quaternions.

I know vectors are usually a pretty big leap in logic for most people. But they are really pretty simple once you really "get" the concept.

First, realize that you really have what you should probably think of as two different types of vectors. You have position vectors that store the position of an object. These are not really vectors, but coordinates stored in a vector. A vector is two points. The second type are actual vectors.

Think of a vector as an arrow with a head and a tail. You have to have a point for the head and another for the tail. In XNA they store them with just one point - the head. And they always "assume" the tail is at 0,0,0. They don't "tell" you that, but that's always the assumption 100% of the time.

You would think these arrows would be absolutely useless if their tails are always stuck to the same spot. But it turns out that it really doesn't matter where their head or tail is. All that matters are where the head and tail are compared to each other. So, where the tail is at doesn't matter.

And that means, you only have to store one of the two points to represent a vector, because you always assume the tail is in the same spot.

This is both good and bad, because it allows you to store actual points/coordinates/vertices in vectors without realizing they are not vectors at all. I mean, technically, they are vectors at that point because they have a head at the point/coordinate/vertex and a tail at 0,0,0. But for points/coordinates/vertices you very rarely care about their "arrow" and that means they are NOT vectors.

Vectors are nothing but an amount (the arrows length) permenantly tied to a direction (the direction the arrow points). What the coordinates of the head are don't matter at all except the head's relationship to the tail.

So, yes, you CAN and do store points as vectors in XNA, but don't let that confuse you with actual vectors.

When working with vectors you will generally have a position (stored unfortunately as a vector) that is just a coordinate representing where the object is at.

To move the object, you usually want to add an actual vector to it.

So, let's say you have a vector that stores a position called ObjectPosition. And then let's say you want to move it by applying a "thrust".

The thrust would be an actual vector. You won't think of the thrust as a position. You think of it as an amount of movement (3 feet or 6 meters for example) and a direction that you want the thrust to cause the movement in. THAT's a vector.

So, you build this thrust as a vector/arrow. Let's call it the Thrust vector. It stores the amount (distance) of the thrust and what direction the thrust points in.

You may be thinking "This sounds too complicated. How am I going to get it to point in the right direction and set it's amount?"

Well, start with a vector you know like Vector3.Forward. That's just a forward pointing unit vector (length one). It has the coordinates (0,0,-1) because it's head points straight down the Z axis.

To set a vector's length, make it a unit vector by normalizing it. Then multiply the vector times the length that you want. So, if you want it to have a length of three then multiply the unit vector by three. (If it's not a unit vector already with a length of 1 you have to normalize it to set it's length to one to make this work.)

To change it's direction, create one or more rotation matrices and apply them (multiply them) to get the vector to face the direction you want.

Once you have this Thrust vector pointing in the right direction and with the correct length, all you have to do is add it to the ObjectPosition vector to make the object move.

This sounds like a lot of work, but it's not once you get going. For example, if we keep this Thrust vector around we can apply it every second and the object will move in that direction by that amount every second from now on. We don't even have to change anything or set anything else up.

And if we want to change directions, we just create a rotation matrix and apply it to the Thrust vector to rotate it.

One of the key things to understand here is that we have no idea what's in the Thrust vector. We simply don't care where the head of this vector is. We don't care what it's X, Y, and Z coordinates are. Even if we knew them it would just make it more confusing. I mean, off the top of your head, can you tell me how many meters the vector 2.4, -3.12, -8.098 is? Seriously. If that's our thrust vector, what do those X, Y, and Z coordinates even mean!?!? Nothing without some serious translation. Can you tell me exactly how many degrees of pitch, yaw, and roll that is? I can't. Not without doing some serious math and having a pencil and paper with me... and probably a calculator... a scientific calculator.

So, the only time we know or care what's in the thrust vector is when we loaded it up with Vector3.Forward. After we change it, we don't care what's in it as long as what's in it is correct. We just add it to the position vector (vector plus vector) and don't worry about it. If we need to change it we either normalize it and multiply it by the length we want, or we apply a rotation matrix to it. But we would never even look at the X, Y, Z values in the vector's head, because they would be basically meaningless.

Quaternions are basically the same: you load them up and don't care what's inside them. (Matrices too.) Really, if you look inside them the information would be meaningless. You have to do quite a bit of math to make the information in a quaternion meaningful. Making the information in a vector meaningful is less math, but still quite bit of math too. But the point is, don't look inside them!

I mean, if you really want to translate the Thrust vector into something meaningful, you would convert it to Yaw, Pitch, and Roll angles along with an amount. The amount is easy to get because it's just Vector3.Length(), but pulling Pitch, Yaw, and Roll out of it is quite a bit more math intensive and probably only useful for the end user. It's probably not very useful information for the computer. The computer doesn't need to know Pitch, Yaw, and Roll to add two vectors together it's just VectorA += VectorB; and you're done. Or, it's as simple as ObjectPostion += Thrust;. You don't care what's in the Thrust vector as long as what's in it is correct. Just add it to the ObjectPosition. You can even modify it without having any idea what's in it. You don't need to know what direction it faces in order to apply a rotation matrix to it. Whatever direction it's facing, the rotational matrix will change it by that amount.

If you are going to use a quaternion as thrust, you have to convert it to a vector because quaternions don't have amounts, they only have a facing/heading. So, you can store the direction of the thrust in a quaternion (such as the rotational facing of a spaceship), but you can't store the amount of the thrust that way. Just store the amount seperately. Then create a normalized/unit vector from the quaternion (with the same facing) and multiply that vector times the amount of thrust you want. Then you have a vector that represents Thrust, just like before.

But you may not even need quaternions, if you're not actually running into a problem of Gimbal Lock. And that only occurs if you allow complete freedom to Pitch, Yaw, and Roll (like with a spaceship, but you wouldn't with a car because the car - hopefully- doesn't tumble end over end).

This post has been edited by BBeck: 30 July 2012 - 07:05 AM

Was This Post Helpful? 0
  • +
  • -

#35 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 560
  • View blog
  • Posts: 1,253
  • Joined: 24-April 12

Re: Quaternion Rotation

Posted 30 July 2012 - 06:10 AM

Take a look at this:

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.



This is code from my "HumanCamera" class which creates a camera similar to walking around looking through the eyes of a person.

This is pretty much exactly what you are talking about in applying a thrust, using vectors (no quaternions).

Handle is a position. It's stored as a Vector3, but it's just 3D coordinates (X,Y,Z). It's stored in a Vector3 for convinence and because that's the way everyone does it. It also makes it easier to use with actual vectors, as you'll see.

HandleFacing is an actual vector that represents the direction the camera is facing. It's a unit vector because I only care about it's direction and not it's amount (it's length/amount is always one). I'll apply whatever amount I want to it when the time comes.

(The handle concept here was supposed to be that it's the handle of the camera that you use to grab the camera and control it.)


So, HandleFacing is like the direction of your thrust.

Now in this particular case I wanted to "strafe" or move perpendicular (90 degrees away from, or left) from whatever direction the camera is currently facing. Notice, I don't know what direction the camera is facing or care what direction it's facing. I just want to move perpendicular to that facing, or left from that facing. The camera could be pointing straight up into the air and this would still be a movement "leftward" of the camera's current facing.

I might add that this camera is "actually" confined to the X,Z plane even though the coordinates are all 3D. So, I may not have fully tested this in situations such as "the camera facing straight up". (Which should never happen with this particular camera design.)

So, I create this YRotation matrix and load it with a 90 degree yaw around the Y axis. What's in the matrix? I don't know. And I don't care. It doesn't matter. Whatever is in their is a 90 degree yaw.

Then I apply that rotation to the HandleFacing (camera direction) vector to produce a new vector LeftFacing. I don't want to permenantly alter my HandleFacing vector, because that would cause the camera to turn. I want the camera to strafe. In otherwords, I want to thrust to the left but I want the camera to continue to face the same direction.

So here's where the actual thrust gets applied:
Handle += LeftFacing * 0.01f; //0.1 meters per frame.

LeftFacing has my newly created temporary vector which faces 90 degrees away from whatever direction the camera is facing. What X,Y,Z coordinate is that? I don't know. I don't care. It would just confuse things and make them more complicated if I did. It doesn't matter. What direction does LeftFacing face? I don't know. I don't care. It's 90 degrees yaw from whatever direction the camera was currently facing.

If you look at the X,Y,Z values in LeftFacing you will probably see something like 0.003234, 0.07244, - 0.8244010. What does that mean? Absolutely nothing to me. It's the position of the vector's head in relation to it's tail. But I don't need to know where the head is at. I just need to add the vector to the camera's current position.

So
Handle += LeftFacing;

says move the camera (Handle) to it's current position plus LeftFacing. LeftFacing has a length of one because it's a unit/normalized vector. So, this would move the camera 1 unit in whatever direction LeftFacing is pointing towards. What direction is that? Don't know. Don't care. It's 90 degrees left of HandleFacing, which is whatever direction the camera is facing.

Moving 1 unit every frame is way to fast, so I set the number of units to move per frame to 0.01 by multiplying the LeftFacing vector (the one I want to change) by 0.01. Since it's a unit/normalized vector, that will set it's length to 0.01 and cause the camera to move that amount per frame.

Handle += LeftFacing * 0.01f;

Notice that none of this code is concerned about the X,Y,Z coordinates in either the position (Handle) or the thrust (LeftFacing). The X,Y,Z coordinates of the position (Handle) would tell you where it's at, but Handle is stored as a Vector3 and LeftFacing is stored as a Vector3. You can add them directly to one another. And in fact, it's probably less efficient to break them into X,Y, and Z components and add the components together.

PiOver2, by the way, is radians for 90 degrees.
Was This Post Helpful? 0
  • +
  • -

#36 rex64  Icon User is offline

  • D.I.C Head

Reputation: 6
  • View blog
  • Posts: 168
  • Joined: 31-January 12

Re: Quaternion Rotation

Posted 30 July 2012 - 08:00 AM

Since I am using Quaternions for rotations everywhere else to avoid Gimbal Lock, I figured I might as well give it a try here as well. Am I close here?

By the way, I use the following:
Ship rotation: Quaternion
Ship position: Vector3
Smoke Offset: Vector3

        /// <summary>
        /// Adds the amount to the vector based on the angle. This basically keeps the ship part/smoke at the same rotation and distance on the ship as the ship rotates.
        /// </summary>
        public static Vector3 AddToVector(Vector3 OrigionalVector, Quaternion heading, Vector3 amountToAdd)
        {
            return Vector3.Transform(OrigionalVector + amountToAdd, heading);
        }


Was This Post Helpful? 0
  • +
  • -

#37 lordofduct  Icon User is offline

  • I'm a cheeseburger
  • member icon


Reputation: 2528
  • View blog
  • Posts: 4,630
  • Joined: 24-September 10

Re: Quaternion Rotation

Posted 30 July 2012 - 09:08 AM

Was that intended to be in this thread?

http://www.dreaminco...based-on-angle/
Was This Post Helpful? 0
  • +
  • -

#38 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 560
  • View blog
  • Posts: 1,253
  • Joined: 24-April 12

Re: Quaternion Rotation

Posted 30 July 2012 - 10:10 AM

View Postrex64, on 30 July 2012 - 09:00 AM, said:

Since I am using Quaternions for rotations everywhere else to avoid Gimbal Lock, I figured I might as well give it a try here as well. Am I close here?

By the way, I use the following:
Ship rotation: Quaternion
Ship position: Vector3
Smoke Offset: Vector3

        /// <summary>
        /// Adds the amount to the vector based on the angle. This basically keeps the ship part/smoke at the same rotation and distance on the ship as the ship rotates.
        /// </summary>
        public static Vector3 AddToVector(Vector3 OrigionalVector, Quaternion heading, Vector3 amountToAdd)
        {
            return Vector3.Transform(OrigionalVector + amountToAdd, heading);
        }





Ok. Back to quaternions.

That's not how I would solve the smoke position problem.

I'm going to make an exception to the rule here; the rule is "always handle quaternion rotations as quaternions". However, in this case you have a perfect 180 degree rotation and that's just too easy to handle as a vector to pass up. And also, this is a position displacement that we're trying to calculate here. If it were an angle other than 180 degrees or changing the ship's heading rather than calculating a position I would handle it all as quaternions. I'll handle the problem as all quaternions, as a second example just to show you how it's done.

Anyway, here's how I would find the SmokePosition using quaternions.

//I assume that ShipsPosition has a value set before this code.
Vector3 ShipsPosition; //Position (not a real vector)
Vector3 SmokePosition; //Will be the position behind the ship
Vector3 SmokesDisplacement; //Where to put the smoke in relation to the ship.
float SmokesDistanceBehindTheShip;  //How far behind the ship you want the smoke  
//I assume ShipsHeadingQuaternion has a value set before this code.
Quaternion ShipsHeadingQuaternion; //Stores the ship's heading
Vector3 ShipsHeadingVector; //Direction the ship faces as a vector
Vector3 ShipsReversedHeadingVector; //Points to the back of the ship.
Matrix QuaternionConversionMatrix; //Used to convert quaternion to vector.


SmokesDistanceBehindTheShip = 0.5f; //Set to any distance you want.

QuaternionConversionMatrix = Matrix.CreateFromQuaternion(ShipsHeadingQuaternion);

ShipsHeadingVector = Vector3.Transform(Vector3.Forward, QuaternionConversionMatrix);

ShipsReversedHeadingVector = ShipsHeadingVector * -1.0f; //Reverses the Ship's Heading 180 degrees by negation.

SmokesDisplacement = ShipsReversedHeadingVector * SmokesDistanceBehindTheShip; 

SmokePosition = ShipsPosition + SmokesDisplacement; 





Of course, that's written for maximum readability. You could shorten it down to this and get the same result:
//I assume that ShipsPosition has a value set before this code.
Vector3 ShipsPosition; //Position (not a real vector)
Vector3 SmokePosition; //Will be the position behind the ship


SmokePosition = ShipsPosition + (((Vector3.Transform(Vector3.Forward, Matrix.CreateFromQuaternion(ShipsHeadingQuaternion))) * -1.0f) * 0.5f); 




Actually, you can combine the 0.5 and -1.0 to be -0.5 and make it even shorter.



Now, if you wanted to do the same thing, but do the rotation as a quaternion, you would do it like this:
//I assume that ShipsPosition has a value set before this code.
Vector3 ShipsPosition; //Position (not a real vector)
Vector3 SmokePosition; //Will be the position behind the ship
Vector3 SmokesDisplacement; //Where to put the smoke in relation to the ship.
float SmokesDistanceBehindTheShip;  //How far behind the ship you want the smoke
//I assume ShipsHeadingQuaternion has a value set before this code.
Quaternion ShipsHeadingQuaternion; //Stores the ship's heading
Quaternion ShipsReversedHeadingQuaternion; //Points to the back of the ship.

Vector3 ShipsReversedHeadingVector; //Points to the back of the ship.
Matrix QuaternionConversionMatrix; //Used to convert quaternion to vector.


SmokesDistanceBehindTheShip = 0.5f; //Set to any distance you want.

//Multiply heading quaternion times a quaternion with the correct rotation
//to get a new quaternion that has been rotated by the specificed amount.
//This combines the two rotation/headings into a result heading.
ShipsReversedHeadingQuaternion = ShipsHeadingQuaternion 
* Quaternion.CreateFromYawPitchRoll(MathHelper.ToRadians(180), 0f, 0f);

QuaternionConversionMatrix = Matrix.CreateFromQuaternion(ShipsReversedHeadingQuaternion);

//Create a vector with the same heading as the quaternion.
ShipsReversedHeadingVector = Vector3.Transform(Vector3.Forward, QuaternionConversionMatrix);

SmokesDisplacement = ShipsReversedHeadingVector * SmokesDistanceBehindTheShip; 

SmokePosition = ShipsPosition + SmokesDisplacement; 



Likewise, this could be shortened:
//I assume that ShipsPosition has a value set before this code.
Vector3 ShipsPosition; //Position (not a real vector)
Vector3 SmokePosition; //Will be the position behind the ship


SmokePosition = ShipsPosition + ((Vector3.Transform(Vector3.Forward, Matrix.CreateFromQuaternion(ShipsHeadingQuaternion 
* Quaternion.CreateFromYawPitchRoll(MathHelper.ToRadians(180), 0f, 0f)))) * 0.5); 


Was This Post Helpful? 0
  • +
  • -

#39 lordofduct  Icon User is offline

  • I'm a cheeseburger
  • member icon


Reputation: 2528
  • View blog
  • Posts: 4,630
  • Joined: 24-September 10

Re: Quaternion Rotation

Posted 30 July 2012 - 10:18 AM

Quote

Ok. Back to quaternions.

That's not how I would solve the smoke position problem.

I'm going to make an exception to the rule here; the rule is "always handle quaternion rotations as quaternions". However, in this case you have a perfect 180 degree rotation and that's just too easy to handle as a vector to pass up.


I'm going to cut you right there.

Now I'm a bit afraid to respond to this because... woah... talk about walls of text. I thought I say a lot.

Anyways, I'm going to disagree merely on the basis of consistency. It is MORE CONSISTENT to stick with some rotation structure than reverting to special case quick maths. Special case quick math is just voodoo math.

if (someArbitraryStateIsMet)
   doQuickMathA
elseif (someOtherArbitraryStateIsMet)
   doQuickMathB
else
   doStandardMath



You either have static code, or you're doing case checks on the existing arithmetic structure that could be solved by just doing the usual math in the first place.

Lets say down the line I want to move the smoke, just a little bit... I have to completely alter my code to meet these demands. Where as if not, I just tweak the property, and be done with it.

Be consistent for consistencies sake.





I can tell you've recently learned about Quaternions, and prior to that you started learning Vectors. And just like most math dorks when they first meet the power of these mathematical constructs, they flip out, and like playing with all the weird stuff you can do with it.

I did the very same thing myself. You should have seen me in Highschool just crooning over the crazy things that you can do, and the crazy things they meant.

But in the end this is about usefulness, and creating tools. And tools should be reusable and consistent. Otherwise you're going to have to memorize why the hell it is you did this a completely different way for some arbitrary reason. WHY? To save 2 minor arithmetic processes? To literally save 0.0000000001 seconds?



No we don't always use quaternions for rotation, and you shouldn't either. Because quaternions are not human readable. They are complex imaginary values that require a strong understanding of math to figure out what a given quaternion's rotation actually is.

One usually inputs and outputs a rotation as euler angles, or axis-angle. It's human readable.

You might also need a matrix for easy rendering and euclidean calculations. Where linear algebra works well in matrices. Or just because the algorithm is simpler to read with a matrix.

The quaternion is good for one major thing. Performing uniform rotations spherically and arbitrarily. They avoid things like gimbal lock because of this. This is what they are used for. That and they are far more compact than the 9 values needed in a matrix to represent rotation, as well as remains unaffected by any planar skewing that might creep in a matrix.

This post has been edited by lordofduct: 30 July 2012 - 10:30 AM

Was This Post Helpful? 0
  • +
  • -

#40 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 560
  • View blog
  • Posts: 1,253
  • Joined: 24-April 12

Re: Quaternion Rotation

Posted 30 July 2012 - 11:24 AM

View Postlordofduct, on 30 July 2012 - 11:18 AM, said:

I'm going to cut you right there.

Now I'm a bit afraid to respond to this because... woah... talk about walls of text. I thought I say a lot.

Anyways, I'm going to disagree merely on the basis of consistency. It is MORE CONSISTENT to stick with some rotation structure than reverting to special case quick maths. Special case quick math is just voodoo math.

if (someArbitraryStateIsMet)
   doQuickMathA
elseif (someOtherArbitraryStateIsMet)
   doQuickMathB
else
   doStandardMath



You either have static code, or you're doing case checks on the existing arithmetic structure that could be solved by just doing the usual math in the first place.

Lets say down the line I want to move the smoke, just a little bit... I have to completely alter my code to meet these demands. Where as if not, I just tweak the property, and be done with it.

Be consistent for consistencies sake.


Yep. Walls of text are what I'm known for. :-)

Well, I was mostly focused on just getting the given problem solved, rather than looking for the specific best code for a given program. However, I can see some value in what you're saying about consistancy and generalization for reuse.

I was also thinking in terms of the smoke needs to always come from the back, rather than something more generalized that could be applied to a lot of situations. But really, once you figure out how it can be done, then you can construct a generalized method of solving the problem.

Still, you're probably right about consistency. By that line of thought, I might just make a function/method that returns a point in relation to an object like:

public Vector3 PositionInRelationToObjectHeading(Vector3 ObjectPosition, Quaternion ObjectsHeading, float DistanceFromObject, float Yaw, float Pitch, float Roll)
{
  return ObjectPosition + ((Vector3.Transform(Vector3.Forward, Matrix.CreateFromQuaternion(ObjectsHeading * Quaternion.CreateFromYawPitchRoll(Yaw, Pitch, Roll)))) * DistanceFromObject);
}



Then you could use that function/method every time you wanted a position relative to the ship or any other object that has a heading as a quaternion and a position as a Vector3.

Really, I'm not entirely sold on the idea that any of the three ways of solving the problem that I have (negating the vector, rotating the quaternion, or generalizing the whole thing to a function) is really superior.

All three are about as straight forward to me as reading 8+3*4=20, especially if the code is well commented to show what each of the numbers represent. The least consistant solution will have the greatest performance due to fewer CPU cycles. Is it worth the extra speed? Well... probably not. It's hard to say. I would say definately not in a first project written in C#. More than likely it would be worthwhile doing the negation option in commercial code that was being called 2,000 times every second. You're probably right that 99% of the time it's not worth the extra speed.

In all 3 cases, it's basically one line of code with a couple of tweaks.

As to human readability, it's about as human readable as a quaternion is going to get. I mean, in the examples I gave I'm using Euler angles.

Quaternion.CreateFromYawPitchRoll(MathHelper.ToRadians(180), 0f, 0f);

That's 180 degrees of Yaw, 0 degrees of Pitch, and 0 degrees of Roll. The other quaternions aren't meant for human consumption and should rarely if ever be looked at internally.

Normally, I would use a WorldMatrix for an object's position and orientation. So, I can see where staying consistant with matrices might be a good thing.

This post has been edited by BBeck: 30 July 2012 - 11:55 AM

Was This Post Helpful? 0
  • +
  • -

#41 lordofduct  Icon User is offline

  • I'm a cheeseburger
  • member icon


Reputation: 2528
  • View blog
  • Posts: 4,630
  • Joined: 24-September 10

Re: Quaternion Rotation

Posted 30 July 2012 - 12:06 PM

Quote

Well, I was mostly focused on just getting the given problem solved, rather than looking for the specific best code for a given program. However, I can see some value in what you're saying about consistancy and generalization for reuse.

...snip


this is called ad hoc, or as needed.

it has it's place, when the place is once. But when the place is with in a system, standards should be followed.
Was This Post Helpful? 0
  • +
  • -

#42 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 560
  • View blog
  • Posts: 1,253
  • Joined: 24-April 12

Re: Quaternion Rotation

Posted 30 July 2012 - 12:09 PM

View Postlordofduct, on 30 July 2012 - 01:06 PM, said:

this is called ad hoc, or as needed.

it has it's place, when the place is once. But when the place is with in a system, standards should be followed.


Agreed.
Was This Post Helpful? 0
  • +
  • -

#43 rex64  Icon User is offline

  • D.I.C Head

Reputation: 6
  • View blog
  • Posts: 168
  • Joined: 31-January 12

Re: Quaternion Rotation

Posted 30 July 2012 - 02:31 PM

My ships look crooked.

Here is the Quaternion I use when drawing, am I combining these correctly?
objects[i].mapInfo.rotationQuaternion * objects[i].objectTypeRef.model.ModelRotationQuaternion


And here is how I set the rotation:
ModelRotationQuaternion = Quaternion.CreateFromYawPitchRoll(vectorRotation.Y, vectorRotation.X, vectorRotation.Z);
Was This Post Helpful? 0
  • +
  • -

#44 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 560
  • View blog
  • Posts: 1,253
  • Joined: 24-April 12

Re: Quaternion Rotation

Posted 30 July 2012 - 02:54 PM

I assume vectorRotation is a Vector3. There is no overload of Quaternion.CreateFromYawPitchRoll that accepts a vector. Yaw, Pitch, and Roll are angles whether measured in radians or degrees. If it's measured in radians then it repeats every 2 * Pi radians. If it's degrees it repeats every 360 degrees.

I mean, theoretically you "could" store the radians as X,Y,Z in a Vector3 but it's just conceptually a mess. There's no valid reason to store Yaw, Pitch, and Roll in a vector even if it is technically possible.

It makes more sense to store them as a structure than as a Vector3.

But anyway you look at it, the input for CreateFromYawPitchRoll is three angles.

http://msdn.microsof...romyawpitchroll

So, that brings us back to "What is vectorRotation? What does it represent?" and more importantly, "What problem are you trying to solve here?"
Was This Post Helpful? 0
  • +
  • -

#45 rex64  Icon User is offline

  • D.I.C Head

Reputation: 6
  • View blog
  • Posts: 168
  • Joined: 31-January 12

Re: Quaternion Rotation

Posted 31 July 2012 - 08:13 AM

Thanks for all your help! I also fixed this based on something you had mentioned, Radians :) I had forgotten them when I stared using a Vector3 adjustment.

View Postrex64, on 30 July 2012 - 02:31 PM, said:

My ships look crooked.

Here is the Quaternion I use when drawing, am I combining these correctly?
objects[i].mapInfo.rotationQuaternion * objects[i].objectTypeRef.model.ModelRotationQuaternion


And here is how I set the rotation:
ModelRotationQuaternion = Quaternion.CreateFromYawPitchRoll(vectorRotation.Y, vectorRotation.X, vectorRotation.Z);

Was This Post Helpful? 0
  • +
  • -

  • (5 Pages)
  • +
  • 1
  • 2
  • 3
  • 4
  • 5