Jump to content
  • Advertisement
Sign in to follow this  
Viik

Matrix from direction and position

This topic is 2778 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

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 this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by Viik
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?


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

Share this post


Link to post
Share on other sites
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 this post


Link to post
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 this post


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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!