How do I rotate a 2D Vector?

Started by
3 comments, last by CowKing 9 years, 10 months ago

I've posted this general programming question on other forums, but haven't had much luck. Hopefully someone here can help me.

As the title says, I have a 2D unit vector, and I simply need to rotate it by X degrees. I've done a lot of googling, and couldn't really find what I needed (most similar problems I found were quite a bit more complex).

Also I'd be calling this up to 4 times per update, so I'm hoping for a solution that isn't horrible on performance.

Tried multiplying my vector like the following as suggested online:


Quaternion.AngleAxis(Camera.main.transform.rotation.y, Vector3.forward) * new Vector2(Input.GetAxis("P1MoveHorizontal"), Input.GetAxis("P1MoveVertical"))

Input.GetAxis returns a float from -1 to 1 representing the X position of the joystick. (So the joystick direction is a unit vector).

Didn't make any difference.
And


    Quaternion.AngleAxis(Camera.main.transform.rotation.y, Vector3.forward) * new Vector2(Input.GetAxis("P1MoveHorizontal"), Input.GetAxis("P1MoveVertical"))

Gives me an error where Quaternion cannot multiply with a vector2.


Tried this:


    float sin = Mathf.Sin(Camera.main.transform.rotation.y);
            float cos = Mathf.Cos(Camera.main.transform.rotation.y);
    
            float tx = Input.GetAxis("P1MoveHorizontal");
            float ty = Input.GetAxis("P1MoveVertical");
            Move(new Vector2((cos * tx) - (sin * ty), (cos * ty) + (sin * tx)));

Made a difference, but still not the correct directions.

I even tried convert the unit vector to degrees, adding the camera's rotation in degrees, and then converting it back into a vector:


    float directionAngle = Mathf.Atan2(Input.GetAxis("P1MoveVertical"), Input.GetAxis("P1MoveHorizontal"));
            directionAngle += Camera.main.transform.rotation.y;
            Move(new Vector2(Mathf.Sin(directionAngle), Mathf.Cos(directionAngle)));

But EVEN THIS which I was certain would work but was hoping to avoid for inefficiency, is not working at all as expected. Without even inputting a direction my object moves around in circles and wanders off the scene.

Advertisement

Let v be your vector and R be the rotation matrix. Simply multiply v by R to get the rotated vector.


v = [ x y ]
R = [ cos(theta) -sin(theta)
      sin(theta)  cos(theta)]

Rotated_v = R * transpose(v)
          = [ cos(theta) * v.x - sin(theta) * v.y
              sin(theta) * v.x + cos(theta) * v.y ]

This looks similar to one of your attempts, the one where you said you didn't get "the correct directions". What did you mean by that? Did it rotate in the opposite direction that you thought it would?

EDIT: For some justification: the columns of R are the basis vectors of the identity matrix under a rotation of theta degrees. Rotation is a linear operation that transforms a vector into a rotated space, which is what the R matrix represents (the identity rotated by theta degrees).

EDIT2: I'm not exactly sure what Camera.main.transform.rotation.y contains. What type is camera.main.transform.rotation? I'm going to guess that it's a quaternion storing the orientation of your camera. In that case, rotating by the y component of the quaternion that represents your camera's orientation doesn't make much (any) sense. You'll have to provide a bit more information for us to understand what exactly you're trying to accomplish here.

Let v be your vector and R be the rotation matrix. Simply multiply v by R to get the rotated vector.


v = [ x y ]
R = [ cos(theta) -sin(theta)
      sin(theta)  cos(theta)]

Rotated_v = R * transpose(v)
          = [ cos(theta) * v.x - sin(theta) * v.y
              sin(theta) * v.x + cos(theta) * v.y ]

This looks similar to one of your attempts, the one where you said you didn't get "the correct directions". What did you mean by that? Did it rotate in the opposite direction that you thought it would?

EDIT: For some justification: the columns of R are the basis vectors of the identity matrix under a rotation of theta degrees. Rotation is a linear operation that transforms a vector into a rotated space, which is what the R matrix represents (the identity rotated by theta degrees).

EDIT2: I'm not exactly sure what Camera.main.transform.rotation.y contains. What type is camera.main.transform.rotation? I'm going to guess that it's a quaternion storing the orientation of your camera. In that case, rotating by the y component of the quaternion that represents your camera's orientation doesn't make much (any) sense. You'll have to provide a bit more information for us to understand what exactly you're trying to accomplish here.

Yeah you guessed correctly. Camera.main.transform.rotation.y wasn't what I thought it was, now I'm using Camera.main.transform.rotation.eulerAngles.y instead. It still doesn't work properly. The directions DO change (incorrectly), and I can't find a pattern with it really.. It's just the more rotated the camera is from it's original position, the less accurate the direction offset seems to be. In one direction the controls get reversed, in another all controls are 90 degrees off.

I'm not sure how to use matrices in code.. Honestly I didn't think I'd need matrices for something so simple anyway.

EDIT: OH and apparently sin and cos take their arguments in radians, which confused me a bit as I remember always putting in degrees in school, but either way now I have the angle converted to radians and still have the problem mentioned above.

EDIT: Solved. Apparently Sin functions aren't consistent in what sign they return their result in. I tried switching it to -sin and all works fine. Thanks for the help!


EDIT: Solved. Apparently Sin functions aren't consistent in what sign they return their result in. I tried switching it to -sin and all works fine. Thanks for the help!

A basic math function is wrong? If that's the case a lot of people should have complained about it a long time ago. Are you sure it's a problem with the function?

Maybe the angle you're sending is wrong... -sin(a) == sin(-a) and cos(a) == cos(-a) so you'll get the right value for cos but the other value for sin if you have the wrong sign on the angle. Changing the angle instead of the sin result seems like a better idea to me.

I assume you're using Unity3D, and you're in "2D" mode. In which case, you need to use unity's depth axis 'Z'. You need to rotate the object on it's Z axis. I got really confused on that as well.

Here's what I used to rotate a point:

theta is in radians


private static Vector2 Rotate2DPoint(Vector2 point, float theta) {
		float sinT = Mathf.Sin(theta); float cosT = Mathf.Cos(theta);
		return new Vector2(
			point.x*cosT - point.y*sinT,
			point.x*sinT + point.y*cosT
			);
}

This topic is closed to new replies.

Advertisement