PositionalAudioHelper.js 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  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. //
  39. function generateSegment( from, to, divisions, materialIndex ) {
  40. const step = ( to - from ) / divisions;
  41. positionAttribute.setXYZ( start, 0, 0, 0 );
  42. count ++;
  43. for ( i = from; i < to; i += step ) {
  44. stride = start + count;
  45. positionAttribute.setXYZ( stride, Math.sin( i ) * range, 0, Math.cos( i ) * range );
  46. positionAttribute.setXYZ( stride + 1, Math.sin( Math.min( i + step, to ) ) * range, 0, Math.cos( Math.min( i + step, to ) ) * range );
  47. positionAttribute.setXYZ( stride + 2, 0, 0, 0 );
  48. count += 3;
  49. }
  50. geometry.addGroup( start, count, materialIndex );
  51. start += count;
  52. count = 0;
  53. }
  54. //
  55. generateSegment( - halfConeOuterAngle, - halfConeInnerAngle, divisionsOuterAngle, 0 );
  56. generateSegment( - halfConeInnerAngle, halfConeInnerAngle, divisionsInnerAngle, 1 );
  57. generateSegment( halfConeInnerAngle, halfConeOuterAngle, divisionsOuterAngle, 0 );
  58. //
  59. positionAttribute.needsUpdate = true;
  60. if ( coneInnerAngle === coneOuterAngle ) this.material[ 0 ].visible = false;
  61. }
  62. dispose() {
  63. this.geometry.dispose();
  64. this.material[ 0 ].dispose();
  65. this.material[ 1 ].dispose();
  66. }
  67. }
  68. THREE.PositionalAudioHelper = PositionalAudioHelper;
  69. } )();