5

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 has no limits and I don't know how to fix it http://360.art.pl/experimental/2/

agamesh
  • 559
  • 1
  • 10
  • 26
Bartosz Walicki
  • 182
  • 2
  • 9
  • I'd love to help but quaternions totally do my head in. You might find some useful stuff regarding this over on Gamedev.se: http://gamedev.stackexchange.com/search?q=quaternion – glenatron Jul 25 '12 at 09:43
  • The link is dead buddy. Could you post another one? – Parth Sep 12 '16 at 11:21

2 Answers2

0

Let me first describe the kind of constraint you're talking about. Given an world_up vector, you want to limit your rotation such that it appears vertical with respect to the camera. If the camera view coordinates are labeled camera_up, camera_right, and camera_forward:

constrain rotation matrix R such that:  dot(R*world_up, camera_right) == 0

This can be done straightforwardly (e.g., in LookAt()-like functions) by constructing a set of perpendicular coordinate vectors as a function of the view direction, view_forward:

given vectors:  view_forward, world_up

Rot_forward = normalize(view_forward)
Rot_right = normalize( cross(view_forward, world_up) )
Rot_up = cross(Rot_right, Rot_forward)

To answer the question: I could be wrong, but I don't think this kind of constraint is straightforward to implement in terms of quaternions. It would be easier to generate the rotation matrix as above, and convert it to a quaternion.

That does raise a question: what problem are you trying to solve by using quaternions here?

  • if you need quaternions to interface with some other system or library, that's fine.
  • if you're trying to fix bad behavior, where the scene rotates quickly when your viewpoint is near the zenith, note that this is a consequence of your constraint: it will happen regardless of how you implement it.
  • if you're trying to use quaternions to get a more natural interpolation, note that your constraint renders this moot: a natural quaternion interpolation will violate the constraint. Given the constraint, it would be more natural to interpolate your view_forward vector, instead of your quaternion.
comingstorm
  • 25,557
  • 3
  • 43
  • 67
0

You can try to construct quaternions directly from yaw/pitch:

q = quat_from_axis_angle(up_vector, yaw) * quat_from_axis_angle(local_right, pitch)

(you may have to multiply these in the reverse order depending on how exactly you turn them into rotation matrices), or realign them every time you change them:

rotated_right = apply_rotation(q, local_right);
projected_right = rotated_right - dot(rotated_right, up_vector) * up_vector;
realign = quat_align_vector(rotated_right, normalized(projected_right));
q = realign * q

projected_right here is a projection of rotated_right onto the horizontal plane. Without rolling, these two vectors must be the same, which implies dot(rotated_right, up_vector) = 0. The last equation is the actual constraint that must be satisfied. It is quadratic in q. E.g. for local_right=(1,0,0), and up_vector=(0,0,1), it becomes dot(q*(1i+0j+0k)*conj(q), 0i+0j+1k)=2*x*z-2*w*y=0, with q=w+xi+yi+zk.

You can find formulas for quat_from_axis_angle and apply_rotation at http://en.wikipedia.org/wiki/Quaternion and http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation. As for quat_align_vector, one way would be

quat_align_vector(src, dst) = sqrt([dot(src, dst), cross(src, dst)])

with [a, b] beign a quaternion with a real part a, and an imaginary part b. Sqrt(x) can be calculated as exp(ln(x)/2) (these functions are on the wiki, too). You could also try replacing sqrt with exp(ln(x)/2*tick*realign_rate) for a smooth restoration of the up-vector :) . Or go the opposite way and simplify the formula a bit:

quat_align_vector(src, dst) = [dot(halfway, dst), cross(halfway, dst)],
halfway = normalized(normalized(src) + normalized(dst))

See also https://stackoverflow.com/a/1171995.

EDIT: corrected vectors, added the constraint.

Community
  • 1
  • 1
vpozdyayev
  • 1,014
  • 5
  • 14