Sign in to follow this  
Matt Aufderheide

make object face camera (not so simple)

Recommended Posts

there is of course a basic method of making an object face a point:
generate a lookat matrix...to do this i use D3DXMatrixLookat
for most purposes this works fine and no more effort is needed.

However, consider this:
1) an object is at 0,0,0
2) it is set to always face camera
3) camera moves up to the "poles" of the object, that is near directly above(or below) it (approaching 0,x,0)

you will notice the object starts to spin around on it's axis as the camera moves farther toward exactly above it. For most objects this is not a big deal, but for my purposes it is a bad thing.

I have what is basically a flat grid of polygons that is positioned at 0,0,0 that should always face the camera but maintaining the same kind of alignment...it shouldn't "spin". Also, i need to be able to rotate in "increments" of degrees or radians.

does anyone have a solution?

Share this post


Link to post
Share on other sites
One possible solution would be to apply incremental rotations to keep the object aligned towards the target point. For any one update, the axis to rotate about would be the (normalized) cross product of the object's current forward vector and the vector from the object's position to the target position; the angle can be computed from these two vectors as well. Once you have an axis-angle pair, you can then apply a relative rotation to re-align the object. (There are a few details that have to be taken into consideration, but that's the general idea. Also, there's a couple of particularly nice quaternion-based algorithms that can be used for this as well.)

Share this post


Link to post
Share on other sites
Can you post a screenshot? It sounds like you are constructing a lookat matrix from the camera location to each individual polygon center, which will cause them to "spin around" as you pass over them looking down. Try building a lookat matrix that looks from the camera origin to camera_origin + camera_normal, and use that for every polygon (you will only need to calculate it once, as the camera normal won't change between polygons). That sounds more like it is what you are looking for.

Share this post


Link to post
Share on other sites
Quote:
Original post by kuroioranda
Can you post a screenshot? It sounds like you are constructing a lookat matrix from the camera location to each individual polygon center, which will cause them to "spin around" as you pass over them looking down. Try building a lookat matrix that looks from the camera origin to camera_origin + camera_normal, and use that for every polygon (you will only need to calculate it once, as the camera normal won't change between polygons). That sounds more like it is what you are looking for.
Are you referring to viewplane-aligned billboarding? If so, that would probably be a good solution as well (maybe better than the incremental rotations I suggested earlier, depending on the context).
Quote:
Original post by Danny02
use Quaternions, the problem u face is called Gimbal lock and is caused by the use of Euler angles.
It's not gimbal lock :| And neither Euler angles nor quaternions have anything to do with it :/

For some reason, there's a tendency (on this forum and others) to a) attribute every artifact or undesirable behavior related to rotation to gimbal lock and b) cite quaternions as the optimal (or only) solution. I don't know where this comes from exactly, but none of that is relevant here. A 'look at' transform is constructed using simple vector math, not Euler angles, and the behavior the OP is describing is simply an artifact of the way the transform is constructed - it's not due to gimbal lock.

Share this post


Link to post
Share on other sites
Quote:
Original post by jyk
Quote:
Original post by kuroioranda
Can you post a screenshot? It sounds like you are constructing a lookat matrix from the camera location to each individual polygon center, which will cause them to "spin around" as you pass over them looking down. Try building a lookat matrix that looks from the camera origin to camera_origin + camera_normal, and use that for every polygon (you will only need to calculate it once, as the camera normal won't change between polygons). That sounds more like it is what you are looking for.
Are you referring to viewplane-aligned billboarding? If so, that would probably be a good solution as well (maybe better than the incremental rotations I suggested earlier, depending on the context).


Yes. Especially when you are moving around I find that viewpoint aligned billboards shift in ways that tend to make me nauseous. So it seemed like a win-win to suggest doing it the viewplane-aligned way.

Share this post


Link to post
Share on other sites
I guess i wasn't clear enough. I think this problem is indeed gimbal lock. In any case, its nothing to do with view aligned quads...Im trying to rotate a single object to face the camera in world space.

The same thing happens when i use Euler angles to rotate the object.

Share this post


Link to post
Share on other sites
The problem is you up vector aligned with your view vector. There are several ways to solve this, one is by modifying your up vector a bit so it does not align with your camera (small amount will solve the problem), this is usually the way space movement is done (modifyng up vectors while rotating space ships).

Hopefully this helps.
Cheers

Share this post


Link to post
Share on other sites
Quote:
Original post by Matt Aufderheide
I think this problem is indeed gimbal lock.
If the problem is as described in your original post, then it's almost certainly not gimbal lock.

May I ask why you think it's gimbal lock? What do you think gimbal lock is exactly?

Share this post


Link to post
Share on other sites
Ok as i understand it gimbal lock is loss of a degree of freedom when using Euler angles to rotate.

It seems to me that roll has no effect when the camera is near the poles of the object to be rotated. Maybe this isnt the case...im a bit confused now.

Basically though i think i need to use a dynamic axis for rotation...

Share this post


Link to post
Share on other sites
Quote:
Original post by Matt Aufderheide
Ok as i understand it gimbal lock is loss of a degree of freedom when using Euler angles to rotate.


Correct, but a lookat matrix doesn't use Euler angles at all. In fact, a lookat matrix has nothing to do with rotations, it defines an orientation. The two are related (you can build an orientation from a series of rotations), but they are not the same.

You may find this thread thread useful; it explains how a lookat matrix is actually constructed. Nowhere are any rotations made, so there is no opportunity for gimbal lock to occur.

As for why your billboards are flipping around, look at this billbaord explanation. Skip down to the right half of Figure 5. Imagine the right half of Figure 5 in that image is flipped vertically so that the camera is on the top. Does that look like what you are trying to do? Notice how once the billboards pass under the camera, the side that is "up" changes. The "down" side of the billboard is always the one closest to the camera's location on the ground. This means, however, that as the camera passes over a billboard, the billboard is going to have to "spin" around so that the "down" part is still closest to the camera.

To fix this problem, use viewplane aligned billboards, also explained in that article (the left hand side of Figure 5). This will guarantee that all billboards in the scene, regardless of where they are in relation to the camera, will have the same orientation. The only thing to be careful of is to never look perfectly straight down, as this will produce undefined behavior. If you do want to look perfectly straight down, just fake it by looking ever so slightly ahead (even a fraction of a fraction of a degree forward is enough) so that the math is properly defined. Your players will never be able to tell the difference, but your billboards will be behaving as you want them to.

[edit] Or at least, this is what I think will fix the problem. You still haven't posted any screenshots or code so I'm going by what in my experience is the most likely cause of your problem as described.

[Edited by - kuroioranda on December 7, 2010 1:51:23 PM]

Share this post


Link to post
Share on other sites
OK, thanks but I'm not trying to do actual billboarding, so view plane alignment wont work for me; I dont want the object moving around when i rotate the camera.

Let me restate things:

1)I am trying to rotate an object to always face camera.
2)It must not move when the camera rotates.
3)It shouldn't spin around when the camera is above or below the object.
4)I have to be able to rotate in "increments" of degrees or radians

While I have mainly been trying to rotate it using Euler angles, i tried a lookat matrix with the same problems.

To me, whatever this problem is called, it seems as though the rotation axis is the important thing. I wish i could explain better, but the practical reason I am doing this is as follows:

I want to render a spherical terrain (planet). I am using vertex textures generated on the fly to displace the terrain and I use a series of flat nested square patches to represent the terrain(they will be displaced and "spherized" in the vertex shader). These patches must rotate around a centerpoint to always face the camera (to maintain the highest vertex density near the viewer) , but they have to move in specific increments so the vertex texture always aligns with the vertices in the same way (otherwise you get this swimming effect). I think you can see then why this "spinning" is a problem.

It works fine when the camera is rotating the planet around the equator, but as you go up toward the poles this spinning starts.

I tried to explain it in the simplest way possible without all this other stuff.

Share this post


Link to post
Share on other sites
I don't think what you're attempting will work. You're dividing the sphere into patches like those formed by latitude and longitude lines. When you move around the equator, all these patches are the same shape. So far so good. But as you move from the equator toward the pole, the patches change shape (becoming thinner). So you cannot rotate the sphere to snap one patch to another, even if you rotate by a fixed increment in degrees.

I think a better approach might be to translate the problem into the flat plane space of your texture, where all the patches are identical in shape. Draw the sphere in world space normally, but slide the texture coordinates in integer increments, so as to shift coverage onto the visible area of the sphere.

Share this post


Link to post
Share on other sites
Do you require that for a given camera location, the object's rotation must always be the same? If so, then I think it's impossible. If not, then I think you can do it with incremental rotations.

What will happen when you fly over the object is that it will get "dragged" over by the camera, and thus be upside down when you get to the other side of it.

However, if you walk around the object, then it will stay rightside up the whole way around. So the object can be rotated differently for a given camera location, depending on how you got it there.

So if that's ok, then here's how I'd do it. Take the object's forward vector (was looking at the camera last frame) and the vector from the object to the camera. Normalize them, dot product them, and if they're too close together, then don't do anything. If there is some difference, then cross product the two vectors to get a rotation axis, inverse cosine that dot product value to get the angular difference, and rotate all 3 axis vectors of the object's matrix around the cross product axis.

Don't forget to normalize and orthogonalize the object's matrix periodically due to imperfect numerical accuracy.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this