Page 1 of 1

Rotating rigidbody to face direction of another rigidbody

Posted: Tue Mar 17, 2015 10:22 am
by ryanas
I want to rotate a rigid body to face in the direction of another rigid body. Everything is on the same Y axis so I'm only worried about x and z.

Currently I'm doing this;

Code: Select all

//get our facing vector
vec3 facingVec = target_location - current_location;

float temp = atan2(facingVec.z(), facingVec.x());
//convert to degrees
float tempDegrees = temp * 180.0f / 3.14159265f;

float angle = tempDegrees - oldAngle;
oldAngle= tempDegrees;
So I figured I have float a which is the difference in angles and am using this function to rotate it

Code: Select all

void rotate(scene_node *player_node, float angle){
      player_node->activate();
      btTransform trans = player_node->get_rigid_body()->getCenterOfMassTransform();
      btQuaternion transrot = trans.getRotation();
      btQuaternion rotquat;
      rotquat = rotquat.getIdentity();
      rotquat.setY(angle);
      transrot = rotquat * transrot;
      trans.setRotation(transrot);
      player_node->get_rigid_body()->setCenterOfMassTransform(trans);
    }
But I cannot get it to work for the life of me, any help would be great.

Re: Rotating rigidbody to face direction of another rigidbod

Posted: Tue Mar 17, 2015 4:51 pm
by Dirk Gregorius
This is often called the shortes arc quaternion. There should be a function called shortesArcQuaternion() in Bullet based on Stan Melax article in one of the GPG.

Here is another good disussion:
http://stackoverflow.com/questions/1171 ... to-another

Re: Rotating rigidbody to face direction of another rigidbod

Posted: Tue Mar 17, 2015 6:37 pm
by ryanas
Thanks for the term, I've had a look at it and I'm not quite sure how I'd use it to rotate the second object to face the first.

Is there any reference/code that shows this in action?

Re: Rotating rigidbody to face direction of another rigidbod

Posted: Tue Mar 17, 2015 8:40 pm
by Erwin Coumans
It seems you just want to create some orientation matrix, given a fixed UP vector (Y axis) and a forward vector in the direction B_center-A_center for object A looking at B.
Then you could create btMatrix3x3 of (right, up, forward), computing 'right' using the normalized cross product of up and forward (and make sure forward and up are orthogonal, re-compute forward using normalized cross product up/right).

Re: Rotating rigidbody to face direction of another rigidbod

Posted: Tue Mar 17, 2015 10:32 pm
by drleviathan
Here is some code that probably does what you want. I had to guess as to what your payer's "forward" direction is in its local frame. I didn't compile or test it:

Code: Select all

btVector3 lookDirection = target_location - current_location;
float lookLength = lookDirection.length();
if (lookLength > FLT_EPSILON) {
    lookDirection /= lookLength;
    setLookDirection(player_node, lookDirection);
}

// ...

void setLookDirection(scene_node *player_node, const btVector3& newLook) {
    player_node->activate();

    // assume that "forward" for the player in local-frame is +zAxis
    // and that the player is constrained to rotate about yAxis (+yAxis is "up")
    btVector3 localLook(0.0f, 0.0f, 1.0f); // zAxis
    btVector3 rotationAxis(0.0f, 1.0f, 0.0f); // yAxis

    // compute currentLook and angle
    btTransform transform = player_node->get_rigid_body()->getCenterOfMassTransform();
    btQuaternion rotation = transform.getRotation();
    btVector3 currentLook = rotation * localLook;
    btScalar angle = currentLook.angle(newLook);

    // compute new rotation
    btQuaternion deltaRotation(axis, angle);
    btQuaternion newRotation = deltaRotation * rotation;

    // apply new rotation
    transform.setRotation(newRotation);
    player_node->get_rigid_body()->setCenterOfMassTransform(transform);
}

Re: Rotating rigidbody to face direction of another rigidbod

Posted: Wed Mar 18, 2015 6:37 am
by ryanas
drleviathan wrote:Here is some code that probably does what you want. I had to guess as to what your payer's "forward" direction is in its local frame. I didn't compile or test it:

Code: Select all

btVector3 lookDirection = target_location - current_location;
float lookLength = lookDirection.length();
if (lookLength > FLT_EPSILON) {
    lookDirection /= lookLength;
    setLookDirection(player_node, lookDirection);
}

// ...

void setLookDirection(scene_node *player_node, const btVector3& newLook) {
    player_node->activate();

    // assume that "forward" for the player in local-frame is +zAxis
    // and that the player is constrained to rotate about yAxis (+yAxis is "up")
    btVector3 localLook(0.0f, 0.0f, 1.0f); // zAxis
    btVector3 rotationAxis(0.0f, 1.0f, 0.0f); // yAxis

    // compute currentLook and angle
    btTransform transform = player_node->get_rigid_body()->getCenterOfMassTransform();
    btQuaternion rotation = transform.getRotation();
    btVector3 currentLook = rotation * localLook;
    btScalar angle = currentLook.angle(newLook);

    // compute new rotation
    btQuaternion deltaRotation(axis, angle);
    btQuaternion newRotation = deltaRotation * rotation;

    // apply new rotation
    transform.setRotation(newRotation);
    player_node->get_rigid_body()->setCenterOfMassTransform(transform);
}
That looks very promising, could I just ask what you meant to define with the variable 'axis' on the line

Code: Select all

// compute new rotation
btQuaternion deltaRotation(axis, angle);

Re: Rotating rigidbody to face direction of another rigidbod

Posted: Wed Mar 18, 2015 12:01 pm
by drleviathan
In order to rotate your object from where it is (rotation) to where you want it to be (newRotation) you must apply a deltaRotation which is defined by some angle about some axis. Hence axis is the axisOfRotation... I was just keeping the names nice and short.