# How to get orientation from a normal

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

## 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 on other sites
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 on other sites
Quote:
 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 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 );      zAxis.normalize();      // 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 );      }      else      {        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 );      xAxis.normalize();      // Correct the Y reference vector      yAxis = xAxis.cross( zAxis );      yAxis.normalize();      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 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).