Ahruman wrote:But surely it’s shooting using -fireDirectLaserShot
, and therefore should be shooting directly at the target (with an error of up to about 8°) regardless of relative orientation?
I always noticed random shots, even in 1.65. Probably I read the code with in my mind that it should be sometimes random. But re-reding the code it is intended to
always shoot in the global direction of the target. All code seems correct but I had my doubt if the calculation of the quaternion itself was always correct. So I added following code:
Code: Select all
Quaternion q_laser = kIdentityQuaternion;
Vector q_laser_cross = fast_cross_product(kBasisZVector, r_pos); // kBasisZVector is vectorForward of kIdentityQuaternion
double q_laser_angle = acosf(dot_product(kBasisZVector, r_pos));
quaternion_rotate_about_axis(&q_laser, q_laser_cross, -q_laser_angle); // rotate vectorForward to r_pos.
Quaternion q_laser2 = quaternion_rotation_between(r_pos, kBasisZVector);
OOLog(@"dumpState.thargoidEntity", @"quat1: %@, quat2: %@", QuaternionDescription(q_laser), QuaternionDescription(q_laser2));
q_laser2
is the way Oolite currently calculates the quaternion and
q_laser
is calculated by rotation of the identity quaternion. I logged both results before randomisation The result should be the same, but was not always:
Code: Select all
[dumpState.thargoidEntity] ShipEntity.m:7561: quat1: (0.794043 - 0.597819i - 0.110034j + 0k), quat2: (0.794043 - 0.597819i - 0.110034j + 0k)
[dumpState.thargoidEntity] ShipEntity.m:7561: quat1: (0.772979 - 0.627878i - 0.090952j + 0k), quat2: (0.772979 - 0.627879i - 0.090952j + 0k)
[dumpState.thargoidEntity] ShipEntity.m:7561: quat1: (0.722108 - 0.690482i - 0.0423704j + 0k), quat2: (0.722108 - 0.690482i - 0.0423704j + 0k)
[dumpState.thargoidEntity] ShipEntity.m:7561: quat1: (0.487414 - 0.835378i + 0.254108j + 0k), quat2: (1 + 0i + 0j + 0k)
[dumpState.thargoidEntity] ShipEntity.m:7561: quat1: (0.526448 + 0.816298i + 0.237717j + 0k), quat2: (0.526449 + 0.816298i + 0.237717j + 0k)
[dumpState.thargoidEntity] ShipEntity.m:7561: quat1: (0.5261 + 0.816444i + 0.237988j + 0k), quat2: (0.5261 + 0.816444i + 0.237988j + 0k)
[dumpState.thargoidEntity] ShipEntity.m:7561: quat1: (0.525694 + 0.81663i + 0.238248j + 0k), quat2: (0.525693 + 0.81663i + 0.238248j + 0k)
[dumpState.thargoidEntity] ShipEntity.m:7561: quat1: (0.525411 + 0.816741i + 0.23849j + 0k), quat2: (0.525411 + 0.816741i + 0.23849j + 0k)
[dumpState.thargoidEntity] ShipEntity.m:7561: quat1: (0.521813 + 0.821227i + 0.230861j + 0k), quat2: (0.521813 + 0.821227i + 0.230861j + 0k)
[dumpState.thargoidEntity] ShipEntity.m:7561: quat1: (0.515604 + 0.829072i + 0.216317j + 0k), quat2: (0.515604 + 0.829072i + 0.216317j + 0k)
[dumpState.thargoidEntity] ShipEntity.m:7561: quat1: (0.437887 + 0.898787i - 0.0208951j + 0k), quat2: (1 + 0i + 0j + 0k)
[dumpState.thargoidEntity] ShipEntity.m:7561: quat1: (0.360759 + 0.49472i - 0.790636j + 0k), quat2: (1 + 0i + 0j + 0k)
[dumpState.thargoidEntity] ShipEntity.m:7561: quat1: (0.553631 - 0.349388i - 0.755924j + 0k), quat2: (0.553631 - 0.349388i - 0.755924j + 0k)
[dumpState.thargoidEntity] ShipEntity.m:7561: quat1: (0.669551 - 0.491976i - 0.556472j + 0k), quat2: (0.669551 - 0.491976i - 0.556472j + 0k)
[dumpState.thargoidEntity] ShipEntity.m:7561: quat1: (0.732027 - 0.525676i - 0.433361j + 0k), quat2: (0.732027 - 0.525676i - 0.433361j + 0k)
[dumpState.thargoidEntity] ShipEntity.m:7561: quat1: (0.752756 - 0.530676i - 0.389539j + 0k), quat2: (0.752756 - 0.530676i - 0.389539j + 0k)
[dumpState.thargoidEntity] ShipEntity.m:7561: quat1: (0.763936 - 0.532033i - 0.36516j + 0k), quat2: (0.763936 - 0.532033i - 0.36516j + 0k)
[dumpState.thargoidEntity] ShipEntity.m:7561: quat1: (0.777968 - 0.533047i - 0.332607j + 0k), quat2: (0.777968 - 0.533047i - 0.332607j + 0k)
[dumpState.thargoidEntity] ShipEntity.m:7561: quat1: (0.77995 - 0.534211i - 0.326031j + 0k), quat2: (0.77995 - 0.534211i - 0.326031j + 0k)
[dumpState.thargoidEntity] ShipEntity.m:7561: quat1: (0.785578 - 0.539619i - 0.302784j + 0k), quat2: (0.785578 - 0.539619i - 0.302784j + 0k)
Sometimes the current code returns (1 + 0i + 0j + 0k) (the identity quaternion)
It happens here:
Code: Select all
Quaternion quaternion_rotation_between(Vector v0, Vector v1)
{
Quaternion q;
OOScalar s = sqrtf((1.0f + v0.x * v1.x + v0.y * v1.y + v0.z * v1.z) * 2.0f);
if (EXPECT(s))
{
OOScalar is = 1.0f / s;
q.x = (v0.y * v1.z - v0.z * v1.y) * is;
q.y = (v0.z * v1.x - v0.x * v1.z) * is;
q.z = (v0.x * v1.y - v0.y * v1.x) * is;
q.w = s * 0.5f;
}
else
{
// Is this actually a problem?
q = kIdentityQuaternion;
}
return q;
}
I think that
sqrtf((1.0f + v0.x * v1.x + v0.y * v1.y + v0.z * v1.z) * 2.0f)
is guaranteed to take the sqrt from a positive number. It can only be zero as lowest value but that would be very rare.