Skip to content

Commit f13c5d7

Browse files
authored
Merge pull request #14243 from Mugen87/dev12
PositionalAudio: Added orientation
2 parents c0e6692 + e053af0 commit f13c5d7

File tree

3 files changed

+262
-2
lines changed

3 files changed

+262
-2
lines changed

examples/files.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ var files = {
313313
],
314314
*/
315315
"webaudio": [
316+
"webaudio_orientation",
316317
"webaudio_sandbox",
317318
"webaudio_timing",
318319
"webaudio_visualizer"

examples/webaudio_orientation.html

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<title>three.js webaudio - orientation</title>
5+
<meta charset="utf-8">
6+
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
7+
<style>
8+
body {
9+
background:#777;
10+
padding:0;
11+
margin:0;
12+
overflow:hidden;
13+
font-family: Monospace;
14+
}
15+
16+
#info {
17+
position: absolute;
18+
z-index: 2;
19+
top: 0px;
20+
width: 100%;
21+
color: #ffffff;
22+
padding: 5px;
23+
24+
font-size:13px;
25+
text-align:center;
26+
font-weight: bold;
27+
}
28+
29+
a {
30+
color: #ffffff;
31+
}
32+
33+
#overlay {
34+
position: absolute;
35+
z-index: 1;
36+
top: 0;
37+
left: 0;
38+
width: 100%;
39+
height:100%;
40+
display: flex;
41+
align-items: center;
42+
justify-content: center;
43+
opacity: 1;
44+
background-color: #000000;
45+
color: #ffffff;
46+
}
47+
48+
#overlay > div {
49+
text-align: center;
50+
}
51+
52+
#overlay > div > button {
53+
height: 20px;
54+
width: 100px;
55+
background: transparent;
56+
color: #ffffff;
57+
outline: 1px solid #ffffff;
58+
border: 0px;
59+
cursor: pointer;
60+
}
61+
62+
#overlay > div > p {
63+
color: #777777;
64+
font-size: 12px;
65+
}
66+
67+
</style>
68+
69+
<script src="../build/three.js"></script>
70+
<script src="js/Detector.js"></script>
71+
<script src="js/controls/OrbitControls.js"></script>
72+
<script src="js/loaders/GLTFLoader.js"></script>
73+
74+
</head>
75+
<body>
76+
77+
<audio loop id="music" preload="auto" style="display: none">
78+
<source src="sounds/376737_Skullbeatz___Bad_Cat_Maste.ogg" type="audio/ogg">
79+
<source src="sounds/376737_Skullbeatz___Bad_Cat_Maste.mp3" type="audio/mpeg">
80+
</audio>
81+
82+
<div id="overlay">
83+
<div>
84+
<button id="startButton">Click to Play</button>
85+
<p>Automatic audio playback requires a user interaction.</p>
86+
</div>
87+
</div>
88+
<div id="container"></div>
89+
<div id="info">
90+
<a href="https://threejs.org" target="_blank" rel="noopener noreferrer">three.js</a> webaudio orientation |
91+
music by <a href="http://www.newgrounds.com/audio/listen/376737" target="_blank" rel="noopener noreferrer">skullbeatz</a>
92+
</div>
93+
94+
<script>
95+
96+
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
97+
98+
var scene, camera, renderer;
99+
100+
var startButton = document.getElementById( 'startButton' );
101+
startButton.addEventListener( 'click', init );
102+
103+
function init() {
104+
105+
var overlay = document.getElementById( 'overlay' );
106+
overlay.remove();
107+
108+
var container = document.getElementById( 'container' );
109+
110+
//
111+
112+
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 100 );
113+
camera.position.set( 0, 1, 2 );
114+
115+
var reflectionCube = new THREE.CubeTextureLoader()
116+
.setPath( 'textures/cube/SwedishRoyalCastle/' )
117+
.load( [ 'px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg' ] );
118+
reflectionCube.format = THREE.RGBFormat;
119+
120+
scene = new THREE.Scene();
121+
scene.background = new THREE.Color( 0xa0a0a0 );
122+
scene.fog = new THREE.Fog( 0xa0a0a0, 2, 20 );
123+
124+
//
125+
126+
light = new THREE.HemisphereLight( 0xffffff, 0x444444 );
127+
light.position.set( 0, 200, 0 );
128+
scene.add( light );
129+
130+
light = new THREE.DirectionalLight( 0xffffff );
131+
light.position.set( 0, 200, 100 );
132+
light.castShadow = true;
133+
light.shadow.camera.top = 180;
134+
light.shadow.camera.bottom = -100;
135+
light.shadow.camera.left = -120;
136+
light.shadow.camera.right = 120;
137+
scene.add( light );
138+
139+
//
140+
141+
var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 20, 20 ), new THREE.MeshPhongMaterial( { color: 0x999999, depthWrite: false } ) );
142+
mesh.rotation.x = - Math.PI / 2;
143+
mesh.receiveShadow = true;
144+
scene.add( mesh );
145+
146+
var grid = new THREE.GridHelper( 20, 20, 0x000000, 0x000000 );
147+
grid.material.opacity = 0.2;
148+
grid.material.transparent = true;
149+
scene.add( grid );
150+
151+
//
152+
153+
var audioLoader = new THREE.AudioLoader();
154+
155+
var listener = new THREE.AudioListener();
156+
camera.add( listener );
157+
158+
var audioElement = document.getElementById( 'music' );
159+
160+
var positionalAudio = new THREE.PositionalAudio( listener );
161+
positionalAudio.setMediaElementSource( audioElement );
162+
positionalAudio.setRefDistance( 1 );
163+
164+
// configure directionality cone, see https://developer.mozilla.org/en-US/docs/Web/API/PannerNode
165+
166+
positionalAudio.panner.coneInnerAngle = 210;
167+
positionalAudio.panner.coneOuterAngle = 230;
168+
positionalAudio.panner.coneOuterGain = 0.1;
169+
170+
//
171+
172+
var gltfLoader = new THREE.GLTFLoader();
173+
gltfLoader.load( 'models/gltf/BoomBox/glTF-Binary/BoomBox.glb', function( gltf ) {
174+
175+
boomBox = gltf.scene;
176+
boomBox.position.set( 0, 0.2, 0 );
177+
boomBox.scale.set( 20, 20, 20 );
178+
179+
boomBox.traverse( function( object ) {
180+
181+
if ( object.isMesh ) {
182+
183+
object.material.envMap = reflectionCube;
184+
object.geometry.rotateY( - Math.PI );
185+
186+
}
187+
188+
} );
189+
190+
audioElement.play();
191+
boomBox.add( positionalAudio );
192+
scene.add( boomBox );
193+
animate();
194+
195+
} );
196+
197+
// sound is damped behind this wall
198+
199+
var wallGeometry = new THREE.BoxBufferGeometry( 2, 1, 0.1 );
200+
var wallMaterial = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
201+
202+
var wall = new THREE.Mesh( wallGeometry, wallMaterial );
203+
wall.position.set( 0, 0.5, - 0.5 );
204+
scene.add( wall );
205+
206+
207+
//
208+
209+
renderer = new THREE.WebGLRenderer( { antialias: true } );
210+
renderer.setSize( window.innerWidth, window.innerHeight );
211+
renderer.setPixelRatio( window.devicePixelRatio );
212+
container.appendChild( renderer.domElement );
213+
214+
renderer.gammaOutput = true;
215+
216+
//
217+
218+
var controls = new THREE.OrbitControls( camera, renderer.domElement );
219+
controls.target.set( 0, 0.1, 0 );
220+
controls.update();
221+
controls.minDistance = 0.5;
222+
controls.maxDistance = 10;
223+
controls.maxPolarAngle = 0.5 * Math.PI;
224+
225+
//
226+
227+
window.addEventListener( 'resize', onWindowResize, false );
228+
229+
}
230+
231+
function onWindowResize( event ) {
232+
233+
camera.aspect = window.innerWidth / window.innerHeight;
234+
camera.updateProjectionMatrix();
235+
236+
renderer.setSize( window.innerWidth, window.innerHeight );
237+
238+
}
239+
240+
function animate() {
241+
242+
requestAnimationFrame( animate );
243+
renderer.render( scene, camera );
244+
245+
}
246+
247+
</script>
248+
249+
</body>
250+
</html>

src/audio/PositionalAudio.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44

55
import { Vector3 } from '../math/Vector3.js';
6+
import { Quaternion } from '../math/Quaternion.js';
67
import { Audio } from './Audio.js';
78
import { Object3D } from '../core/Object3D.js';
89

@@ -76,14 +77,22 @@ PositionalAudio.prototype = Object.assign( Object.create( Audio.prototype ), {
7677
updateMatrixWorld: ( function () {
7778

7879
var position = new Vector3();
80+
var quaternion = new Quaternion();
81+
var scale = new Vector3();
82+
83+
var orientation = new Vector3();
7984

8085
return function updateMatrixWorld( force ) {
8186

8287
Object3D.prototype.updateMatrixWorld.call( this, force );
8388

84-
position.setFromMatrixPosition( this.matrixWorld );
89+
var panner = this.panner;
90+
this.matrixWorld.decompose( position, quaternion, scale );
91+
92+
orientation.set( 0, 0, 1 ).applyQuaternion( quaternion );
8593

86-
this.panner.setPosition( position.x, position.y, position.z );
94+
panner.setPosition( position.x, position.y, position.z );
95+
panner.setOrientation( orientation.x, orientation.y, orientation.z );
8796

8897
};
8998

0 commit comments

Comments
 (0)