quaternion camera - almost working - rotation control glitch

So my quaternion based camera is almost working perfectly.

I’ve just noticed one odd glitch.

If i roll 180 degrees and then yaw say 45 degrees… the movement is off. (i yaw more than i should and move forward less than i should )
If i roll back to up is back to opposite direction everything works great.

I believe this might be a bug in my getForward logic that doesnt account for the up vector.

anyone encounter this before? or have tips?

j.

to narrow the problem you could try to normalizing the quaternions more, even if it doesn’t look necessary.

another issue could be, quaternions and 180 degrees rotation do not work well. a quick fix could be …

  • figure out if a quaternion is 180 deg. (w is probably 0.0)
  • do not apply it to vectors
  • instead negate the vector. x = -x;

Huh?

depends on how you create and apply the quaterion. not a general issue, but possible.

Only if you make a math or implementation error. Quaternions are degenerate nowhere. Choose a convention: say X to right, Y forward and Z up. The choice doesn’t really matter. Some quaternion ‘q’ rotates arbitrary vector ‘v’ by qvq-1. True for all ‘q’ except zero. OK there’s one degenerate case that we don’t care about because we’ll restrict to unit quaternions to simplify computation and increase numeric robustness. So the equation reduces to qvq*

Extracting forward ‘f’ (in this case) becomes f=qYq = q(0,1,0)q.

Let q = (x,y,z)+w:

f = (2(xy-wz), w2-x2+y2-z2, 2(wx+yz))

since |q| = 1

f = (2(xy-wz), 1-2(x2+z2), 2(wx+yz))

So this code snippet extracts forward:


float tx = x+x;
float tz = z+z;
    
v.x =     tx*y - tz*w;
v.y = 1 - tx*x - tz*z;
v.z =     tx*w + tz*y;

For a +/-Pi rotation: ‘w’ is zero and x2+y2+z2 =1:

f = (2xy, 2y2-1, 2yz)

for any axis of rotation independent of “Y” then y = zero:

f = (0, -1, 0)

exactly as expected.

ofc. i’m just pointing out possible issues.

you can run into 180 deg. trouble when you create a quat like this :

// quaterion to rotate u to match v
public vec4 from2vec(vec3 u, vec3 v)
{
  vec3 c = cross(u,v);
  float d = dot(u,v);
  return normalize(vec4(c, 1.0 + d));
}

The issue here isn’t quaternion rotations and getting information from them but using a method which is numerically unsound as the two input vectors approach opposite directions. You have to account for that hedge case if you want that to be a legal thing to do. Oh and you can drop a couple of computations. Given unit vectors ‘u’ & ‘v’ and not approaching +/-Pi between them:


d     = 1.0+dot(u,v);
m     = inversesqrt(d+d);
q.xyz = m*cross(u,v);
q.w   = d*m;