0

I am working on a game project using OpenGl. I am building a game from skeleton code I found online. I have a character that can move around in a 2D plane. (x and z, ie you are viewing the character from above.) I am currently stuck on making him rotate as he moves, and I can't seem to find a solution online that solves my problem.

At the moment when the character is being drawn he faces a certain way (along the arrow in my diagram below.). I can rotate him an arbitrary number of degrees from his default direction using glm::rotate.

I have updated the code to log the characters position from a frame ago when he moves, so I have this information:

character old position (known)->           O    
character starting angle (unknown)->       |\    
                                           | \   
                                           |  \
                                           |(X)\
                                           |    \
                                           V     O <- character new position (known)

How do I compute the angle (X)? Is it possible with the information I have?

I have been doodling on a page trying to figure this out for the last hour but can't seem to figure it out. Thanks very much.

kevinh
  • 61
  • 7

2 Answers2

1

Yes. This answer gives you an example of how to do it: How to calculate the angle between a line and the horizontal axis? Note however that that will give you the angle between the horizontal axsis and the point. You can however just add 90 degrees.

Community
  • 1
  • 1
Kurdunas
  • 26
  • 2
  • Thank you, that does exactly what I needed. Just tested it and it works great! Thank you very much. – kevinh Dec 06 '14 at 14:46
1

What you're doing sounds somewhat convoluted. From the description, it seems like you want a rotation matrix that matches the direction. There's really no need to calculate an angle. You can build the rotation matrix directly, which is easier and more efficient.

I'll illustrate the calculations with points/vectors in the xy-plane, since that's much more standard. It sounds like you're operating in the xz-plane. While that doesn't change things much, you might need slight changes because you have a left-handed coordinate system.

If you have the direction vector (difference between new position and old position), all you need to do is normalize it, and you already have what's needed for the rotation matrix. I'll write the calculation explicitly, but your matrix/vector library most likely has a method to normalize a vector.

float vx = nexPosX - oldPosX;
float vy = newPosY - oldPosY;
float s = 1.0f / sqrt(vx * vx + vy * vy);
vx *= s;
vy *= s;

vx is now the cosine of the rotation angle, and vy the sine of the rotation angle. Substituting this into the standard form of a rotation matrix, you get:

R = ( cos(phi)  -sin(phi) ) = ( vx  -vy )
    ( sin(phi)   cos(phi) )   ( vy   vx )

This is the absolute rotation for the new direction. If you need the relative rotation between old direction and new direction, it just takes a few more operations. Let's say you already calculated the normalized vectors for the old and new directions as (v1x, v1y) and (v2x, v2y). The cosine of the rotation angle is the scalar product of the two vectors:

cosPhi = v1x * v2x + v1y * v2y;

and the sine is the length of the cross product. Since both vectors are in the xy-plane, that's simply the z-component of the cross product:

sinPhi = v1x * v2y - v1y * v2x;

With these two values, you can directly build the rotation matrix again:

R = ( cosPhi  -sinPhi )
    ( sinPhi   cosPhi )
Reto Koradi
  • 53,228
  • 8
  • 93
  • 133
  • Hi Reto Koradi, Thanks very much for your answer, I don't think I will be implementing it that way in my project for now because I have it working at the moment and its only for a student project due in about two days, but that definitely explained it quite clearly. (Your way is consistent with what my lecturer has been telling me so I will refer back to it for my exam.) Thanks very much! – kevinh Dec 06 '14 at 21:03