PositionalAudioHelper.js 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. ( function () {
  2. class PositionalAudioHelper extends THREE.Line {
  3. constructor( audio, range = 1, divisionsInnerAngle = 16, divisionsOuterAngle = 2 ) {
  4. const geometry = new THREE.BufferGeometry();
  5. const divisions = divisionsInnerAngle + divisionsOuterAngle * 2;
  6. const positions = new Float32Array( ( divisions * 3 + 3 ) * 3 );
  7. geometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
  8. const materialInnerAngle = new THREE.LineBasicMaterial( {
  9. color: 0x00ff00
  10. } );
  11. const materialOuterAngle = new THREE.LineBasicMaterial( {
  12. color: 0xffff00
  13. } );
  14. super( geometry, [ materialOuterAngle, materialInnerAngle ] );
  15. this.audio = audio;
  16. this.range = range;
  17. this.divisionsInnerAngle = divisionsInnerAngle;
  18. this.divisionsOuterAngle = divisionsOuterAngle;
  19. this.type = 'PositionalAudioHelper';
  20. this.update();
  21. }
  22. update() {
  23. const audio = this.audio;
  24. const range = this.range;
  25. const divisionsInnerAngle = this.divisionsInnerAngle;
  26. const divisionsOuterAngle = this.divisionsOuterAngle;
  27. const coneInnerAngle = THREE.MathUtils.degToRad( audio.panner.coneInnerAngle );
  28. const coneOuterAngle = THREE.MathUtils.degToRad( audio.panner.coneOuterAngle );
  29. const halfConeInnerAngle = coneInnerAngle / 2;
  30. const halfConeOuterAngle = coneOuterAngle / 2;
  31. let start = 0;
  32. let count = 0;
  33. let i;
  34. let stride;
  35. const geometry = this.geometry;
  36. const positionAttribute = geometry.attributes.position;
  37. geometry.clearGroups(); //
  38. function generateSegment( from, to, divisions, materialIndex ) {
  39. const step = ( to - from ) / divisions;
  40. positionAttribute.setXYZ( start, 0, 0, 0 );
  41. count ++;
  42. for ( i = from; i < to; i += step ) {
  43. stride = start + count;
  44. positionAttribute.setXYZ( stride, Math.sin( i ) * range, 0, Math.cos( i ) * range );
  45. positionAttribute.setXYZ( stride + 1, Math.sin( Math.min( i + step, to ) ) * range, 0, Math.cos( Math.min( i + step, to ) ) * range );
  46. positionAttribute.setXYZ( stride + 2, 0, 0, 0 );
  47. count += 3;
  48. }
  49. geometry.addGroup( start, count, materialIndex );
  50. start += count;
  51. count = 0;
  52. } //
  53. generateSegment( - halfConeOuterAngle, - halfConeInnerAngle, divisionsOuterAngle, 0 );
  54. generateSegment( - halfConeInnerAngle, halfConeInnerAngle, divisionsInnerAngle, 1 );
  55. generateSegment( halfConeInnerAngle, halfConeOuterAngle, divisionsOuterAngle, 0 ); //
  56. positionAttribute.needsUpdate = true;
  57. if ( coneInnerAngle === coneOuterAngle ) this.material[ 0 ].visible = false;
  58. }
  59. dispose() {
  60. this.geometry.dispose();
  61. this.material[ 0 ].dispose();
  62. this.material[ 1 ].dispose();
  63. }
  64. }
  65. THREE.PositionalAudioHelper = PositionalAudioHelper;
  66. } )();