9
votes

I would like to rotate an object to face a point which I'm have a bit of of trouble with.

So I'm starting with an object that has a base at zero and is aligned on the y axis.

enter image description here

I would like to rotate it so that the top of the object is facing the destination

enter image description here

My process so far is to: Given axis A

  1. find the distance between my position and my look position: D
  2. create a direction vector: V = D.normalize()
  3. find the right vector: R = A cross D
  4. find the up vector: U = D cross R
  5. find the angle between up and direction: ANGLE = acos((U dot D) / (U.length * D.length))
  6. rotate by angle scaled by direction on each axis

here is the code representation of that. I'm not sure what exactly is wrong with this I've worked it out on paper and to my knowledge this approach should work but the results are completely incorrect when drawn. If anyone sees any flaws and could point me in the right direction it would be great.

    Vector3 distance = new Vector3(from.x, from.y, from.z).sub(to.x, to.y, to.z);
    final Vector3 axis = new Vector3(0, 1, 0);
    final Vector3 direction = distance.clone().normalize();

    final Vector3 right = (axis.clone().cross(direction));
    final Vector3 up = (distance.clone().cross(right));

    float angle = (float) Math.acos((up.dot(direction)/ (up.length() * direction.length()))); 
    bondObject.rotateLocal(angle, direction.x , direction.y, direction.z);
1
I think there is a problem with your math. In step 5 you find the angle between the "up" vector and the direction vector, but this angle will always be 90 degrees. U = D cross R, so by definition U is perpendicular to both D and R, and the dot product U dot D will always be zero. If you can be more specific about what you are trying to accomplish then I can find you a better formula.mikebolt
Thanks for the reply, I'm trying to rotate the object to face a point so if my object is at (0,0,0) and the point is at (0,0,1) I want the cylinder to face down the z axis(the tube encapsulating the z axis). II tried to provide an image above but my paint skills are a lacking ^^William Gervasio

1 Answers

19
votes

The basic idea here is as follows.

  • Determine which way the object is facing: directionA
  • Determine which way the object should be facing: directionB
  • Determine the angle between those directions: rotationAngle
  • Determine the rotation axis: rotationAxis

Here's the modified code.

Vector3 distance = new Vector3(from.x, from.y, from.z).sub(to.x, to.y, to.z);

if (distance.length() < DISTANCE_EPSILON)
{
    //exit - don't do any rotation
    //distance is too small for rotation to be numerically stable
}

//Don't actually need to call normalize for directionA - just doing it to indicate
//that this vector must be normalized.
final Vector3 directionA = new Vector3(0, 1, 0).normalize();
final Vector3 directionB = distance.clone().normalize();

float rotationAngle = (float)Math.acos(directionA.dot(directionB));

if (Math.abs(rotationAngle) < ANGLE_EPSILON)
{
    //exit - don't do any rotation
    //angle is too small for rotation to be numerically stable
}

final Vector3 rotationAxis = directionA.clone().cross(directionB).normalize();

//rotate object about rotationAxis by rotationAngle