Jump to content
  • Advertisement
Sign in to follow this  

How to get orientation from a normal

This topic is 4616 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 there, I am coding a small app where I drop a few boxes on an irregular floor and I'd like them to be rotated according to the ground normal once they hit the floor but I'm having problems with it, I tried building a quaternion from the normal and getting the rotation from it but didn't work very well... anybody has any ideas of another method to orientate a box given a triangle normal?? Thanks in advance for any help :)

Share this post

Link to post
Share on other sites
Guest Anonymous Poster
Use Collision Detection to see when boxes hit the floor. As long as your Collision Responce doesn't make them bounce too much (dampened) then the boxes should end up resting on the ground automatically after a while.

Could there be a problem with gravity in your program? Maybe if gravity was pointed up instead of down the boxes might not want to land flat on the floor...

Share this post

Link to post
Share on other sites
Guest Anonymous Poster
Original post by Elefagente_Secreto
orientate a box given a triangle normal??

Box.Z=Triangle.Normal ?

that should make them line up....

Or if you have information about what part of the box hits the floor first you could take the normal force, and separate it into separte torque and translation force at the point of contact, then use that to calculate how the box should rotate and bounce.
The translation component is whatever part of the normal force aligns with the line from the center of the box to the contact point. the torque component is whatever is left over after translation is subtracted out
so its just a matter of some simple vector projections to calculate them

Share this post

Link to post
Share on other sites
I'm using the following code in my matrix class (i found somewhere on the net), and it works neatly.

GR::tVector is a 3d-vector, GR::f32 is a float. The code is using a lot of vector and math functions but the name should give them away. One problem though: Orienting along a vector is not enough information; the object can be rotated about that vector as well.

matrix4& OrientAboutAxis( GR::tVector& vectDir, const GR::f32 fDegrees )
GR::tVector zAxis( vectDir );


// Build the Y vector of the matrix (handle the degenerate case
// in the way that 3DS does) -- This is not the TRUE vector, only
// a reference vector.

GR::tVector yAxis;

if ( ( !zAxis.x )
&& ( !zAxis.z ) )
yAxis = GR::tVector( -zAxis.y, 0.0f, 0.0f );
yAxis = GR::tVector( 0.0f, 1.0f, 0.0f );

// Build the X axis vector based on the two existing vectors
GR::tVector xAxis = yAxis.cross( zAxis );


// Correct the Y reference vector
yAxis = xAxis.cross( zAxis );
yAxis = -yAxis;

// Generate rotation matrix without roll included
math::matrix4 rot;

rot.m[0][0] = xAxis.x;
rot.m[0][1] = xAxis.y;
rot.m[0][2] = xAxis.z;
rot.m[0][3] = 0.0f;

rot.m[1][0] = yAxis.x;
rot.m[1][1] = yAxis.y;
rot.m[1][2] = yAxis.z;
rot.m[1][3] = 0.0f;

rot.m[2][0] = zAxis.x;
rot.m[2][1] = zAxis.y;
rot.m[2][2] = zAxis.z;
rot.m[2][3] = 0.0f;

rot.m[3][0] = 0.0f;
rot.m[3][1] = 0.0f;
rot.m[3][2] = 0.0f;
rot.m[3][3] = 1.0f;

// Generate the Z rotation matrix for roll (bank)
math::matrix4 roll;

roll.RotationZ( fDegrees );

// Concatinate them for a complete rotation matrix that includes
// all rotations
*this = roll * rot;

return *this;

Share this post

Link to post
Share on other sites
It's possible that you are having a problem because a surface normal does not give you enough information compute an orientation. There are an infinite number of orientations that will line up with a surface normal. Luckily, it is easy to compute one of them. You can compute the axis and angle of a rotation that will line up two unit vectors (in your case, the normal of the floor surface and the normal of the box surface) like this:
    axis = normalize( cross( v1, v2 ) )
angle = acos( dot( v1, v2 ) )

A note of caution: You should clamp the parameter of acos to [-1,1] just in case the result of the dot product is outside of that range. v1 and v2 must not be parallel (if they are, you can pick any axis).

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.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!