PositionalAudioHelper.js 2.8 KB

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