• Advertisement
Sign in to follow this  

Preserving up as much as possible while generating a new orientation

This topic is 3765 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi! What I'm trying to do today [smile], is generate an orientation from a normal vector and a desired "up" vector. I want forward (local z axis) to be a normal I have generated off of some world geometry. So far so good. Now, I want up (local y axis) to be as close to possible to some vector, desiredUp. However, the important vector here is the forward vector, so I need the up vector to be "perfectly" perpendicular to the forward vector, just as close to the desiredUp up as possible. (I generate the local x axis via a cross product of the local z and local y.) I'm using quaternions, and need a quaternion for the final orientation. Though if matrices would work better or are needed, I can freely convert between the two. Ideas? So far I've tried just using desiredUp and the normal directly, and that works great when the 2 are perfectly perpendicular. But when things start sloping, it fails (the ground fails, too, for that matter, since desiredUp and the normal would be the same or exactly the opposite): Notice how [1] is aligned well to the wall (which is perpendicular to "up"), but [2] is sort of "upwards"-ish (I tried to outline the quads themselves, they were a bit vague). Thanks a bunch in advance! Hopefully this doesn't sound too stupid [embarrass]

Share this post


Link to post
Share on other sites
Advertisement
What you want, basically, is to do the same math as is involved in gluLookat. Basically, you're given the forwards vector; you calculate the side vector by a cross product and a normalization; and then you calculate the local up vector by another cross product.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
What you want, basically, is to do the same math as is involved in gluLookat. Basically, you're given the forwards vector; you calculate the side vector by a cross product and a normalization; and then you calculate the local up vector by another cross product.


That was my other approach, but while the generated vectors would work, the y axis would sometimes be completely different from my "desired" y axis. The idea is that my quad should be aligned so that it's "up" is as close as possible to the player's "up" (and not to the side of it, or upside down, for example, since those are all possible given one forward vector). Thanks for the reply, though [smile]!

Share this post


Link to post
Share on other sites
Quote:
Original post by agi_shi
Quote:
Original post by Sneftel
What you want, basically, is to do the same math as is involved in gluLookat. Basically, you're given the forwards vector; you calculate the side vector by a cross product and a normalization; and then you calculate the local up vector by another cross product.


That was my other approach, but while the generated vectors would work, the y axis would sometimes be completely different from my "desired" y axis. The idea is that my quad should be aligned so that it's "up" is as close as possible to the player's "up" (and not to the side of it, or upside down, for example, since those are all possible given one forward vector). Thanks for the reply, though [smile]!

Then you did it wrong. With this formulation, the local up-vector will be as close to the desired up-vector as possible while still being perpendicular to the forwards-vector.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
Quote:
Original post by agi_shi
Quote:
Original post by Sneftel
What you want, basically, is to do the same math as is involved in gluLookat. Basically, you're given the forwards vector; you calculate the side vector by a cross product and a normalization; and then you calculate the local up vector by another cross product.


That was my other approach, but while the generated vectors would work, the y axis would sometimes be completely different from my "desired" y axis. The idea is that my quad should be aligned so that it's "up" is as close as possible to the player's "up" (and not to the side of it, or upside down, for example, since those are all possible given one forward vector). Thanks for the reply, though [smile]!

Then you did it wrong. With this formulation, the local up-vector will be as close to the desired up-vector as possible while still being perpendicular to the forwards-vector.


orly?

xa = za.crossProduct(desiredUp), xa.normalise();
ya = za.crossProduct(xa); ya.normalise();


Mind giving a bit of a better description? Math confuses me, especially when written in a really ugly font like most math sites do it.

Share this post


Link to post
Share on other sites
Quote:
Original post by agi_shi

xa = za.crossProduct(desiredUp), xa.normalise();
ya = za.crossProduct(xa); ya.normalise();


You switched the operands to the cross products. Oh, and there's no real need for the last normalize.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
Quote:
Original post by agi_shi

xa = za.crossProduct(desiredUp), xa.normalise();
ya = za.crossProduct(xa); ya.normalise();


You switched the operands to the cross products. Oh, and there's no real need for the last normalize.


I ... switched the operands to the cross-products? As in I should use xa.crossProduct(za) instead of za.crossProduct(xa)?

Share this post


Link to post
Share on other sites
Yep, and the same with the other one. Remember that vector cross-products aren't commutative.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
Yep, and the same with the other one. Remember that vector cross-products aren't commutative.



xa = desiredUp.crossProduct(za), xa.normalise();
ya = xa.crossProduct(za);


Still no dice [sad]

Share this post


Link to post
Share on other sites
Not sure what you mean by that. What values are you passing in for za and desiredUp, what values are you getting out, and what do you expect to get out? In this situation, numbers are far more reliable than pictures.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
Not sure what you mean by that. What values are you passing in for za and desiredUp, what values are you getting out, and what do you expect to get out? In this situation, numbers are far more reliable than pictures.


Hm. Actually, I seem to be getting zero vectors for the x and y axises. For z I've tried [0, -1, 0], [0, 1, 0], to demonstrate the problem most clearly.

Share this post


Link to post
Share on other sites
There are only two ways the math works out. You either need to do:

right = desiredUp x forward
up = forward x right

or

right = forward x desiredUp
up = right x forward

Note how the forward vectors never "line up" in a column. And if you're getting zero vectors for strange reasons, you should definitely check to make sure the cross product is correct in the first place :)

Share this post


Link to post
Share on other sites
Quote:
Original post by agi_shi
For z I've tried [0, -1, 0], [0, 1, 0], to demonstrate the problem most clearly.

If your up-vector and your forward-vector are collinear, then the problem is underconstrained (has an infinite number of solutions).

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
Quote:
Original post by agi_shi
For z I've tried [0, -1, 0], [0, 1, 0], to demonstrate the problem most clearly.

If your up-vector and your forward-vector are collinear, then the problem is underconstrained (has an infinite number of solutions).


Yeah, I sort of realized that... so how do I fix it?

@ Zipster: Thanks, I get it now :D

Share this post


Link to post
Share on other sites
Quote:
Original post by agi_shi
Yeah, I sort of realized that... so how do I fix it?

You'd hardcode an alternate desiredUp (or two), if you actually expected the situation to ever arise. Of course, in the vast majority of cases this won't be necessary.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
Quote:
Original post by agi_shi
Yeah, I sort of realized that... so how do I fix it?

You'd hardcode an alternate desiredUp (or two), if you actually expected the situation to ever arise. Of course, in the vast majority of cases this won't be necessary.


Ah, I see... I hard-coded the forward vector as the "alternate" desired up vector, and it works wonders!

I would like to really thank you two! [smile]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement