Sign in to follow this  
impulsee

make an object rotate to face a vector (Opengl 3D)

Recommended Posts

Hi guys

 

I have been trying to work out how to make an object rotate to face another object in Opengl (with the glm library) but in still a little confused on a couple of things and was hoping you guys could help me out smile.png

 

At this moment I think what I have to do is have a normalized direction vector, and then a normalized vector of the object I want to face - current object and then computer the dot and cross product from this for the axis and angle of rotation. It is at this point where I am stuck on what to do next (if I even have the first part right). I should also mention that I am trying to use quaternions so any help that you can give me on applying it both for a rotation matrix and a quaternions would be very appreciated. 

 

For the original set up, I use a set of Euler angles (in a vec 3 for pitch, yaw and roll) and do the following   myquat = glm::quat(Eulerangles);. and then turn the quaternion into a matrix  glm::mat4 RotationMatrix = glm::toMat4(myquat);

 

Here is the code I have so far 


void Gamemodelimported::rotateobject(glm::vec3 otherposition)
{
  glm::vec3 currentlook;

  currentlook.x = glm::cos(glm::pitch(myquat)) * glm::cos(glm::yaw(myquat) + (0.0174532925 * 90));
  currentlook.z = -glm::cos(glm::pitch(myquat)) * glm::sin(glm::yaw(myquat) + (0.0174532925 * 90));
  currentlook.y = glm::sin(glm::pitch(myquat));

  currentlook = glm::normalize(currentlook);

  glm::vec3 diff = otherposition - _position;

  diff = glm::normalize(diff);
    
  float angle = glm::acos(glm::dot(diff,currentlook));

  glm::vec3 corrsspro = glm::cross(diff,currentlook); 


 
}

If you also have time can you suggest a good way to make the object slowly rotate to face the vector point.

 

Thanks for you time and help smile.png

 

Edit: I should mention that the + 90 on the yaw is to compensate for the original model rotation (I think that's the correct way not sure but it does move in the correct direction with that code)

Edited by impulsee

Share this post


Link to post
Share on other sites

The quaternion version of the look at is more expensive than the conversion from a look at matrix.

Just make a look at matrix, transpose it and convert to a quaternion and you have the result.

Edited by Alundra

Share this post


Link to post
Share on other sites


Just make a look at matrix, transpose it and convert to a quaternion and you have the result.

 

can you go into more depth about this if you don't mind sorry, still trying to get to grips with it all.

Share this post


Link to post
Share on other sites

Use GLM lookAt :

detail::tmat4x4<T> glm::gtc::matrix_transform::lookAt
(
  detail::tvec3< T > const & eye,
  detail::tvec3< T > const & center,
  detail::tvec3< T > const & up
)

On your case the rotation matrix will be :

glm::mat4 RotationMatrix = glm::transpose(glm::lookAt(_position, otherposition, glm::vec3(0.0f, 1.0f, 0.0f)));

Now convert to quaternion if you use quaternion and not matrix for the representation of the rotation :

Rotation = glm::toQuat(RotationMatrix);
Edited by Alundra

Share this post


Link to post
Share on other sites

Something extra to consider:

While it may happen to be convenient that your OpenGL math functions do the same operations as your world manipulation math functions, I strongly recommend you consider them as distinct actions.  Moving a game object should not be considered the same thing as the OpenGL rendering motion. 


The objects being shown to the player have very little to do with the representation of game objects within a simulation, which also typically has very little to do with the objects inside a physics simulation.  Yes the player can see the end results of the action, but it is a common mistake for beginners to equate graphics, physics, and simulator motions since the all happen to use the same branch of mathematics. 

Just because they happen to use the same type of math operations does not mean they are otherwise closely related.  

 

The math operation you call "rotate to face a vector" is typically called "lerp" (a linear interpolation) or "slerp" (spherical linear interpolation), with the difference shown here.  There are several similar and related interpolation functions with slight variations to compute cost and behavior. For example you can follow a less compute-expensive path through a quaternion where the vector out is the same but results in rotations, basically a partial barrel roll as the direction smoothly changes.

Share this post


Link to post
Share on other sites

Just to ask another question, if the object i want to rotate to is directly above me (e.g. position = (0,0,0), otherposition = (0,5,0)) it comes back as error values (I'm guessing because of the matrix construction) is there any practical way around this? (this is with the look at function)

Edited by impulsee

Share this post


Link to post
Share on other sites

The direction and the up vector must not be parallel, check using a dot product and an epsilon then change the up to (1.0f, 0.0f, 0.0f) of the lookAt matrix.

Another option is to check if the cross product of the direction and the up is the vector (0.0f, 0.0f, 0.0f).

Edited by Alundra

Share this post


Link to post
Share on other sites

blink.png wow cant believe I missed that, thanks.

 

sorry again but I just want to be sure, what is the best way to create a direction vector from a quaternion (or matrix) and is there any way of slowly rotating the object towards the target rather then having it always facing?

Share this post


Link to post
Share on other sites

To smoothly rotate an object from one direction to another you can use the SLERP or NLERP, but i'm not sure if GLM has NLERP version.

Pseudo code :

NewRotation = SLERP(CurrentRotation, NewRotation, Factor);

Don't forget to always use the elapsed time to be frame-independent, Factor can be like that :

Factor = CLAMP(5.0f * ElapsedTime, 0.0f, 1.0f);
Edited by Alundra

Share this post


Link to post
Share on other sites

Thanks again,

 

One last question then I think i'm all set, obviously I could make the object move towards the point by doing 

 

vec3 direction = nor(otherposition - position) but i want to move in the rotation direction (forward vector)

 

is the best way to do this with pitch roll and yaw of the quad or is there a better/other way?

Edited by impulsee

Share this post


Link to post
Share on other sites

I don't understand well your question, if you want to move your object on its current rotation, only compute the forward vector from the quaternion and use that to move :

glm::vec3 ForwardDirection = glm::normalize(Rotation * glm::vec3(0.0f, 0.0f, 1.0f));
glm::vec3 NewPosition = CurrentPosition + (ForwardVector * Speed * ElapsedTime);
Edited by Alundra

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