Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Positional audio isn't correct #4

Open
icculus opened this issue Aug 14, 2021 · 5 comments
Open

Positional audio isn't correct #4

icculus opened this issue Aug 14, 2021 · 5 comments
Assignees

Comments

@icculus
Copy link
Owner

icculus commented Aug 14, 2021

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 #2 (comment)

@icculus icculus self-assigned this Aug 14, 2021
@adahlkvist-feral
Copy link

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:

  1. Take the position vector and subtract the listener position, store in a vector called V
  2. Let a = Dot(V, Up)
  3. Remove upwards component of V by doing V = V - a * Up
  4. V will now lie in the plane with your "at" vector
  5. Use the cross product to calculate the angle.

@adahlkvist-feral
Copy link

		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;
		}

@adahlkvist-feral
Copy link

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.

@adahlkvist-feral
Copy link

adahlkvist-feral commented Apr 12, 2023

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;
	}
	```

@ericoporto
Copy link
Contributor

A person made a fork with an alternative calculation that appears related to this

Helco@f5db374

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants