Selaa lähdekoodia

fix AudioListener3D not tracking self velocity for doppler

Roy Berardo 2 kuukautta sitten
vanhempi
commit
769795f54a

+ 17 - 0
doc/classes/AudioListener3D.xml

@@ -35,4 +35,21 @@
 			</description>
 		</method>
 	</methods>
+	<members>
+		<member name="doppler_tracking" type="int" setter="set_doppler_tracking" getter="get_doppler_tracking" enum="AudioListener3D.DopplerTracking" default="0">
+			If not [constant DOPPLER_TRACKING_DISABLED], this listener will simulate the [url=https://en.wikipedia.org/wiki/Doppler_effect]Doppler effect[/url] for objects changed in particular [code]_process[/code] methods.
+			[b]Note:[/b] The Doppler effect will only be heard on [AudioStreamPlayer3D]s if [member AudioStreamPlayer3D.doppler_tracking] is not set to [constant AudioStreamPlayer3D.DOPPLER_TRACKING_DISABLED].
+		</member>
+	</members>
+	<constants>
+		<constant name="DOPPLER_TRACKING_DISABLED" value="0" enum="DopplerTracking">
+			Disables [url=https://en.wikipedia.org/wiki/Doppler_effect]Doppler effect[/url] simulation (default).
+		</constant>
+		<constant name="DOPPLER_TRACKING_IDLE_STEP" value="1" enum="DopplerTracking">
+			Simulate [url=https://en.wikipedia.org/wiki/Doppler_effect]Doppler effect[/url] by tracking positions of objects that are changed in [code]_process[/code]. Changes in the relative velocity of this listener compared to those objects affect how audio is perceived (changing the audio's [member AudioStreamPlayer3D.pitch_scale]).
+		</constant>
+		<constant name="DOPPLER_TRACKING_PHYSICS_STEP" value="2" enum="DopplerTracking">
+			Simulate [url=https://en.wikipedia.org/wiki/Doppler_effect]Doppler effect[/url] by tracking positions of objects that are changed in [code]_physics_process[/code]. Changes in the relative velocity of this listener compared to those objects affect how audio is perceived (changing the audio's [member AudioStreamPlayer3D.pitch_scale]).
+		</constant>
+	</constants>
 </class>

+ 1 - 0
doc/classes/AudioStreamPlayer3D.xml

@@ -74,6 +74,7 @@
 		</member>
 		<member name="doppler_tracking" type="int" setter="set_doppler_tracking" getter="get_doppler_tracking" enum="AudioStreamPlayer3D.DopplerTracking" default="0">
 			Decides in which step the Doppler effect should be calculated.
+			[b]Note:[/b] If [member doppler_tracking] is not [constant DOPPLER_TRACKING_DISABLED] but the current [Camera3D]/[AudioListener3D] has doppler tracking disabled, the Doppler effect will be heard but will not take the movement of the current listener into account. If accurate Doppler effect is desired, doppler tracking should be enabled on both the [AudioStreamPlayer3D] and the current [Camera3D]/[AudioListener3D].
 		</member>
 		<member name="emission_angle_degrees" type="float" setter="set_emission_angle" getter="get_emission_angle" default="45.0">
 			The angle in which the audio reaches a listener unattenuated.

+ 1 - 0
doc/classes/Camera3D.xml

@@ -175,6 +175,7 @@
 		</member>
 		<member name="doppler_tracking" type="int" setter="set_doppler_tracking" getter="get_doppler_tracking" enum="Camera3D.DopplerTracking" default="0">
 			If not [constant DOPPLER_TRACKING_DISABLED], this camera will simulate the [url=https://en.wikipedia.org/wiki/Doppler_effect]Doppler effect[/url] for objects changed in particular [code]_process[/code] methods.
+			[b]Note:[/b] The Doppler effect will only be heard on [AudioStreamPlayer3D]s if [member AudioStreamPlayer3D.doppler_tracking] is not set to [constant AudioStreamPlayer3D.DOPPLER_TRACKING_DISABLED].
 		</member>
 		<member name="environment" type="Environment" setter="set_environment" getter="get_environment">
 			The [Environment] to use for this camera.

+ 38 - 0
scene/3d/audio_listener_3d.cpp

@@ -88,6 +88,9 @@ void AudioListener3D::_notification(int p_what) {
 
 		case NOTIFICATION_TRANSFORM_CHANGED: {
 			_request_listener_update();
+			if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {
+				velocity_tracker->update_position(get_global_transform().origin);
+			}
 		} break;
 
 		case NOTIFICATION_EXIT_WORLD: {
@@ -140,15 +143,50 @@ bool AudioListener3D::is_current() const {
 	}
 }
 
+void AudioListener3D::set_doppler_tracking(DopplerTracking p_tracking) {
+	if (doppler_tracking == p_tracking) {
+		return;
+	}
+
+	doppler_tracking = p_tracking;
+	if (p_tracking != DOPPLER_TRACKING_DISABLED) {
+		velocity_tracker->set_track_physics_step(doppler_tracking == DOPPLER_TRACKING_PHYSICS_STEP);
+		if (is_inside_tree()) {
+			velocity_tracker->reset(get_global_transform().origin);
+		}
+	}
+}
+
+AudioListener3D::DopplerTracking AudioListener3D::get_doppler_tracking() const {
+	return doppler_tracking;
+}
+
 void AudioListener3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("make_current"), &AudioListener3D::make_current);
 	ClassDB::bind_method(D_METHOD("clear_current"), &AudioListener3D::clear_current);
 	ClassDB::bind_method(D_METHOD("is_current"), &AudioListener3D::is_current);
 	ClassDB::bind_method(D_METHOD("get_listener_transform"), &AudioListener3D::get_listener_transform);
+	ClassDB::bind_method(D_METHOD("set_doppler_tracking", "mode"), &AudioListener3D::set_doppler_tracking);
+	ClassDB::bind_method(D_METHOD("get_doppler_tracking"), &AudioListener3D::get_doppler_tracking);
+
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "doppler_tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Physics"), "set_doppler_tracking", "get_doppler_tracking");
+
+	BIND_ENUM_CONSTANT(DOPPLER_TRACKING_DISABLED);
+	BIND_ENUM_CONSTANT(DOPPLER_TRACKING_IDLE_STEP);
+	BIND_ENUM_CONSTANT(DOPPLER_TRACKING_PHYSICS_STEP);
+}
+
+Vector3 AudioListener3D::get_doppler_tracked_velocity() const {
+	if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {
+		return velocity_tracker->get_tracked_linear_velocity();
+	} else {
+		return Vector3();
+	}
 }
 
 AudioListener3D::AudioListener3D() {
 	set_notify_transform(true);
+	velocity_tracker.instantiate();
 }
 
 AudioListener3D::~AudioListener3D() {

+ 27 - 10
scene/3d/audio_listener_3d.h

@@ -31,10 +31,32 @@
 #pragma once
 
 #include "scene/3d/node_3d.h"
+#include "scene/3d/velocity_tracker_3d.h"
 
 class AudioListener3D : public Node3D {
 	GDCLASS(AudioListener3D, Node3D);
 
+public:
+	enum DopplerTracking {
+		DOPPLER_TRACKING_DISABLED,
+		DOPPLER_TRACKING_IDLE_STEP,
+		DOPPLER_TRACKING_PHYSICS_STEP,
+	};
+
+	void make_current();
+	void clear_current();
+	bool is_current() const;
+
+	virtual Transform3D get_listener_transform() const;
+
+	void set_doppler_tracking(DopplerTracking p_tracking);
+	DopplerTracking get_doppler_tracking() const;
+
+	Vector3 get_doppler_tracked_velocity() const;
+
+	AudioListener3D();
+	~AudioListener3D();
+
 private:
 	bool force_change = false;
 	bool current = false;
@@ -44,6 +66,9 @@ private:
 	friend class Viewport;
 	void _update_audio_listener_state();
 
+	DopplerTracking doppler_tracking = DOPPLER_TRACKING_DISABLED;
+	Ref<VelocityTracker3D> velocity_tracker;
+
 protected:
 	void _update_listener();
 	virtual void _request_listener_update();
@@ -54,14 +79,6 @@ protected:
 	void _notification(int p_what);
 
 	static void _bind_methods();
-
-public:
-	void make_current();
-	void clear_current();
-	bool is_current() const;
-
-	virtual Transform3D get_listener_transform() const;
-
-	AudioListener3D();
-	~AudioListener3D();
 };
+
+VARIANT_ENUM_CAST(AudioListener3D::DopplerTracking);

+ 3 - 3
scene/3d/audio_stream_player_3d.cpp

@@ -397,13 +397,11 @@ Vector<AudioFrame> AudioStreamPlayer3D::_update_panning() {
 			continue;
 		}
 
-		bool listener_is_camera = true;
 		Node3D *listener_node = camera;
 
 		AudioListener3D *listener = vp->get_audio_listener_3d();
 		if (listener) {
 			listener_node = listener;
-			listener_is_camera = false;
 		}
 
 		Vector3 local_pos = listener_node->get_global_transform().orthonormalized().affine_inverse().xform(global_pos);
@@ -507,7 +505,9 @@ Vector<AudioFrame> AudioStreamPlayer3D::_update_panning() {
 		if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {
 			Vector3 listener_velocity;
 
-			if (listener_is_camera) {
+			if (listener) {
+				listener_velocity = listener->get_doppler_tracked_velocity();
+			} else {
 				listener_velocity = camera->get_doppler_tracked_velocity();
 			}