Przeglądaj źródła

Merge pull request #2432 from capdevon/capdevon-TestAudioDirectional

jme3-examples: add TestAudioDirectional class
Ryan McDonough 4 miesięcy temu
rodzic
commit
3cc16ab79d

+ 141 - 0
jme3-examples/src/main/java/jme3test/audio/TestAudioDirectional.java

@@ -0,0 +1,141 @@
+package jme3test.audio;
+
+import com.jme3.app.SimpleApplication;
+import com.jme3.audio.AudioData;
+import com.jme3.audio.AudioNode;
+import com.jme3.environment.util.BoundingSphereDebug;
+import com.jme3.input.KeyInput;
+import com.jme3.input.controls.ActionListener;
+import com.jme3.input.controls.KeyTrigger;
+import com.jme3.input.controls.Trigger;
+import com.jme3.material.Material;
+import com.jme3.math.ColorRGBA;
+import com.jme3.math.FastMath;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.Mesh;
+import com.jme3.scene.Node;
+import com.jme3.scene.Spatial;
+import com.jme3.scene.debug.Arrow;
+import com.jme3.scene.debug.Grid;
+import com.jme3.scene.shape.Line;
+
+/**
+ * @author capdevon
+ */
+public class TestAudioDirectional extends SimpleApplication implements ActionListener {
+
+    public static void main(String[] args) {
+        TestAudioDirectional app = new TestAudioDirectional();
+        app.start();
+    }
+
+    private AudioNode audioSource;
+    private final Vector3f tempDirection = new Vector3f();
+    private boolean rotationEnabled = true;
+
+    @Override
+    public void simpleInitApp() {
+        configureCamera();
+
+        audioSource = new AudioNode(assetManager,
+                "Sound/Environment/Ocean Waves.ogg", AudioData.DataType.Buffer);
+        audioSource.setLooping(true);
+        audioSource.setPositional(true);
+        audioSource.setMaxDistance(100);
+        audioSource.setRefDistance(5);
+        audioSource.setDirectional(true);
+//        audioSource.setOuterGain(0.2f); // Volume outside the cone is 20% of the inner volume (Not Supported by jME)
+        audioSource.setInnerAngle(30); // 30-degree cone (15 degrees on each side of the direction)
+        audioSource.setOuterAngle(90); // 90-degree cone (45 degrees on each side of the direction)
+        audioSource.play();
+
+        // just a green sphere to mark the spot
+        Geometry sphere =  BoundingSphereDebug.createDebugSphere(assetManager);
+        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+        mat.setColor("Color", ColorRGBA.Green);
+        sphere.setMaterial(mat);
+        sphere.setLocalScale(0.5f);
+        audioSource.attachChild(sphere);
+
+        float angleIn = audioSource.getInnerAngle() * FastMath.DEG_TO_RAD;
+        float angleOut = audioSource.getOuterAngle() * FastMath.DEG_TO_RAD;
+        Vector3f forwardDir = audioSource.getWorldRotation().mult(Vector3f.UNIT_Z);
+
+        audioSource.attachChild(createFOV(angleIn, 20f));
+        audioSource.attachChild(createFOV(angleOut, 20f));
+        audioSource.attachChild(makeShape("ZAxis", new Arrow(forwardDir.mult(5)), ColorRGBA.Blue));
+        rootNode.attachChild(audioSource);
+
+        Geometry grid = makeShape("DebugGrid", new Grid(21, 21, 2), ColorRGBA.Gray);
+        grid.center().move(0, 0, 0);
+        rootNode.attachChild(grid);
+
+        registerInputMappings();
+    }
+
+    @Override
+    public void simpleUpdate(float tpf) {
+        if (rotationEnabled) {
+            // Example: Rotate the audio node
+            audioSource.rotate(0, tpf * 0.5f, 0);
+            audioSource.setDirection(audioSource.getWorldRotation().mult(Vector3f.UNIT_Z, tempDirection));
+        }
+    }
+
+    @Override
+    public void onAction(String name, boolean isPressed, float tpf) {
+        if (!isPressed) return;
+
+        if (name.equals("toggleDirectional")) {
+            boolean directional = !audioSource.isDirectional();
+            audioSource.setDirectional(directional);
+            System.out.println("directional: " + directional);
+
+        } else if (name.equals("toggleRotationEnabled")) {
+            rotationEnabled = !rotationEnabled;
+            System.out.println("rotationEnabled: " + rotationEnabled);
+        }
+    }
+
+    private void registerInputMappings() {
+        addMapping("toggleDirectional", new KeyTrigger(KeyInput.KEY_SPACE));
+        addMapping("toggleRotationEnabled", new KeyTrigger(KeyInput.KEY_P));
+    }
+
+    private void addMapping(String mappingName, Trigger... triggers) {
+        inputManager.addMapping(mappingName, triggers);
+        inputManager.addListener(this, mappingName);
+    }
+
+    private void configureCamera() {
+        flyCam.setMoveSpeed(25f);
+        flyCam.setDragToRotate(true);
+
+        cam.setLocation(new Vector3f(12, 5, 12));
+        cam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);
+    }
+
+    private Geometry makeShape(String name, Mesh mesh, ColorRGBA color) {
+        Geometry geo = new Geometry(name, mesh);
+        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+        mat.setColor("Color", color);
+        geo.setMaterial(mat);
+        return geo;
+    }
+
+    private Spatial createFOV(float angleRad, float extent) {
+        Vector3f origin = new Vector3f();
+        Node node = new Node("Cone");
+        Vector3f sx = dirFromAngle(angleRad/2).scaleAdd(extent, origin);
+        Vector3f dx = dirFromAngle(-angleRad/2).scaleAdd(extent, origin);
+        node.attachChild(makeShape("Line.SX", new Line(origin, sx), ColorRGBA.Red));
+        node.attachChild(makeShape("Line.DX", new Line(origin, dx), ColorRGBA.Red));
+
+        return node;
+    }
+
+    private Vector3f dirFromAngle(float angleRad) {
+        return new Vector3f(FastMath.sin(angleRad), 0, FastMath.cos(angleRad));
+    }
+}