2
$\begingroup$

Get the title problem when implementing a walkthrough camera.

I use normlize(cross(WorldUp, Front)) to get Right vector. And when they are collinear, I get a zero vector.

Is there any more robust fake version? Or do I need to store the "previous" Right vector as a backup?

$\endgroup$
5
  • $\begingroup$ Are you doing a first-person-shooter style camera? Most games that implement this kind of camera restrict the x-axis rotation so you can never look straight up or down (clamped at maybe 85 degrees) to avoid exactly this problem. $\endgroup$ – russ Aug 11 '17 at 7:06
  • $\begingroup$ @russ its a CAD camera in my case, so it does need every view angle. $\endgroup$ – ZenWu Aug 11 '17 at 7:09
  • $\begingroup$ hmmm ok, then i guess storing a right vector to handle the edge cases would be one way to do it. either that or use a quaternion for the camera orientation and extract the matrix from that. $\endgroup$ – russ Aug 11 '17 at 7:19
  • $\begingroup$ @russ yeah i think quaternion is a nice solution. If i get how to do euler rotation on quaternion done, i will answer this question myself. THX $\endgroup$ – ZenWu Aug 11 '17 at 7:24
  • $\begingroup$ An alternate to quaternions is to describe the camera's rotation in spherical coordinates: one angle represents rotation around the vertical axis (0 to 360 degrees) and another angle represents how far you are looking down or up (-90 to +90). If going that route you may be interested in this which talks about how to transform between spherical and cartesian coordinates so you can get vectors out: blog.demofox.org/2013/10/12/… $\endgroup$ – Alan Wolfe Aug 11 '17 at 18:15
1
$\begingroup$

You can't have a camera with collinear look/front and up vectors. It doesn't make geometric sense. The whole point of the up vector is to disambiguate roll.

As russ says, for a "first-person" camera it's reasonable to always use world-up for the up vector and simply lock the pitch angle to within (say) 85 degrees of horizontal, to avoid degenerate cases.

For a CAD viewer where the user would expect to pitch the camera arbitrarily, you should rotate both the up and front vectors about the right vector when the user pitches the camera, to ensure they are always perpendicular. Beware that when you do this kind of arbitrary rotation, it's easy for the user to get stuck in unfortunate roll angles. You need to do at least one of the following to let them get themselves out:

  1. Have a "reset up" button that applies the pitch angle limits and resets the up vector to world up.
  2. Give the user arbitrary control over camera roll. (This can be confusing, so it's best to offer the first option as well if you do this.)
  3. Constrain the up vector so that its dot product with the world up is non-negative. That is, if the user pitches so far up or down that they are upside-down, roll the camera 180 degrees.
$\endgroup$
1
$\begingroup$

First of all instead of taking Cross(WorldUp, Front/LookAt) you can use Gram-Schmidt orthogonalization to produce an orthogonal vector that's close to the WorldUp vector. Then you take the cross of this orthogonal vector and the look at to get the side vector. However as you mentioned this'd fail if the vectors are parallel.

Hence the usual solution is to pick another vector that's not parallel to the look at one and again use Gram-Schmidt orthogonalization to produce the orthogonal vector ( camera up) and then take the cross.

The maths is like this.

CameraUp = c
WorldUp = w
LookAt = l

c = w - ( (w.l) / ||l||^2 ) * l 

What it does is this. We know that world up isn't pure orthogonal to the look at vector. So we take the projection of world up onto the direction of the look at vector. Subtract the parallel part of this projection from the world up vector to obtain the remaining i.e. the orthogonal part. This vector is closer to the world up but is purely orthogonal to the look at vector.

$\endgroup$
6
  • $\begingroup$ i can't get why this formula will change the bad situation. If w equals l, then c will still be zero vector? Because when these two vectors are parallel, there will only parallel part, and no orthogonal part. $\endgroup$ – ZenWu Aug 14 '17 at 6:41
  • $\begingroup$ Yes that's why i said, you have to check for this. If that's the case then you'll have to take another arbitrary vector. For example if "j" is the world up and it's parallel with look at, take "i' or "k". What i wanted to point out is, world up and front vector won't always be orthogonal. To make an orthogonal vector close to world up you have to use that formula $\endgroup$ – gallickgunner Aug 14 '17 at 7:23
  • $\begingroup$ if just switch j to i, the the RIGHT vector will probably change a lot. And cross(front, worldUp) is used to compute right vector, the worldUp don't need to be orthogonal to front, just not parallel. $\endgroup$ – ZenWu Aug 14 '17 at 7:29
  • $\begingroup$ i think the world up needs to be orthogonal to the front, else you won't have an orthogonal basis for the camera? $\endgroup$ – gallickgunner Aug 14 '17 at 7:41
  • $\begingroup$ for usual, figure out RIGHT by cross(front, woldUp) first, and then get real up by cross(front, right). That's why it's called world up but not camera up. Your idea make sense maybe, but i think it's not related to the problem i met here. $\endgroup$ – ZenWu Aug 14 '17 at 7:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.