I am trying to figure out how an enemy should turn so that he is facing the player. The world is flat, so i can concentrate on only a plane approach so far. Only relevant rotation your be the one arround the y-axis in this case.
I have these situations:
Situation A:
[java]_______
| E | <= enemy
| / | <= enemy is looking exactly 45° down right
| P | <= player is approachin from bottom at roughly 30° to the view direction of enemy
-------[/java]
Situation B:
[java]_______
| E| <= enemy
| P / | <= enemy is looking exactly 45° down right
| | player is approachin from left at roughly 30° to the view direction of enemy
-------[/java]
I am trying to figure out the angle the enemy has to turn now. I tried several approaches but the results are somewhat strange.
The code i have to figure it out:
[java]
Quaternion currentRot = enemy.getLocalRotation();
Vector3f[] initialAxes = new Vector3f[3];
currentRot.toAxes(initialAxes);
Plane forward = new Plane(initialAxes[0], 0);
Plane sidewards = new Plane(initialAxes[2], 0);
if (forward.whichSide(player.getLocalTranslation()) == Plane.Side.Positive) {
System.out.println("Player is in front of enemy.");
} else if (forward.whichSide(player.getLocalTranslation()) == Plane.Side.None) {
System.out.println("Player is next to enemy.");
} else {
System.out.println("Player is behind of enemy.");
}
if (sidewards.whichSide(player.getLocalTranslation()) == Plane.Side.Negative) {
System.out.println("Player is left of enemy.");
} else if (sidewards.whichSide(player.getLocalTranslation()) == Plane.Side.None) {
System.out.println("Player is next to enemy.");
} else {
System.out.println("Player right of enemy.");
}
Quaternion wantedRot = currentRot.clone();
wantedRot.lookAt(player.getLocalTranslation(), Vector3f.UNIT_Y);
float angle1 = currentRot.getY() - wantedRot.getY();
System.out.println("Simple angle towards player: " + angle1 * FastMath.RAD_TO_DEG);
float angle2 = FastMath.acos(currentRot.dot(wantedRot));
System.out.println("Dotproduct angle towards player: " + angle2 * FastMath.RAD_TO_DEG);
Quaternion delta = currentRot.inverse().mult(wantedRot);
System.out.println("Deltaquaternion angle towards player: " + delta.getY() * FastMath.RAD_TO_DEG);
Vector3f enemyPosition = enemy.getLocalTranslation();
Vector3f enemyForwardPoint = enemy.getLocalRotation().mult(new Vector3f(0, 0, 1));
Vector3f playerPosition = player.getLocalTranslation();
Vector3f viewDirection = enemyForwardPoint.subtract(enemyPosition).normalize();
Vector3f playerDirection = playerPosition.subtract(enemyPosition).normalize();
float angle3 = FastMath.acos(viewDirection.dot(playerDirection));
System.out.println("Trigonometry angle towards player: " + delta.getY() * FastMath.RAD_TO_DEG);
[/java]
In situation A the output is:
Player is in front of enemy. Player is left of enemy. Simple angle towards player: 39.604862 Dotproduct angle towards player: 99.04719 Deltaquaternion angle towards player: -56.582966 Trigonometry angle towards player: 23.150555
In situation B the output is:
Player is behind of enemy. Player is left of enemy. Simple angle towards player: 23.71655 Dotproduct angle towards player: 81.83965 Deltaquaternion angle towards player: -56.71563 Trigonometry angle towards player: 20.338633
First of all its strange that in B the planes are somewhat turned arround so now the player is seen behind and left wich is not true,
Then the calculated angles have me at a loss, in theory they all should give the same value, but each one of them is different. The simple one looks like the one that is the most realistic, altho it is not negative in situation B as i excpected.
Are my calculations wrong somehow ?
Is there an easy and simple way to determine the rotation from the current view to a certain point ?
What i need to know is if the player is left or right of enemy and at what angle so i can turn the enemy by that angle to face the player.
Also i need to know if the player is behind or in front of the enemy so in one case enemy can start walking forward, in other case walking backward and inverse rotation to turn.