Positional audio isn't correct
As for the transition: yes, this code also has problems. It's already an extremely naive approach, and on top of that, there's clearly some incorrect math somewhere causing that jarring transition. Fixing that is on the TODO list (but I'm going to split this comment into a second bug so there's an actual place we're tracking that change).
Originally posted by @icculus in https://github.com/icculus/mojoAL/issues/2#issuecomment-898814119
I believe you are overcomplicating your approach to calculating the angle between the "at" and the "position".
I think the correct way is to do the following:
- Take the position vector and subtract the listener position, store in a vector called V
- Let a = Dot(V, Up)
- Remove upwards component of V by doing V = V - a * Up
- V will now lie in the plane with your "at" vector
- Use the cross product to calculate the angle.
ALfloat V[3];
SDL_memcpy(V, position, sizeof(V));
ALfloat a = dotproduct(V, up);
V[0] -= a * up[0];
V[1] -= a * up[1];
V[2] -= a * up[2];
ALfloat mags = magnitude(at) * magnitude(V);
ALfloat dot = dotproduct(at, V);
radians = (mags == 0.0f) ? 0.0f : SDL_acosf(dot / mags);
if (dot < 0.0f)
{
radians = -radians;
}
Actually the above code might not always work, you need to clamp the thing you put into SDL_acosf from -1 to 1 otherwise you get NaN issues when the float rounding goes ever so slightly above 1 sometimes.
Upon further reflection, I think the right code would look like this:
// Get position relative to the listener
ALfloat V[3];
SDL_memcpy(V, position, sizeof(V));
ALfloat a = dotproduct(V, up);
// Remove upwards component so it lies completely within the horizontal plane.
V[0] -= a * up[0];
V[1] -= a * up[1];
V[2] -= a * up[2];
// Calculate angle
ALfloat mags = magnitude(at) * magnitude(V);
ALfloat cosAngle = (mags == 0.0f) ? 0.0f : (dotproduct(at, V) / mags);
cosAngle = fmaxf(fminf(cosAngle, 1.0f), -1.0f);
radians = SDL_acosf(cosAngle);
// Get "right" vector
ALfloat R[3];
xyzzy(R, at, up);
// If it's facing right, then it's positive, if it's facing left, then it's negative.
if (dotproduct(R,V) < 0.0f)
{
radians = -radians;
}
```
A person made a fork with an alternative calculation that appears related to this
https://github.com/Helco/mojoAL/commit/f5db374adc0d1254876450ca97a259ef9990922b