Files
junisaber/src/components/audio-columns.js
Kevin Ngo e94ab73212 lint
2018-10-13 17:19:36 -07:00

94 lines
2.9 KiB
JavaScript

/**
* 72 values per box.
* Divided by 3 (x, y, z) is 24 vertices.
* 6 vertices per side of the cube (2 faces per side).
*/
const NUM_VALUES_PER_BOX = 72;
/**
* Column bars moving in sync to the audio via audio analyser.
*/
AFRAME.registerComponent('audio-columns', {
schema: {
analyser: {type: 'selector', default: '#audioAnalyser'},
height: {default: 1.0},
mirror: {default: 3},
scale: {default: 4.0},
separation: {default: 0.3},
thickness: {default: 0.1}
},
init: function () {
this.analyser = this.data.analyser.components.audioanalyser;
// Number of levels is half the FFT size.
this.frequencyBinCount = this.analyser.data.fftSize / 2;
// Create boxes (one row on each side per level).
const geometries = [];
let zPosition = 0;
for (let i = 0; i < this.frequencyBinCount; i++) {
for (let side = 0; side < 2; side++) {
const box = new THREE.BoxBufferGeometry();
this.initBox(box, side === 0 ? 1 : -1, zPosition);
geometries.push(box);
// Move Z back.
zPosition -= this.data.separation;
}
}
this.geometry = THREE.BufferGeometryUtils.mergeBufferGeometries(geometries);
const mesh = new THREE.Mesh(this.geometry, this.el.sceneEl.systems.materials.black);
this.el.setObject3D('mesh', mesh);
},
tick: function () {
// Step by 2 since we create one box of each side per level.
for (let i = 0; i < this.frequencyBinCount * 2; i += 2) {
let yScale = (this.data.height / 2) + this.analyser.levels[Math.floor(i / 2)] / 256.0 *
this.data.scale;
if (isNaN(yScale)) { return; }
this.setBoxHeight(i, yScale);
this.setBoxHeight(i + 1, yScale);
this.geometry.attributes.position.needsUpdate = true;
}
},
/**
* Initialize box by changing vertex buffer, to set position and scale.
*/
initBox: function (box, flip, zPosition) {
const data = this.data;
// Set position and scale of box via vertices.
for (let v = 0; v < box.attributes.position.array.length; v += 3) {
// Apply thickness to X and Z.
box.attributes.position.array[v] *= data.thickness;
box.attributes.position.array[v + 2] *= data.thickness;
// Apply zPosition.
box.attributes.position.array[v + 2] += zPosition;
// Apply height to Y.
box.attributes.position.array[v + 1] *= data.height / 2;
// Change X vertex positions for mirroring.
box.attributes.position.array[v] += flip * data.mirror;
}
},
/**
* Set Y of vertices.
*/
setBoxHeight: function (boxNumber, height) {
const boxIndex = boxNumber * NUM_VALUES_PER_BOX;
for (let i = boxIndex; i < boxIndex + NUM_VALUES_PER_BOX; i += 3) {
// Set Y.
let yValue = this.geometry.attributes.position.array[i + 1];
this.geometry.attributes.position.array[i + 1] = yValue >= 0
? height
: -1 * height;
}
}
});