# Vector Rotation Problem

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

## Recommended Posts

So what I want to do is to have my main character holding a weapon that aims wherever the mouse is pointing.

My solution to this is to find the current position of the mouse, find the angle between that point and the character's current direction vector, and then finally rotate the character's direction vector by that angle to make it point toward the mouse.

I've never used vectors in my games before, and I'm running into a problem; namely, my code implementation isn't working Here is my code (C++):

//set weapon's direction
//rotate
m_vDirection.rotate(angle);
//get angle between weapon direction and 0 degrees
Vector2D vectemp;
vectemp.x = m_vPosition.x - m_rCamera->x;
vectemp.y = m_vPosition.y - m_rCamera->y;
float angleFromZero = m_vDirection.findAngleDegrees(vectemp);
if(angleFromZero > 360)
angleFromZero /= 360;
//set image accordingly
if((angleFromZero >= 0 && angleFromZero <= 30) ||
(angleFromZero >= 330 && angleFromZero <= 0))
{
currentDirection = RIGHT;
}
else if(angleFromZero >= 31 && angleFromZero <= 59)
{
currentDirection = UPRIGHT;
}
else if(angleFromZero >= 60 && angleFromZero <= 120)
{
currentDirection = UP;
}
else if(angleFromZero >= 121 && angleFromZero <= 149)
{
currentDirection = LEFTUP;
}
else if(angleFromZero >= 150 && angleFromZero <= 210)
{
currentDirection = LEFT;
}
else if(angleFromZero >= 211 && angleFromZero <= 239)
{
currentDirection = LEFTDOWN;
}
else if(angleFromZero >= 240 && angleFromZero <= 300)
{
currentDirection = DOWN;
}
else if(angleFromZero >= 301 && angleFromZero <= 329)
{
currentDirection = RIGHTDOWN;
}
m_pSprite->setClip(clips[currentDirection]);

As you can see, I try to find the direction that the weapon is currently pointing by checking the angle between a vector (that I think is) pointing along 0 degrees, and the main character's direction vector. This is the part that I think is really not working. And in actuality, I expect it not to because when I think about it, I feel like there is definitely something wrong with my theory, because I don't know what the origin of these vectors are, which could throw off my whole assumption of the 0-360 degrees being the directions that I think they are.

Here are my implementations for Vector2D::findAngleRadians(), Vector2D::findAngleDegrees(), and Vector2D::rotate() just in case anyone wants to see them:

{
float dotProd,
lengthLHS,
lengthRHS,
angleCos;
//find dot product
dotProd = dot(rhs);
//find length of each vector
lengthLHS = getLength();
lengthRHS = rhs.getLength();
//find the cosine of the angle
angleCos = dotProd / (lengthLHS * lengthRHS);
//return angle between the two vectors in radians
return acosf(angleCos);
}
//*****************************************************
float Vector2D::findAngleDegrees(Vector2D& rhs)
{
const double PI = 3.1415926;
float dotProd,
lengthLHS,
lengthRHS,
angleCos,
//find dot product
dotProd = dot(rhs);
//find length of each vector
lengthLHS = getLength();
lengthRHS = rhs.getLength();
//find the cosine of the angle
angleCos = dotProd / (lengthLHS * lengthRHS);
//return angle between the two vectors in degrees
return (angleInRads * (180 / PI));
}
//*****************************************************
Vector2D& Vector2D::rotate(float t)
{
x = x * cosf(t) - y * sinf(t);
y = y * cosf(t) + x * sinf(t);
return *this;
}

##### Share on other sites

My solution to this is to find the current position of the mouse, find the angle between that point and the character's current direction vector, and then finally rotate the character's direction vector by that angle to make it point toward the mouse.

It is usually not necessary to compute an angle and from that to compute an orientation. Often it is suitable to build the orientation directly from the direction.

E.g. if t denotes the target point and a the anchor point of the character, then
d := t - a
denotes the difference vector from the character to the target, and
d' := d / |d|
denotes the belonging normalized direction vector. Using the perp operator you can get a perpendicular vector to that. E.g.
p := perp( d' ) = [ d'[sub]y[/sub] -d'[sub]x[/sub] ][sup]t[/sup]
is a solution if the positive y is 90° counterclockwise to the positive x axis.

With this, the orientation matrix is simply
[ d' p ]
(assuming that the "forward" vector is located at the first column). Much easier than using angles, isn't it?

However, throwing a look at your code:

...

//set weapon's direction

So, how is "mouse" defined? Is it already given in the same space as m_vDirection?

//rotate
m_vDirection.rotate(angle);
//get angle between weapon direction and 0 degrees
Vector2D vectemp;
vectemp.x = m_vPosition.x - m_rCamera->x;
vectemp.y = m_vPosition.y - m_rCamera->y;
float angleFromZero = m_vDirection.findAngleDegrees(vectemp);
if(angleFromZero > 360)
angleFromZero /= 360;

You want to use "angleFromZero -= 360;" here.

//set image accordingly
if((angleFromZero >= 0 && angleFromZero <= 30) ||
(angleFromZero >= 330 && angleFromZero <= 0))
{
currentDirection = RIGHT;
}
else if(angleFromZero >= 31 && angleFromZero <= 59)
{
currentDirection = UPRIGHT;
}
else if(angleFromZero >= 60 && angleFromZero <= 120)
{
currentDirection = UP;
}
else if(angleFromZero >= 121 && angleFromZero <= 149)
{
currentDirection = LEFTUP;
}
else if(angleFromZero >= 150 && angleFromZero <= 210)
{
currentDirection = LEFT;
}
else if(angleFromZero >= 211 && angleFromZero <= 239)
{
currentDirection = LEFTDOWN;
}
else if(angleFromZero >= 240 && angleFromZero <= 300)
{
currentDirection = DOWN;
}
else if(angleFromZero >= 301 && angleFromZero <= 329)
{
currentDirection = RIGHTDOWN;
}
m_pSprite->setClip(clips[currentDirection]);

This is an insufficient solution, because you have gaps between the particular branches. E.g. what happens if angleFromZero is 59.5?

As you can see, I try to find the direction that the weapon is currently pointing by checking the angle between a vector (that I think is) pointing along 0 degrees, and the main character's direction vector. This is the part that I think is really not working. And in actuality, I expect it not to because when I think about it, I feel like there is definitely something wrong with my theory, because I don't know what the origin of these vectors are, which could throw off my whole assumption of the 0-360 degrees being the directions that I think they are.

m_vDirection's name hints that the vector is a direction vector. vectemp is definitely a direction vector. Opposed to position vectors (a.k.a. points), direction vectors lack the concept of "origin". They are just directions.

Here are my implementations for Vector2D::findAngleRadians(), Vector2D::findAngleDegrees(), and Vector2D::rotate() just in case anyone wants to see them:

{
float dotProd,
lengthLHS,
lengthRHS,
angleCos;
//find dot product
dotProd = dot(rhs);
//find length of each vector
lengthLHS = getLength();
lengthRHS = rhs.getLength();
//find the cosine of the angle
angleCos = dotProd / (lengthLHS * lengthRHS);
//return angle between the two vectors in radians
return acosf(angleCos);
}
//*****************************************************
float Vector2D::findAngleDegrees(Vector2D& rhs)
{
const double PI = 3.1415926;
float dotProd,
lengthLHS,
lengthRHS,
angleCos,
//find dot product
dotProd = dot(rhs);
//find length of each vector
lengthLHS = getLength();
lengthRHS = rhs.getLength();
//find the cosine of the angle
angleCos = dotProd / (lengthLHS * lengthRHS);
//return angle between the two vectors in degrees
return (angleInRads * (180 / PI));
}
//*****************************************************
Vector2D& Vector2D::rotate(float t)
{
x = x * cosf(t) - y * sinf(t);
y = y * cosf(t) + x * sinf(t);
return *this;
}

IMHO:
1. You should use "const&" for the parameters named "rhs" above.
2. You should rewrite findAngleDegrees to be as simple as "return findAngleInRadians(rhs) * 180 / PI;", perhaps even inlined.

EDIT: Unfortunately I had written 'perpDot' instead of 'perp' in the original version of this post. Edited by haegarr

##### Share on other sites
Thanks for your reply! I'll look through all of this tomorrow after work

##### Share on other sites

[quote name='Ziel' timestamp='1331290547' post='4920628']
My solution to this is to find the current position of the mouse, find the angle between that point and the character's current direction vector, and then finally rotate the character's direction vector by that angle to make it point toward the mouse.

It is usually not necessary to compute an angle and from that to compute an orientation. Often it is suitable to build the orientation directly from the direction.

E.g. if t denotes the target point and a the anchor point of the character, then
d := t - a
denotes the difference vector from the character to the target, and
d' := d / |d|
denotes the belonging normalized direction vector. Using the perpDot operator you can get a perpendicular vector to that. E.g.
p := perpDot( d' ) = [ d'[sub]y[/sub] -d'[sub]x[/sub] ][sup]t[/sup]
is a solution if the positive y is 90° counterclockwise to the positive x axis.

With this, the orientation matrix is simply
[ d' p ]
(assuming that the "forward" vector is located at the first column). Much easier than using angles, isn't it?
[/quote]

I hate to ask, but would you mind giving a code example of this? Also, I don't understand what the perpendicular dot operator is. >_<

##### Share on other sites
Any help guys? I don't understand the orientation matrix. I looked up the perpdot product and apparently it returns a scalar. How do you stick a vector d' and a scalar p into a matrix? !

##### Share on other sites

[quote name='haegarr' timestamp='1331293732' post='4920638']
...

I hate to ask, but would you mind giving a code example of this? Also, I don't understand what the perpendicular dot operator is. >_<
[/quote]
Form the OP's code snippets its not clear to me whether you have a Matrix2D class, whether Vector2D (and perhaps Matrix2D) are affine or homogeneous, and whether non-scalar operators plus, minus, ... exist. So I'll try to give some code that seems me suiting the OP's code, although I would not implement it that way.

// the position vector denoting the target
Vector2D t = ...;
// the position vector denoting the anchor point of the character, given in same space as t
Vector2D a = ...;

// difference vector from a to t
Vector2D d;
d.x = t.x - a.x;
d.y = t.y - a.y;

// normalizing difference vector gives a standard direction vector (d')
float norm = sqrt( d.x*d.x + d.y*d.y );
d.x /= norm;
d.y /= norm;

// making a perpendicular vector
Vector2D p;
p.x = d.y;
p.y = -d.x;

// building 2D orientation matrix; it is given in the same space as t and a
Matrix2D m;
m.x.x = d.x;
m.x.y = d.y;
m.y.x = p.x;
m.y.y = p.y;

Now, the problems with showing some code are further:
1. I don't know whether you deal with column or row vectors.
2. I don't know whether my definition of "forward" vector (e.g. d') is suitable for our definition of the model and world.
Hence it may be that an offset of e.g. 90° is needed, and / or that the distribution of d's and p's scalars when building m must be done in another way.

...I looked up the perpdot product and apparently it returns a scalar. How do you stick a vector d' and a scalar p into a matrix?

Sorry for that, my mistake. The perpDot operator is just a dot operator but uses a variation of one of its arguments. That variation is in fact a simple method of building a perpendicular vector from a given vector. Its just that method that I wanted to hint at, but not the perpDot in its entirety. I've corrected my posts above, now using a "perp" instead of perpDot now.

• ### Game Developer Survey

We are looking for qualified game developers to participate in a 10-minute online survey. Qualified participants will be offered a \$15 incentive for your time and insights. Click here to start!

• 11
• 23
• 36
• 16
• 75