Matrix from direction and position

Recommended Posts

Viik    252
I need to construct motion matrix of an object knowing only direction where it looks at and position. Right now I'm using this routine:
float3	forward = normalize(light_dir);float3	up = float3(0,1,0);float3	v_right = normalize(cross(up, forward));float	dotRP = dot(v_right, light_pos);float	dotUP = dot(up, light_pos);float	dotFP = dot(forward, light_pos);float4x4 parab_matrix = {	 v_right.x, up.x, forward.x, 0.0f,	 v_right.y, up.y, forward.y, 0.0f,	 v_right.z, up.z, forward.z, 0.0f,	 -dotRP,  -dotUP, -dotFP, 1.0f};

It works pretty fine except cases when objects direction and "up" vectors are almost the same, so it gives a gimbal lock. Is there any other way how this can be achived?
I was thinking to use quaternions for this but it looks like it will hit performance too much.

Share on other sites
RobTheBloke    2553
Quote:
 Original post by ViikIt works pretty fine except cases when objects direction and "up" vectors are almost the same, so it gives a gimbal lock. Is there any other way how this can be achived?

Change your up vector when abs(dot(up, forward)) is close to 1.

Share on other sites
jyk    2094
Quote:
 It works pretty fine except cases when objects direction and "up" vectors are almost the same, so it gives a gimbal lock.
It seems to be pretty common to refer to any rotation-related artifact as 'gimbal lock', but no, that's not gimbal lock.
Quote:
 I was thinking to use quaternions for this but it looks like it will hit performance too much.
You don't need to use quaternions for this (in fact, this particular problem is more easily solved using matrices/vectors, IMO).

You can just handle the case you described separately, as RobTheBloke suggested. My own preferred solution though is to use as the reference vector the cardinal basis vector corresponding to the element of the input vector that has the least magnitude; this ensures a valid result, and also ensures maximum stability.

Share on other sites
The calculation is missing a step. You should add this line after the line computing v_right. (Otherwise up and forward may not be perpendicular to each other.)

>>> up = cross(forward, v_right);

Also, your v_right is actually v_left, but perhaps you are using a left-handed coordinate system.

This problem actually has no solution which is continuous in the inputs. In other words, no matter what you do, there will be some direction near which the solution changes suddenly.

The suggestions given in this thread will work, in the sense that you won't get division by zero during the 'normalize', but they won't be stable.

If you know a "previous" value --- for instance if you are tracking this object over time --- then you can achieve stability. Use the previous value of up as the seed for the next value of up.

Share on other sites
Viik    252
Thanks guys! Dynamically setting "up-vector" solves the issue.