5
\$\begingroup\$

I'm looking for an easy way to achieve the following:

Object A, B
{
    Vector2D position;
    Vector2D orientation;
}

update(elapsed)
{
    //rotate A's orientation in B's direction by x * elapsed degrees
    //until A's orientation equals the direction from A to B
}

I am trying to align object A with an object B. Object A should rotate in B's direction by certain degrees/sec, e.g. max 45/sec.

I calculate the direction from A to B with normalize(B.position - A.position), but I don't know how to rotate A's orientation vector stepwise in B's direction.

\$\endgroup\$

4 Answers 4

5
\$\begingroup\$

You could always deploy a type of Linear Interpolation. This allows you to slowly move to the target rotation over time and make it look decent.

If I'm misunderstanding and you simply want the angle between the two vectors, you might want to first normalize them (as you have done) and then simply take the dot product and angle. You can find a StackOverflow post on the topic over here, it's written in PHP but very easily read for any language.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ In addition, some engines already have build in linear interpolation functions (e.g. lerp in unity3d). \$\endgroup\$
    – Appleshell
    Commented May 26, 2013 at 14:01
  • \$\begingroup\$ Interpolating the orientation of a vector is not that simple. Imagine: A = (1.0, 0.0), B = (-1.0, 0.0) A is pointing right, B is pointing left. Interpolating them will not give the desired result (rotating, passing through top) \$\endgroup\$ Commented Jul 19, 2014 at 3:38
2
\$\begingroup\$

thank you for your answers.

Linear interpolation sounds interesting, but I wasn't able to solve my problem with it. What I didn't mention in my question is that object B can change its position while A is aligning to it, so the adjustment of the interpolation scalar seemed quite difficult to me. (e.g. if the angle between both objects increases, the interpolated vector "moves" faster)

I extended my vector class by the following function which should be equivalent to multiplying the vector by a 2x2 rotation matrix:

public Vector2D rotate(double radians)
{
    double x = this.x * Math.cos(radians) - this.y * Math.sin(radians);
    double y = this.x * Math.sin(radians) + this.y * Math.cos(radians);
    this.x = x;
    this.y = y;
    return this;
}

If I call rotate(desiredRadians * elapsed) on A's orientation vector, the rotation works fine.

I still don't know how to stop the rotation when the desired direction (or angle) is reached. Also A would ideally rotate in the "shorter" and not necessarily in clockwise direction (e.g. prefer a rotation by -90 to +270 degrees).

Thank you.

\$\endgroup\$
1
\$\begingroup\$

Finally I solved my issue as follows:

update(double elapsed)
{
double targetAngle = Math.atan2(B.position.y - position.y, B.position.x - position.x);
double currentAngle = orientation.toRadians();

//Calculate angular deviation
double deviation = targetAngle - currentAngle;
double absDeviation = (deviation < 0 ? -deviation : deviation);

double maxRotation = maxRad * elapsed;

//If the absolute deviation is less than max rotation, rotate by.
//Else rotate the allowed radians in B's direction.
if(absDeviation <= maxRotation)
    orientation.rotate(deviation);
else
    orientation.rotate(Math.signum(deviation) * maxRotation);
}

Thank you for your time.

\$\endgroup\$
0
\$\begingroup\$
  1. Convert the desired degrees/second to radians/frame;
  2. Calculate the rotation matrix M (if 3D, about the cross-product A x B, else about the Z-axis) for the value calculated in (1) above;
  3. Each frame, generate a new A from the previous frame's A * M.

Are you familiar with (1) use of homogeneous matrices and (2) converting a rotation matrix about the origin to a rotation matrix about some other point in the plane?

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .