Is there any possibility to limit quaternions to move only in x & y axis (like in Eulers- yaw and pitch, without rolling)? I's there any equation or something similar to do this?
Some example:
Movement should behave like this: http://360.art.pl/experimental/1/
But when I build my player on quaternions it have no limits and I don't know how to fix it http://360.art.pl/experimental/2/
-
\$\begingroup\$ Duplicate? gamedev.stackexchange.com/questions/30644/… \$\endgroup\$– ltjaxCommented Jul 25, 2012 at 10:56
-
\$\begingroup\$ It's simply to make it when key is pressed, but problem is how to do it with mouse controller. \$\endgroup\$– Bartosz WalickiCommented Jul 25, 2012 at 11:00
-
\$\begingroup\$ Question to your question: a quaternion is mighty similar to an angle-axis rotation. How do you get your quaternion? (i.e. from a matrix, from euler angles.. and do you really need to use euler angles as rotation specifiers?? If you do, then how do you convert them into a quat? That's just how you should "restrict it to avoid roll".. \$\endgroup\$– teodronCommented Jul 25, 2012 at 12:11
-
\$\begingroup\$ Wow, I think you've discovered parallel transport :D, it's so cool! en.wikipedia.org/wiki/Parallel_transport Way cooler than gimbal lock :D \$\endgroup\$– teodronCommented Jul 25, 2012 at 12:14
-
\$\begingroup\$ @Bartosz: Its really simple even with a mouse. Just multiply one part to the left and the other to the right, as in the question I linked \$\endgroup\$– ltjaxCommented Jul 25, 2012 at 13:05
2 Answers
Don't use quaternions. Store yaw and pitch Euler angles, and convert to a quaternion if you need to (for supplying to another piece of code, for example). There are no real advantages to using a quaternion like this (this set up cannot get into a gimbal lock, for example).
If you feel the need to use a quaternion, use two: one to represent the pitch and one to represent the yaw. If you ever permanently compose them, you'll have to decompose them at some point to apply the constraints. (Note that two quaternions, one for pitch and one for yaw, is really just obfuscated Euler angles.)
-
\$\begingroup\$ First, an observation: the quat is then perpendicular to the forward/looking direction, but this is not really getting rid of the headaches. Want to know why? The camera also has an up direction, and that one is perpendicular only to two possible oriented rotation axes in the XY plane. Hence he gets that nasty gut feeling of the camera being rotated. It's actually a case of parallel transport on a sphere. One solution is to do something in the likes of your suggestion: use spherical coordinates and avoid reaching the exact poles. \$\endgroup\$– teodronCommented Jul 25, 2012 at 15:31
-
1\$\begingroup\$ @teodron My mistake, the correct set of quaternions is indeed not as simple as letting k = 0. Yet another reason to not store your orientation as a single quaternion. \$\endgroup\$ Commented Jul 26, 2012 at 4:49
UPDATE: As pointed out in one of the other answers, you could use Euler angles. Actually, when analyzing the solution given in the first web application, we can see that this is how they do it. They're computing latitude and longitude (spherical coordinates) and from then on, they move by rotating a gimbal rig.
You can picture this imagining that the z axis of a frame is pointing towards the ceiling and NEVER moves (can only rotate in place, spinning). Now, you weld an y axis to this z one and let that axis support a ring. Z and Y must be perpendicular. Denote a point X on the cross product end of YxZ. That's where your camera can point. Now try to derive the mathematical equations that allow you to cover the whole sphere by first rotating against the Z, then against the Y axis. REMEMBER: the Y axis has rotated as well, so it's not correct to name it (0,1,0) or whatever convention you have for a world axis. It's actually something in the likes of (cos(t), sin(t), 0), where t is the longitude coordinate of a spherical coordinate system. On the other hand, Z does remain fixed and you can call it (0,0,1) (or, again, whatever convention you choose).
Mathematically, to rotate the camera you can first apply a rotation R_z(deltaLongitude) followed by an R_Y(currentLongitude) (endLongitude - currentLongitude).
longitude is an angle in radians, in the [0, pi) interval, whereas latitude is in the (0, pi) interval.
The only advantage of this rotation system is that it's easier for the human brain to accommodate to: it's pretty much how our head pan/tilts. Our entire body, perpendicular on the ground is the Z axis I was talking about, while the Y axis is free to rotate perpendicular to this axis (picture it as the your shoulder line when it is in its rest position :D).
Quats are very similar to an angle-axis representation, nothing more.
So if you apply a quat, you imply that the result is the input rotated against the quat's axis by the specified angle.
What does that tell us?
It tells me this: that the quat's axis must be perpendicular to the camera's lookat axis in order to not rotate the camera against this look at ray.
If the axes are not perpendicular, there will be a roll component taking its toll, and hence the OPs problem.
If required, I could provide further details (a 3D rep maybe?). This link does explain a trackball rotation concept and how to implement it..
-
\$\begingroup\$ I get the quaternion from axis and angle<br>
var angle = Math.acos( _rotateStart.dot( _rotateEnd ) / _rotateStart.length() / _rotateEnd.length() );
<br>var axis = ( new THREE.Vector3() ).cross( _rotateStart, _rotateEnd ).normalize();
<br>quaternion.setFromAxisAngle( axis, -angle );
<br> <br> Quat angle is perpendicular to the camera's lookat and view is still rolling, when I try to set axis perpendicular to lookat alghoritm crashes.<br> Thank's for link, now I better understand trackball concept, but still I don't know how to solve my problem with rolling. Please write more. \$\endgroup\$ Commented Jul 25, 2012 at 12:59 -
\$\begingroup\$ Glad to share some useful info then :)! Good luck in implementing such a system ;) \$\endgroup\$– teodronCommented Jul 30, 2012 at 9:08