Quaternion and Rotation Primer in wiki!

A place for users of OGRE to discuss ideas and experiences of utilitising OGRE in their games / demos / applications.
User avatar
discipline
OGRE Community Helper
OGRE Community Helper
Posts: 766
Joined: Mon May 16, 2005 12:09 am

Quaternion and Rotation Primer in wiki!

Post by discipline »

Finally, I got my objects to rotate properly in Ogre!! :D To celebrate this success, I decided to write a Quaternion and Rotation Primer in the wiki. It is ready for release to the forums for checking. Then I'll link it up with various pages so it can be found.

Here's what I need:
1) Check my accuracy and understanding, grammar, spelling, etc.
2) Check the clarity of my descriptions.
3) Send me working, concrete code samples that show how to do things with quaternions. For example, I've seen explanations on using slerp in the forums, but no code (haven't looked, nor taken the time to write my own yet). I've also seen discussions on objects walking on the inside and outside of spheres, etc. Provide everything required to run the operation and define each variable.

For the moment, please post corrections, feedback and samples in this thread. I'll compile and organize it all. Then I'll make a public release, link up the wiki page and turn it over.

Quaternion and Rotation Primer
Last edited by discipline on Fri Jun 17, 2005 1:24 am, edited 1 time in total.
User avatar
regress
Halfling
Posts: 78
Joined: Sat Mar 26, 2005 8:39 pm

Post by regress »

Sounds great, I know I could certainly use a deeper understanding (which means, just a tiny bit of it, since right now is pretty much nothing), as well as the math associated with it. A good way to show what math is relevant, and which is not.

Great idea!
regards
User avatar
discipline
OGRE Community Helper
OGRE Community Helper
Posts: 766
Joined: Mon May 16, 2005 12:09 am

Post by discipline »

Thanks! I appreciate any feedback. Maybe I didn't mention I'm looking for that too. :roll:
User avatar
discipline
OGRE Community Helper
OGRE Community Helper
Posts: 766
Joined: Mon May 16, 2005 12:09 am

Post by discipline »

added section on smooth rotation w/ slerp, nlerp and squad. 8)
added section on orientations vs rotations.

I've learned so much writing this article. Now my objects rotate like champs!
joi
Gnome
Posts: 327
Joined: Tue Feb 22, 2005 8:11 pm
Location: brazil

Post by joi »

Thats very cool! Thanks for your time on this!
maya 7.0, vs 2005, ogre 1.2
User avatar
discipline
OGRE Community Helper
OGRE Community Helper
Posts: 766
Joined: Mon May 16, 2005 12:09 am

Post by discipline »

Thanks Joi.

I've linked up the wiki to other pages so it can be found. Consider it released. I've included a link to this thread on the page for article discussion.
User avatar
skullfire
Gremlin
Posts: 150
Joined: Sat Mar 19, 2005 7:51 pm
Location: San Jose, Costa Rica
Contact:

Post by skullfire »

Looks awesome.. already saved on HD, gonna read this tomorrow! Thanks!
Ralen
Kobold
Posts: 33
Joined: Sun Jun 19, 2005 6:25 am

Post by Ralen »

A vector describes a line from a given 0,0,0 to another point in 3-space
Is 0,0,0 the actual coordinate or do you mean x,y,z? As in 0,0,0 can be any combination of x, y or z coordinates?
I want to know what good is a search engine that returns 324,909,188 "matches" to my keyword. That's like saying, "Good news, we've located the product you're looking for. It's on Earth."
User avatar
Chris Jones
Lich
Posts: 1742
Joined: Tue Apr 05, 2005 1:11 pm
Location: Gosport, South England
x 1

Post by Chris Jones »

A vector describes a line from a given 0,0,0 to another point in 3-space
it should be 3d-space shouldnt it?
User avatar
SuprChikn
Bugbear
Posts: 863
Joined: Tue Apr 19, 2005 6:10 am
Location: Melbourne, Aus
Contact:

Post by SuprChikn »

Ralen wrote:
A vector describes a line from a given 0,0,0 to another point in 3-space
Is 0,0,0 the actual coordinate or do you mean x,y,z? As in 0,0,0 can be any combination of x, y or z coordinates?
That is the 3D co-ordinate (0,0,0). ie: The point in 3D space defined as having x, y, and z components all equal to 0 (aka the origin).
A vector is used to define direction and distance between two points.
Hmm, hope that isn't too confusing.

Chris Jones wrote:
A vector describes a line from a given 0,0,0 to another point in 3-space
it should be 3d-space shouldnt it?
Yes.
User avatar
discipline
OGRE Community Helper
OGRE Community Helper
Posts: 766
Joined: Mon May 16, 2005 12:09 am

Post by discipline »

3-space is a lesser used synonym for 3d-space.

A vector is a ray from point A to point B. So really it should look like "A(x1,y1,z1) to B(x2,y2,z2)". However most vectors are assumed to originate from a zero (0,0,0) point. So by convention, we define the vector with only the B coordinate. The reason I say, "a zero point" is because this is relative. The zero point may be the origin of the world, or any other point. The vector only describes the offset from the chosen zero point.

To illustrate using all Vector3s, say a scene node is at (33,55,77) and we attach a camera to it. We can put the camera position at (0,10,-10), relative to the scene node. The camera's position relative to the world is actually (0+33, 55+10, 77-10). These are two different vectors originating at two different points. However they identify the same point in space.
User avatar
SuprChikn
Bugbear
Posts: 863
Joined: Tue Apr 19, 2005 6:10 am
Location: Melbourne, Aus
Contact:

Post by SuprChikn »

discipline wrote:A vector is a ray from point A to point B.
I'm not sure "ray" is technically the right word here.
The way I learnt it (and I could be wrong here, there may be different definitions in use by different people), a "ray" started at a point and went to infinity in one direction, a "line" goes to infinity in two oposite directions, and a "line segment" goes from one point to another.
If this is the case, then really a vector is a line segment (sorry for being so pedantic).
User avatar
discipline
OGRE Community Helper
OGRE Community Helper
Posts: 766
Joined: Mon May 16, 2005 12:09 am

Post by discipline »

I used ray because it signifies direction, which is a crucial part of the vector. A segment does not signify direction.

This is a segment: -------
This is a vector: ------>
Perhaps this is a ray: --------------------------....-------->

Really it is a vector, but I have to draw an analogy from somewhere. :idea: It is a segmented ray! :idea:
User avatar
SuprChikn
Bugbear
Posts: 863
Joined: Tue Apr 19, 2005 6:10 am
Location: Melbourne, Aus
Contact:

Post by SuprChikn »

ah yes, I forgot that line segments don't have a direction as such. They define the connection between two points, but they don't say which way you move (ie: from point A to point B, or B to A).
catalin1976
Kobold
Posts: 26
Joined: Wed Jul 20, 2005 11:05 am
Location: Bucharest
Contact:

Rotation question

Post by catalin1976 »

Hello!

I have one simple question. I know the rotation around axis X, Y and Z. From those rotation I want to create an Quaternion. Please can some one guide me?

PS:
The functions getPitch() = degree around X (dx), getYaw() = degree around Y (dy), getRoll() = degree around Z (dz). (dx) (dy) and (dz) must be equal with the information used to create the quaternion.

Thank you
User avatar
haffax
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 4823
Joined: Fri Jun 18, 2004 1:40 pm
Location: Berlin, Germany
x 7
Contact:

Post by haffax »

Code: Select all

Matrix3 mat;
mat.FromEulerAnglesXYZ(pitch, yaw, roll);
Quaternion q(mat);
Note: This is only disambigious if no angle is greater than 90 degrees. And only in this case you will get the same values with the getters. (I am not 100% sure on this though)
Anyway a quaternion does not and cannot store the euler angles you used to create it.
team-pantheon programmer
creators of Rastullahs Lockenpracht
catalin1976
Kobold
Posts: 26
Joined: Wed Jul 20, 2005 11:05 am
Location: Bucharest
Contact:

Post by catalin1976 »

Sorry for not posing what I was already tested.

Tested code:

Code: Select all

Matrix3 mx;
Quaternion q;

mx.FromEulerAnglesXYZ(Degree(rot.x), Degree(rot.y), Degree(rot.z));
q.FromRotationMatrix(mx);
_viewport[_selectedViewport]->setCameraRotation(q);
input:
pitch = Degree(10)
yaw = Degree(10)
roll = Degree(10)

results:
pitch = 11.6291
yaw = 7.94708
roll = 11.6921

Code: Select all

Quaternion q, qx, qy, qz;

qx.FromAngleAxis(Degree(rot.x), Vector3::UNIT_X);
qy.FromAngleAxis(Degree(rot.y), Vector3::UNIT_Y);
qz.FromAngleAxis(Degree(rot.z), Vector3::UNIT_Z);

q = qx * qy * qz;

_viewport[_selectedViewport]->setCameraRotation(q);
same input - same results.
catalin1976
Kobold
Posts: 26
Joined: Wed Jul 20, 2005 11:05 am
Location: Bucharest
Contact:

Post by catalin1976 »

So, after a lot of searching over the internet and a lot of trying I have arived to this:

Code: Select all

Matrix3 mx;

mx.FromEulerAnglesZYX(Degree(rot.z), Degree(rot.y), Degree(rot.x));

Quaternion q(mx);

_viewport[_selectedViewport]->setCameraRotation(q);
This code is correct only for the following ranges:
pitch -> -179.99 to 179.99
yaw -> -89.96 to 89.97
roll -> -179.99 to 179.99

This is a stat but I need an algorithm for the entire interval of yaw, any idea?
catalin1976
Kobold
Posts: 26
Joined: Wed Jul 20, 2005 11:05 am
Location: Bucharest
Contact:

Post by catalin1976 »

Problem solved I have found a way to simulate the yaw rotation.
tgraupmann
Gnoll
Posts: 696
Joined: Sun Feb 20, 2005 5:28 am
Contact:

Post by tgraupmann »

Spent quite a while experiementing and reading the quat primer.

All I want to do is keep the orientation of an existing quat, while just changing the view axis component to point at a new vector.

Code: Select all

const Ogre::Quaternion cameraOrientation = m_CameraSceneNode->getOrientation();
Ogre::Vector3 lineOfSight = cameraPosition-(shipPosition-shipOrientation.zAxis()*500);
lineOfSight.normalise();
How do I say, hey quat, point at this but keep the same roll?

To be more clear (I want):

Code: Select all

m_CameraSceneNode->getOrientation().zAxis()
to equal:

Code: Select all

lineOfSight
Since the two vectors are usually within 30 degrees, I should be able to find the angle between them and rotate the orientation until it matches the second vector.

I'll keep muling over the primer.


Update:

Figured out the answer finally (note the order is important):

Code: Select all

Ogre::Vector3 lineOfSight = cameraPosition-(shipPosition-shipOrientation.zAxis()*500);
lineOfSight.normalise();
Quaternion quat = m_CameraSceneNode->getOrientation().zAxis().getRotationTo(lineOfSight);
m_CameraSceneNode->rotate(quat, Node::TS_PARENT);
or written another way:

Code: Select all

Ogre::Vector3 lineOfSight = cameraPosition-(shipPosition-shipOrientation.zAxis()*500);
lineOfSight.normalise();
Quaternion quat = shipOrientation.zAxis().getRotationTo(lineOfSight);
m_CameraSceneNode->setOrientation(quat*shipOrientation);
Last edited by tgraupmann on Fri Nov 11, 2005 5:57 pm, edited 1 time in total.
User avatar
discipline
OGRE Community Helper
OGRE Community Helper
Posts: 766
Joined: Mon May 16, 2005 12:09 am

Post by discipline »

You could also use the section titled "Flat XZ Rotation of Objects". Just change XZ to XY.
tgraupmann
Gnoll
Posts: 696
Joined: Sun Feb 20, 2005 5:28 am
Contact:

Post by tgraupmann »

The primer has this example:

Code: Select all

 Vector3 mDestination = mWalkList.front( );                    // mDestination is the next location
 Vector3 mDirection = mDestination - mNode->getPosition();     // B-A = A->B (see vector questions above)
 Vector3 src = mNode->getOrientation() * Vector3::UNIT_X;      // Orientation from initial direction
 src.y = 0;                                                    // Ignore pitch difference angle - has to be axis aligned
 mDirection.y = 0;                                             
 src.normalise();                                              
 Real mDistance = mDirection.normalise( );                     // Both vectors modified so renormalize them
 Quaternion quat = src.getRotationTo(mDirection);
 mNode->rotate(quat);
Unfortunately, it only works if your node is aligned with this axis. Is there a way to ignore the mNode->getOrientation()->yAxis() plane?

Essentially, it would be useful if an axis in a quaternion could be locked.

I suppose I could always temporarily rotate the node to make it axis aligned Do the calculation. And then rotate it back...
tgraupmann
Gnoll
Posts: 696
Joined: Sun Feb 20, 2005 5:28 am
Contact:

Post by tgraupmann »

There's an easy way and a hard way. This is an example of the hard way. But it works.

I decided to use our axis dependent solution on an arbitrary axis. To do this, first I needed to rotate to put us back on the axis. Use the axis dependent solution and then rotate back. Walla.

Code: Select all

					Ogre::Vector3 lineOfSight = m_Body->getPosition() - m_SelectedTarget->GetPosition();

					// We are going to need to rotate this vector to do an axis dependent lookup
					Ogre::Vector3 test1 = lineOfSight.normalisedCopy();
					Ogre::Quaternion sightOrientation = Ogre::Vector3::UNIT_Z.getRotationTo(test1);
					Ogre::Vector3 test2 = sightOrientation.zAxis();

					// We need to orient the body so it is axis aligned
					Ogre::Quaternion origOrientation = m_Body->getOrientation();
					Vector3 test3 = origOrientation.zAxis().normalisedCopy();
					Ogre::Quaternion axisOffsetOrientation = Ogre::Vector3::UNIT_Z.getRotationTo(test3);

					// We need to apply the orientation to our sight orientation
					Ogre::Quaternion oldOrientation = axisOffsetOrientation*origOrientation;
					sightOrientation = axisOffsetOrientation*sightOrientation;

					// Do the axis dependent lookup
					Vector3 src = oldOrientation.zAxis();
					src.y = 0; // ignore the y component - has to be axis aligned
					src.normalise();
					Vector3 dst = sightOrientation.zAxis();
					dst.y = 0; // ignore the y component - has to be axis aligned
					dst.normalise();
					Ogre::Quaternion quat = src.getRotationTo(dst);

					// rotate everything back
					oldOrientation = axisOffsetOrientation.Inverse() * oldOrientation;
					Vector3 test4 = oldOrientation.zAxis().normalisedCopy();
					sightOrientation = axisOffsetOrientation.Inverse() * sightOrientation;
					Vector3 test5 = sightOrientation.zAxis().normalisedCopy();

					// Apply the calculated orientation
					oldOrientation = Quaternion::Slerp(Real(_deltaTime*4), oldOrientation, quat*oldOrientation);

					// assign the new orientation
					m_Body->setOrientation(oldOrientation);
nim
Gnoblar
Posts: 22
Joined: Wed Sep 13, 2006 6:22 am
Location: Sweden
Contact:

Post by nim »

I haven't read linear algebra or I've forgotten if it's in another course so please clarify abbreviations like the "Th" in "Cos Th". If not an explaination, atleast the full word would be good so I can look it up :-)

anyway, great article! I was looking for exactly what it covers for half a day before I found it!
Gamok
Kobold
Posts: 32
Joined: Tue Oct 10, 2006 7:16 pm

Post by Gamok »

i think its "Theta", used later in the article.
Post Reply