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
    Commented Aug 11, 2017 at 7:06
  • $\begingroup$ @russ its a CAD camera in my case, so it does need every view angle. $\endgroup$
    – ZenWu
    Commented Aug 11, 2017 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
    Commented Aug 11, 2017 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
    Commented Aug 11, 2017 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
    Commented Aug 11, 2017 at 18:15

2 Answers 2

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
    Commented Aug 14, 2017 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$ Commented Aug 14, 2017 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
    Commented Aug 14, 2017 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$ Commented Aug 14, 2017 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
    Commented Aug 14, 2017 at 7:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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