Thanks for the advice. I finally worked the rotation out using the following code and after rereading the rotation around a point guide. Now I have a new problem. First I'll post the working rotation code in case it helps someone else. Next I'll post the new bug: the black hole effect at the poles.
// the node stays in the translation on the globe (but the model does not!)
Vector3f playerLocation = player.getLocalTranslation();
float playerDistanceFromCOTW = playerLocation.distance(centerOfTheWorld);
player.getLocalTranslation().multLocal(1 + ((GLOBE_RADIUS + 1) - playerDistanceFromCOTW) / (GLOBE_RADIUS+1));
// the player is rotated around the axis of where they are (must tilt the model to make it look right)
Quaternion q = player.getLocalRotation();
float angle = player.angle * FastMath.PI / 180;
q.fromAngleAxis(angle, playerLocation);
player.model.updateGeometricState(0, true);
// rotate the model to face th correct angle
quatA.loadIdentity();
quatB.loadIdentity();
// calculate the angles from the vector
xAngle = FastMath.asin(playerLocation.x/playerDistanceFromCOTW);
yAngle = FastMath.asin(playerLocation.y/playerDistanceFromCOTW);
zAngle = FastMath.asin(playerLocation.z/playerDistanceFromCOTW);
// change the model's rotation to point away from the globe
Quaternion qp = player.model.getLocalRotation();
// special cases for if z > 0 or z < 0
if (playerLocation.z >=0) {
quatA.fromAngleNormalAxis(FastMath.PI/2 - yAngle, Vector3f.UNIT_X);
quatB.fromAngleNormalAxis(xAngle, new Vector3f(0,0,-1));
} else {
quatA.fromAngleNormalAxis(FastMath.PI/2 - yAngle, new Vector3f(-1, 0, 0));
quatB.fromAngleNormalAxis(xAngle, new Vector3f(0,0,-1));
}
// now multiply
qp.loadIdentity();
qp.multLocal(quatA);
qp.multLocal(quatB);
I'm sure that the above code isn't optimal, but it seems to work pretty well. Now I have a different problem. As the player gets closer to the north or south poles they are more or less sucked in. I can not get the player to be able to run around the globe near either pole without the pole automatically sucking them in. If I run the player around elsewhere it is fine, but I think my movement math is a little off. Can anyone help? I think it has to do with using the y-axis as my reference point when calculating what direction is forward based on the player's current rotation.
Here is the player movement code. As before,
angle is an angle between 0 and 360 that gets updated as the left and right turn keys are pressed. Velocity is the same as in the flag rush tutorial, just a scalar that is either positive or negative based on if the forward or backward keys have been pressed.
// always going to move a unit of 0.25
float moveDistance = player.getVelocity() * tpf;
// move the player appropriately
Vector3f moveVector = player.getLocalTranslation();
// calculate the angle to y
Vector3f yIsUp = moveVector.mult(Vector3f.UNIT_Y);
// rotate about the axis -- seems to work well
rotationQuat.fromAngleAxis(player.angle*FastMath.DEG_TO_RAD, moveVector);
// calc the distance to the center of the world
float d = yIsUp.distance(Vector3f.ZERO);
yIsUp.normalizeLocal();
yIsUp.multLocal(MultiThreadGameState.GLOBE_RADIUS);
d = yIsUp.distance(Vector3f.ZERO);
// this vector is what I use as the 'forward' axis to move the player
Vector3f diff = moveVector.subtract(yIsUp);
diff.normalizeLocal().multLocal(moveDistance);
// rotate the vector around our axis
diff = rotationQuat.mult(diff);
// when crossing the y-axis flip rotation by 180 degrees to keep orientation.
if (moveVector.y > 0 && moveVector.y + diff.y < 0 || moveVector.y < 0 && moveVector.y + diff.y > 0) {
player.angle += 180;
}
// move the player the appropriate distance in the right direction
moveVector.addLocal(diff);
player.getLocalTranslation().set(moveVector);
My best guess is that I need to use more than just the y-axis when calculating the movement vector. I've played around with using the x-axis as well and adding 90 degrees to the rotation. It seems to work; however, the black hole effect still exists. Does anyone know how to modify the above code to avoid the black hole effect that I described?