UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

85 lines (84 loc) 3.11 kB
"use strict"; import { BufferAttribute } from "three"; import { BufferGeometry } from "three"; import { Line } from "three"; import { LineBasicMaterial } from "three"; import { MathUtils } from "three"; function createGeometry(divisionsInnerAngle, divisionsOuterAngle) { const geometry = new BufferGeometry(); const divisions = divisionsInnerAngle + divisionsOuterAngle * 2; const positions = new Float32Array((divisions * 3 + 3) * 3); geometry.setAttribute("position", new BufferAttribute(positions, 3)); return geometry; } function createInnerAngleMaterial() { return new LineBasicMaterial({ color: 65280 }); } function createOuterAngleMaterial() { return new LineBasicMaterial({ color: 16776960 }); } export class CorePositionalAudioHelper extends Line { constructor(audio, range = 1, divisionsInnerAngle = 16, divisionsOuterAngle = 2) { super(createGeometry(divisionsInnerAngle, divisionsOuterAngle), [ createInnerAngleMaterial(), createOuterAngleMaterial() ]); this.audio = audio; this.range = range; this.divisionsInnerAngle = divisionsInnerAngle; this.divisionsOuterAngle = divisionsOuterAngle; this.type = "PositionalAudioHelper"; this.update(); } update() { const audio = this.audio; const range = this.range; const divisionsInnerAngle = this.divisionsInnerAngle; const divisionsOuterAngle = this.divisionsOuterAngle; const coneInnerAngle = MathUtils.degToRad(audio.coneInnerAngle()); const coneOuterAngle = MathUtils.degToRad(audio.coneOuterAngle()); const halfConeInnerAngle = coneInnerAngle / 2; const halfConeOuterAngle = coneOuterAngle / 2; let start = 0; let count = 0; let i; let stride; const geometry = this.geometry; const positionAttribute = geometry.attributes.position; geometry.clearGroups(); function generateSegment(from, to, divisions, materialIndex) { const step = (to - from) / divisions; positionAttribute.setXYZ(start, 0, 0, 0); count++; for (i = from; i < to; i += step) { stride = start + count; positionAttribute.setXYZ(stride, Math.sin(i) * range, 0, Math.cos(i) * range); positionAttribute.setXYZ( stride + 1, Math.sin(Math.min(i + step, to)) * range, 0, Math.cos(Math.min(i + step, to)) * range ); positionAttribute.setXYZ(stride + 2, 0, 0, 0); count += 3; } geometry.addGroup(start, count, materialIndex); start += count; count = 0; } generateSegment(-halfConeOuterAngle, -halfConeInnerAngle, divisionsOuterAngle, 0); generateSegment(-halfConeInnerAngle, halfConeInnerAngle, divisionsInnerAngle, 1); generateSegment(halfConeInnerAngle, halfConeOuterAngle, divisionsOuterAngle, 0); positionAttribute.needsUpdate = true; if (coneInnerAngle === coneOuterAngle) { const materials = this.material; materials[0].visible = false; } } dispose() { this.geometry.dispose(); const materials = this.material; materials[0].dispose(); materials[1].dispose(); } }