diff --git a/docs/api/en/helpers/PositionalAudioHelper.html b/docs/api/en/helpers/PositionalAudioHelper.html
new file mode 100644
index 00000000000000..61b1ff7ce6d5c2
--- /dev/null
+++ b/docs/api/en/helpers/PositionalAudioHelper.html
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+ [page:Object3D] →
+
+ [name]
+
+ This helper displays the directional cone of a [page:PositionalAudio].
+
+ Example
+
+ [example:webaudio_orientation webaudio / orientation ]
+
+ Code Example
+
+var positionalAudio = new THREE.PositionalAudio( listener );
+positionalAudio.setDirectionalCone( 180, 230, 0.1 );
+
+var helper = new PositionalAudioHelper( positionalAudio );
+positionalAudio.add( helper );
+
+
+
+ Constructor
+
+ [name]( [param:PositionalAudio audio], [param:Number range] )
+
+ [page:PositionalAudio audio] -- The [page:PositionalAudio] to be visualized.
+
+ [page:Number range] -- (optional) The range of the directional cone.
+
+ [page:Number divisionsInnerAngle] -- (optional) The amount of divisions of the inner part of the directional cone.
+
+ [page:Number divisionsOuterAngle] -- (optional) The amount of divisions of the outer part of the directional cone.
+
+
+
+ Properties
+ See the base [page:Object3D] class for common properties.
+
+ [property:PositionalAudio audio]
+ [page:PositionalAudio] to be visualized.
+
+ [property:Number range]
+ The range of the directional cone.
+
+ [property:Number divisionsInnerAngle]
+ The amount of divisions of the inner part of the directional cone.
+
+ [property:Number divisionsOuterAngle]
+ The amount of divisions of the outer part of the directional cone.
+
+ Methods
+ See the base [page:Object3D] class for common methods.
+
+ [method:null dispose]()
+ Disposes of the helper.
+
+ [method:null update]()
+ Updates the helper.
+
+ Source
+
+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+
+
diff --git a/docs/api/zh/helpers/PositionalAudioHelper.html b/docs/api/zh/helpers/PositionalAudioHelper.html
new file mode 100644
index 00000000000000..61b1ff7ce6d5c2
--- /dev/null
+++ b/docs/api/zh/helpers/PositionalAudioHelper.html
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+ [page:Object3D] →
+
+ [name]
+
+ This helper displays the directional cone of a [page:PositionalAudio].
+
+ Example
+
+ [example:webaudio_orientation webaudio / orientation ]
+
+ Code Example
+
+var positionalAudio = new THREE.PositionalAudio( listener );
+positionalAudio.setDirectionalCone( 180, 230, 0.1 );
+
+var helper = new PositionalAudioHelper( positionalAudio );
+positionalAudio.add( helper );
+
+
+
+ Constructor
+
+ [name]( [param:PositionalAudio audio], [param:Number range] )
+
+ [page:PositionalAudio audio] -- The [page:PositionalAudio] to be visualized.
+
+ [page:Number range] -- (optional) The range of the directional cone.
+
+ [page:Number divisionsInnerAngle] -- (optional) The amount of divisions of the inner part of the directional cone.
+
+ [page:Number divisionsOuterAngle] -- (optional) The amount of divisions of the outer part of the directional cone.
+
+
+
+ Properties
+ See the base [page:Object3D] class for common properties.
+
+ [property:PositionalAudio audio]
+ [page:PositionalAudio] to be visualized.
+
+ [property:Number range]
+ The range of the directional cone.
+
+ [property:Number divisionsInnerAngle]
+ The amount of divisions of the inner part of the directional cone.
+
+ [property:Number divisionsOuterAngle]
+ The amount of divisions of the outer part of the directional cone.
+
+ Methods
+ See the base [page:Object3D] class for common methods.
+
+ [method:null dispose]()
+ Disposes of the helper.
+
+ [method:null update]()
+ Updates the helper.
+
+ Source
+
+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+
+
diff --git a/docs/list.js b/docs/list.js
index 8e56f65219fb48..c375d7dfb85205 100644
--- a/docs/list.js
+++ b/docs/list.js
@@ -196,6 +196,7 @@ var list = {
"FaceNormalsHelper": "api/en/helpers/FaceNormalsHelper",
"GridHelper": "api/en/helpers/GridHelper",
"PolarGridHelper": "api/en/helpers/PolarGridHelper",
+ "PositionalAudioHelper": "api/en/helpers/PositionalAudioHelper",
"HemisphereLightHelper": "api/en/helpers/HemisphereLightHelper",
"PlaneHelper": "api/en/helpers/PlaneHelper",
"PointLightHelper": "api/en/helpers/PointLightHelper",
@@ -621,6 +622,7 @@ var list = {
"FaceNormalsHelper": "api/zh/helpers/FaceNormalsHelper",
"GridHelper": "api/zh/helpers/GridHelper",
"PolarGridHelper": "api/zh/helpers/PolarGridHelper",
+ "PositionalAudioHelper": "api/zh/helpers/PositionalAudioHelper",
"HemisphereLightHelper": "api/zh/helpers/HemisphereLightHelper",
"PlaneHelper": "api/zh/helpers/PlaneHelper",
"PointLightHelper": "api/zh/helpers/PointLightHelper",
diff --git a/examples/webaudio_orientation.html b/examples/webaudio_orientation.html
index 5ed6a374c43c05..619f6a23bf0727 100644
--- a/examples/webaudio_orientation.html
+++ b/examples/webaudio_orientation.html
@@ -114,7 +114,7 @@
//
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 100 );
- camera.position.set( 0, 1, 2 );
+ camera.position.set( 3, 2, 3 );
var reflectionCube = new THREE.CubeTextureLoader()
.setPath( 'textures/cube/SwedishRoyalCastle/' )
@@ -151,7 +151,7 @@
mesh.receiveShadow = true;
scene.add( mesh );
- var grid = new THREE.GridHelper( 50, 50, 0x444444, 0x444444 );
+ var grid = new THREE.GridHelper( 50, 50, 0x888888, 0x888888 );
scene.add( grid );
//
@@ -165,7 +165,10 @@
var positionalAudio = new THREE.PositionalAudio( listener );
positionalAudio.setMediaElementSource( audioElement );
positionalAudio.setRefDistance( 1 );
- positionalAudio.setDirectionalCone( 210, 230, 0.1 );
+ positionalAudio.setDirectionalCone( 180, 230, 0.1 );
+
+ var helper = new THREE.PositionalAudioHelper( positionalAudio, 0.1 );
+ positionalAudio.add( helper );
//
diff --git a/src/Three.d.ts b/src/Three.d.ts
index 0901252240f9ac..01000302a89357 100644
--- a/src/Three.d.ts
+++ b/src/Three.d.ts
@@ -137,6 +137,7 @@ export { RectAreaLightHelper } from './helpers/RectAreaLightHelper';
export { HemisphereLightHelper } from './helpers/HemisphereLightHelper';
export { GridHelper } from './helpers/GridHelper';
export { PolarGridHelper } from './helpers/PolarGridHelper';
+export { PositionalAudioHelper } from './helpers/PositionalAudioHelper';
export { FaceNormalsHelper } from './helpers/FaceNormalsHelper';
export { DirectionalLightHelper } from './helpers/DirectionalLightHelper';
export { CameraHelper } from './helpers/CameraHelper';
diff --git a/src/Three.js b/src/Three.js
index bff7cf76960e20..96ddb030225731 100644
--- a/src/Three.js
+++ b/src/Three.js
@@ -131,6 +131,7 @@ export { RectAreaLightHelper } from './helpers/RectAreaLightHelper.js';
export { HemisphereLightHelper } from './helpers/HemisphereLightHelper.js';
export { GridHelper } from './helpers/GridHelper.js';
export { PolarGridHelper } from './helpers/PolarGridHelper.js';
+export { PositionalAudioHelper } from './helpers/PositionalAudioHelper.js';
export { FaceNormalsHelper } from './helpers/FaceNormalsHelper.js';
export { DirectionalLightHelper } from './helpers/DirectionalLightHelper.js';
export { CameraHelper } from './helpers/CameraHelper.js';
diff --git a/src/helpers/PositionalAudioHelper.d.ts b/src/helpers/PositionalAudioHelper.d.ts
new file mode 100644
index 00000000000000..3bccf84c09e389
--- /dev/null
+++ b/src/helpers/PositionalAudioHelper.d.ts
@@ -0,0 +1,14 @@
+import { PositionalAudio } from './../audio/PositionalAudio';
+import { Line } from './../objects/Line';
+
+export class PositionalAudioHelper extends Line {
+ constructor(audio: PositionalAudio, range?: number, divisionsInnerAngle?: number, divisionsOuterAngle?: number);
+
+ audio: PositionalAudio;
+ range: number;
+ divisionsInnerAngle: number;
+ divisionsOuterAngle: number;
+
+ dispose(): void;
+ update(): void;
+}
diff --git a/src/helpers/PositionalAudioHelper.js b/src/helpers/PositionalAudioHelper.js
new file mode 100644
index 00000000000000..2826e8b5cd7df6
--- /dev/null
+++ b/src/helpers/PositionalAudioHelper.js
@@ -0,0 +1,108 @@
+/**
+ * @author Mugen87 / http://github.com/Mugen87
+ */
+
+import { BufferGeometry } from '../core/BufferGeometry.js';
+import { BufferAttribute } from '../core/BufferAttribute.js';
+import { LineBasicMaterial } from '../materials/LineBasicMaterial.js';
+import { Line } from '../objects/Line.js';
+import { _Math } from '../math/Math.js';
+
+function PositionalAudioHelper( audio, range, divisionsInnerAngle, divisionsOuterAngle ) {
+
+ this.audio = audio;
+ this.range = range || 1;
+ this.divisionsInnerAngle = divisionsOuterAngle || 16;
+ this.divisionsOuterAngle = divisionsOuterAngle || 2;
+
+ var geometry = new BufferGeometry();
+ var divisions = this.divisionsInnerAngle + this.divisionsOuterAngle * 2;
+ var positions = new Float32Array( ( divisions * 3 + 3 ) * 3 );
+ geometry.addAttribute( 'position', new BufferAttribute( positions, 3 ) );
+
+ var materialInnerAngle = new LineBasicMaterial( { color: 0x00ff00 } );
+ var materialOuterAngle = new LineBasicMaterial( { color: 0xffff00 } );
+
+ Line.call( this, geometry, [ materialOuterAngle, materialInnerAngle ] );
+
+ this.update();
+
+}
+
+PositionalAudioHelper.prototype = Object.create( Line.prototype );
+PositionalAudioHelper.prototype.constructor = PositionalAudioHelper;
+
+PositionalAudioHelper.prototype.update = function () {
+
+ var audio = this.audio;
+ var range = this.range;
+ var divisionsInnerAngle = this.divisionsInnerAngle;
+ var divisionsOuterAngle = this.divisionsOuterAngle;
+
+ var coneInnerAngle = _Math.degToRad( audio.panner.coneInnerAngle );
+ var coneOuterAngle = _Math.degToRad( audio.panner.coneOuterAngle );
+
+ var halfConeInnerAngle = coneInnerAngle / 2;
+ var halfConeOuterAngle = coneOuterAngle / 2;
+
+ var start = 0;
+ var count = 0;
+ var i, stride;
+
+ var geometry = this.geometry;
+ var positionAttribute = geometry.attributes.position;
+
+ geometry.clearGroups();
+
+ //
+
+ function generateSegment( from, to, divisions, materialIndex ) {
+
+ var step = ( to - from ) / divisions;
+
+ positionAttribute.setXYZ( start, 0, 0, 0 );
+ count ++;
+
+ for ( i = from; i < to; i += step ) {
+
+ stride = start + count;
+
+ positionAttribute.setXYZ( stride, Math.sin( i ) * range, 0, Math.cos( i ) * range );
+ positionAttribute.setXYZ( stride + 1, Math.sin( Math.min( i + step, to ) ) * range, 0, Math.cos( Math.min( i + step, to ) ) * range );
+ positionAttribute.setXYZ( stride + 2, 0, 0, 0 );
+
+ count += 3;
+
+ }
+
+ geometry.addGroup( start, count, materialIndex );
+
+ start += count;
+ count = 0;
+
+ }
+
+ //
+
+ generateSegment( - halfConeOuterAngle, - halfConeInnerAngle, divisionsOuterAngle, 0 );
+ generateSegment( - halfConeInnerAngle, halfConeInnerAngle, divisionsInnerAngle, 1 );
+ generateSegment( halfConeInnerAngle, halfConeOuterAngle, divisionsOuterAngle, 0 );
+
+ //
+
+ positionAttribute.needsUpdate = true;
+
+ if ( coneInnerAngle === coneOuterAngle ) this.material[ 0 ].visible = false;
+
+};
+
+PositionalAudioHelper.prototype.dispose = function () {
+
+ this.geometry.dispose();
+ this.material[ 0 ].dispose();
+ this.material[ 1 ].dispose();
+
+};
+
+
+export { PositionalAudioHelper };