PositionalAudioHelper.js 2.8 KB

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