# Get quaternion between two objects on sphere

In a planetary gravity environment objects are represented in the following way:

struct object {
struct quaternion quat; // quaternion to represent the rotation between the object and the center of the planet
float dist; // distance from the center of the planet
};


Here are the steps at which I position my player:

// start at center of the planet
applyQuaternion(&object.quat);
glTranslatef(0.0f, object.dist, 0.0f);
drawObject(&object);


Step 1, translate to center of planet:

Step 2, apply quaternion:

Step 3, translate outwards by distance value:

I am also able to get the current position of the player or enemy by using this code:

struct matrix initialMatrix, resultantMatrix;
glPushMatrix();
getPositionMatrix(&initialMatrix);
applyQuaternion(&player.quat);
glTranslatef32(0, player.dist, 0);
getPositionMatrix(&resultantMatrix);
playerPosition = matrixTranslationToVector(initialMatrix, resultantMatrix);
glPopMatrix();


Given two objects:

struct object player;
struct object enemy;


How can I get the enemy to face in the direction of the player, whilst always standing upright on the planet, using quaternions?

I want the enemy to go from this:

To this:

His feet always on the planet, and head always away from planet.

I'm able to rotate on the axis which doesn't affect the position (from first enemy diagram to second enemy diagram like so):

// Rotate right
Quaternion_multiply(&player.quat, Quaternion_fromAxisAngle(vect(0.0f, 0.0f, 1.0f), degreesToAngle(2)));

// Rotate left
Quaternion_multiply(&player.quat, Quaternion_fromAxisAngle(vect(0.0f, 0.0f, 1.0f), degreesToAngle(-2)));


So I'm unsure as to why I'd need a local orientation in addition to the quaternion I already have.

• You are representing your position as quaternion. How are you representing your local orientation, your player orientation relative to itself ? Oct 30, 2014 at 7:46
• There is only 1 quaternion, and 1 distance value. The player is rotated by the quaternion so he is perpendicular to the planet (standing upright) and then translated outwards according to his distance from the planet. The quaternion can represent any position on the planet. The player is always facing outwards of the planet. Oct 30, 2014 at 8:01
• So if I understand correctly the forward vector (direction player is facing) is pointing outwards (perpendicular) of the planet? Oct 30, 2014 at 8:20
• the struct object you mentioned only represent position. Do you have local orientation? Oct 30, 2014 at 8:22
• Your quaternion in this case is actually position in spherical coordinates. if I understand correctly your player doesn't have a local orientation (you don't track the direction the player is facing). Otherwise your question How can I get the enemy to face in the direction of the player doesn't make much sense. Oct 30, 2014 at 8:45

Your task is to find the forward vector (the blue one) that is pointing towards the other player.

This vector can be approximated by finding the tangent at the player position on the shortest arc between the player and the enemy.

The tangent of the arc between the two players can be approximated using an approximated derivative (delta). So should we calculate it?

We use SLERP between P1 and P0 to find P, SLERP naturally maps to an arc, we don't need to explicitly represent an arc.

P is only a very small fraction away from P1.

P = SLERP( P1, P2, 0.001 );


Now we have two quaternions P1 and P in order to find the tangent we need to convert them to 3D vectors, in other words positions.

Once P1 and P are positions. We can now calculate deltaP.

The direction vector is actually the normalized version of deltaP

vec3 deltaP = normalize (Pvec - P1vec);


Now we have a direction vector. We only need to convert it to a rotation matrix/quaternion. In this case you need an extra matrix or quaternion to track the local orientation. You can assume your forward vector is forward=vec(0,0,1), up = vec(0,1,0) and vec(1,0,0) is your right vector.

Converting a direction vector to a quaternion (again you should have a reference) is little bit of work. You can find this function here.