Skip to content

Commit

Permalink
Added the chroma.js library to do all the heavy lifting for colour mi…
Browse files Browse the repository at this point in the history
…xing / interpolation, format calculation, etc. Yeah, it's another library, yeah, I don't want to spend my time writing this shit myself. Started integrating chroma with a bunch of the older colour code, replacing my poorly functioning crap.
  • Loading branch information
callumhay committed Jun 11, 2020
1 parent fb39549 commit 6d9fbd5
Show file tree
Hide file tree
Showing 10 changed files with 126 additions and 86 deletions.
57 changes: 55 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@serialport/bindings": "^8.0.8",
"bufferutil": "^4.0.1",
"canvas": "^2.6.1",
"chroma-js": "^2.1.0",
"cobs": "^0.2.1",
"dat.gui": "^0.7.7",
"express": "^4.17.1",
Expand Down
7 changes: 5 additions & 2 deletions src/Animation/FireAnimator.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const fireAnimatorDefaultConfig = {
viscosity: 0.000,
buoyancy: 5.4,
cooling: 1.3,
initialIntensityMultiplier: 8,
vorticityConfinement: 8.0,
spectrumTempMin: 700,
spectrumTempMax: 1700,
Expand Down Expand Up @@ -47,6 +48,8 @@ class FireAnimator extends VoxelAnimator {
render(dt) {
super.render(dt);

const {speed, initialIntensityMultiplier} = this.config;

const startX = 1;
const endX = this.voxelModel.xSize()-startX;
const startZ = 1;
Expand All @@ -57,10 +60,10 @@ class FireAnimator extends VoxelAnimator {
for (let z = startZ; z < endZ; z++) {
let f = this.genFunc(x-startX, z-startZ, endX-startX, endY, this.t, this.randomArray);
this.fluidModel.sd[this.fluidModel._I(x, 1, z)] = 1.0;
this.fluidModel.sT[this.fluidModel._I(x, 1, z)] = 1.0 + f*8.0;
this.fluidModel.sT[this.fluidModel._I(x, 1, z)] = 1.0 + f*initialIntensityMultiplier;
}
}
const speedDt = dt*this.config.speed;
const speedDt = dt*speed;
this.fluidModel.step(speedDt);
this.t += speedDt;

Expand Down
45 changes: 5 additions & 40 deletions src/Animation/Randomizers.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as THREE from 'three';
import chroma from 'chroma-js'
import { VOXEL_EPSILON } from '../MathUtils';

export class Randomizer {
Expand Down Expand Up @@ -138,49 +139,13 @@ export class Vector3DirectionRandomizer extends Randomizer {
export class ColourRandomizer extends Randomizer {
constructor(min = new THREE.Color(0,0,0), max = new THREE.Color(1,1,1)) {
super();

let _min = min.clone();
let _max = max.clone();

this.getMin = () => (_min);
this.setMin = (m) => { _min.setRGB(m.r, m.g, m.b); };
this.getMax = () => (_max);
this.setMax = (m) => { _max.setRGB(m.r, m.g, m.b); };

this.setMin(min);
this.setMax(max);

this.setRandomizers = (min, max) => {
this._randomizers = [
new UniformIntRandomizer(Math.floor(255*min.r), Math.floor(255*max.r), false),
new UniformIntRandomizer(Math.floor(255*min.g), Math.floor(255*max.g), false),
new UniformIntRandomizer(Math.floor(255*min.b), Math.floor(255*max.b), false)
];
}
this.setRandomizers(_min, _max);
}

get min() { return this.getMin(); }
get max() { return this.getMax(); }

set min(min) {
this.setMin(new THREE.Color(min.r, min.g, min.b));
this.setRandomizers(this.getMin(), this.getMax())
}
set max(max) {
this.setMax(new THREE.Color(max.r, max.g, max.b));
this.setRandomizers(this.getMin(), this.getMax());
this.min = min;
this.max = max;
}

generate() {
const colour = new THREE.Color();
colour.setRGB(
this._randomizers[0].generate() / 255.0,
this._randomizers[1].generate() / 255.0,
this._randomizers[2].generate() / 255.0
);

return colour;
const temp = chroma.mix(chroma.gl(this.min), chroma.gl(this.max), Randomizer.getRandomIntInclusive(0,1000)/1000).gl();
return new THREE.Color(temp[0], temp[1], temp[2]);
}

toJSON() {
Expand Down
3 changes: 2 additions & 1 deletion src/Animation/ShootingStarAnimator.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as THREE from 'three';

import VoxelAnimator, {REPEAT_INFINITE_TIMES} from './VoxelAnimator';
import VoxelColourAnimator, {INTERPOLATION_SMOOTHER} from './VoxelColourAnimator';
import VoxelColourAnimator, {INTERPOLATION_SMOOTHER, COLOUR_INTERPOLATION_LRGB} from './VoxelColourAnimator';

import {VOXEL_EPSILON, VOXEL_ERR_UNITS} from '../MathUtils';

Expand Down Expand Up @@ -61,6 +61,7 @@ class ShootingStarAnimator extends VoxelAnimator {
startTimeSecs: 0.0,
endTimeSecs: fadeTimeSecs,
interpolation: INTERPOLATION_SMOOTHER,
colourInterpolationType: COLOUR_INTERPOLATION_LRGB,
}),
};
this.currAnimatorMap.push(animatorObj);
Expand Down
28 changes: 14 additions & 14 deletions src/Animation/VoxelColourAnimator.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import * as THREE from 'three';
import chroma from 'chroma-js';

import VoxelAnimator, {REPEAT_INFINITE_TIMES} from './VoxelAnimator';

export const COLOUR_INTERPOLATION_HSL = 'hsl';
export const COLOUR_INTERPOLATION_RGB = 'rgb';

export const COLOUR_INTERPOLATION_RGB = 'rgb';
export const COLOUR_INTERPOLATION_HSL = 'hsl';
export const COLOUR_INTERPOLATION_LAB = 'lab';
export const COLOUR_INTERPOLATION_LCH = 'lch';
export const COLOUR_INTERPOLATION_LRGB = 'lrgb';
export const COLOUR_INTERPOLATION_TYPES = [
COLOUR_INTERPOLATION_HSL,
COLOUR_INTERPOLATION_RGB,
COLOUR_INTERPOLATION_HSL,
COLOUR_INTERPOLATION_LAB,
COLOUR_INTERPOLATION_LCH,
COLOUR_INTERPOLATION_LRGB,
];

export const INTERPOLATION_LERP = 'lerp';
Expand Down Expand Up @@ -73,17 +82,8 @@ class VoxelColourAnimator extends VoxelAnimator {
break;
}

const currColour = this.colourStart.clone();

switch (colourInterpolationType) {
default:
case COLOUR_INTERPOLATION_HSL:
currColour.lerpHSL(this.colourEnd, interpolateAlpha);
break;
case COLOUR_INTERPOLATION_RGB:
currColour.lerp(this.colourEnd, interpolateAlpha);
break;
}
const temp = chroma.mix(chroma.gl(this.colourStart), chroma.gl(this.colourEnd), interpolateAlpha, colourInterpolationType).gl();
const currColour = new THREE.Color(temp[0], temp[1], temp[2]);

this.voxelPositions.forEach(voxelPos => {
this.voxelModel.setVoxel(voxelPos, currColour);
Expand Down
8 changes: 4 additions & 4 deletions src/VoxelTracer/Scenes/Audio/BasicBarsAudioVisScene.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

import * as THREE from 'three';
import chroma from 'chroma-js';

import AudioVisUtils from './AudioVisUtils';

Expand Down Expand Up @@ -66,9 +67,8 @@ class BasicBarsAudioVisScene extends SceneRenderer {
const levelColours = [];
for (let y = Y_START; y < ySize; y++) {
const t = THREE.MathUtils.smootherstep(y, Y_START, ySize-1);
const colour = new THREE.Color(lowColour.r, lowColour.g, lowColour.b);
colour.lerp(highColour, t);
levelColours.push(colour);
const temp = chroma.mix(chroma.gl(lowColour), chroma.gl(highColour), t, 'lrgb').gl();
levelColours.push(new THREE.Color(temp[0], temp[1], temp[2]));
}

const voxelOptions = {receivesShadow: false};
Expand Down Expand Up @@ -217,7 +217,7 @@ class BasicBarsAudioVisScene extends SceneRenderer {
if (centerSorted) {
// First sort all of the frequency bins by their descending amplitudes
// (after we add all of the indices in the collective bin index lookup)
const collectedFFTs = Object.keys(binIndexLookup).map(idx => AudioVisUtils.calcFFTBinLevelSum(this.binIndexLookup[idx], fft));
const collectedFFTs = Object.keys(this.binIndexLookup).map(idx => AudioVisUtils.calcFFTBinLevelSum(this.binIndexLookup[idx], fft));
collectedFFTs.sort((a,b) => b-a);

// The spiral index list and the sorted fft list should be the same length.
Expand Down
24 changes: 12 additions & 12 deletions src/VoxelTracer/Scenes/Audio/FireAudioVisScene.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {Randomizer} from '../../../Animation/Randomizers';
const SPECTRUM_WIDTH = 256;

export const fireAudioVisDefaultConfig = {
initialIntensityMultiplier: 8,
speedMultiplier: 1,
coolingMultiplier: 1,
boyancyMultiplier: 1,
Expand Down Expand Up @@ -91,6 +92,8 @@ class FireAudioVisScene extends SceneRenderer {
return;
}

const {speedMultiplier, initialIntensityMultiplier} = this._options.sceneConfig;

const xSize = this.voxelModel.xSize();
const ySize = this.voxelModel.ySize();
const zSize = this.voxelModel.zSize();
Expand All @@ -105,14 +108,11 @@ class FireAudioVisScene extends SceneRenderer {
for (let z = startZ; z < endZ; z++) {
let f = this._genFunc(x-startX, z-startZ, endX-startX, endY, this.t, this.initArray);
this.fluidModel.sd[this.fluidModel._I(x, 1, z)] = 1.0;
this.fluidModel.sT[this.fluidModel._I(x, 1, z)] = 0.25*this.fluidModel.sT[this.fluidModel._I(x, 1, z)] + 0.75*(1.0 + f*8.0);
this.fluidModel.sT[this.fluidModel._I(x, 1, z)] = 0.25*this.fluidModel.sT[this.fluidModel._I(x, 1, z)] + 0.75*(1.0 + f*initialIntensityMultiplier);
}
}

const {speedMultiplier} = this._options.sceneConfig;
const currSpeed = speedMultiplier * (2 + clamp(THREE.MathUtils.smootherstep(this.avgBeatsPerSec, 0, 80), 0, 0.5));
//console.log(currSpeed);

const currSpeed = speedMultiplier * (2 + clamp(THREE.MathUtils.smootherstep(this.avgBeatsPerSec, 0, 80), 0, 1));
const speedDt = dt*currSpeed;
this.fluidModel.step(speedDt);
this.t += speedDt;
Expand Down Expand Up @@ -157,7 +157,7 @@ class FireAudioVisScene extends SceneRenderer {
for (let i = 0; i < this.initArray.length; i++) {
const fftIndices = this.binIndexLookup[i];
const binLevel = AudioVisUtils.calcFFTBinLevelMax(fftIndices, fft);
this.initArray[i] = THREE.MathUtils.smootherstep(binLevel/levelMax, 0, 1);
this.initArray[i] = clamp(binLevel/levelMax, 0, 1);
}
//console.log(this.initArray);

Expand Down Expand Up @@ -185,13 +185,13 @@ class FireAudioVisScene extends SceneRenderer {
this.dRMSAvg = (this.dRMSAvg + (denoisedRMS - this.lastRMS) / dt) / 2.0;
if (this.timeSinceLastBeat > 0.001 && (this.dRMSAvg < 0 && this.lastdRMS > 0) || (this.dRMSAvg > 0 && this.lastdRMS < 0)) {
// We crossed zero, count the beat
this.avgBeatsPerSec = 1.0 / this.timeSinceLastBeat;
this.avgBeatsPerSec = clamp((this.avgBeatsPerSec + 1.0 / this.timeSinceLastBeat) / 2.0, 0, 80);
this.timeSinceLastBeat = 0;
}
else {
this.timeSinceLastBeat += dt;
if (this.timeSinceLastBeat > 1) {
this.avgBeatsPerSec = 0.01;
this.avgBeatsPerSec = clamp((this.avgBeatsPerSec + 0.01) / 2.0, 0, 80);
}
}

Expand Down Expand Up @@ -223,9 +223,7 @@ class FireAudioVisScene extends SceneRenderer {
const MAX_FIRE_ALPHA = 1.0;
const FULL_ON_FIRE = 100;

const {sceneConfig} = options;
const lowTempColour = sceneConfig.lowTempColour; //instanceof THREE.Color ? sceneConfig.lowTempColour : new THREE.Color(sceneConfig.lowTempColour[0]/255, sceneConfig.lowTempColour[1]/255, sceneConfig.lowTempColour[2]/255);
const highTempColour = sceneConfig.highTempColour;// instanceof THREE.Color ? sceneConfig.highTempColour : new THREE.Color(sceneConfig.highTempColour[0]/255, sceneConfig.highTempColour[1]/255, sceneConfig.highTempColour[2]/255);
const {lowTempColour, highTempColour} = options.sceneConfig;

const spectrum = this._genCustomColourSpectrum(lowTempColour, highTempColour, SPECTRUM_WIDTH);
this.fireTexture = [];
Expand Down Expand Up @@ -267,11 +265,13 @@ class FireAudioVisScene extends SceneRenderer {
let i = 0;

let avgP = 0;
let maxP = 0;
for (let j = 0; j < p.length; j++) {
avgP += p[j];
maxP = Math.max(maxP, p[j]);
}
avgP /= p.length;
const multiplier = avgP < 0.01 ? 0.0 : 0.25;
const multiplier = maxP < 0.1 ? 0.0 : Math.min(avgP, 0.25);

for (; i < 12; i++) {
f += (1.0 +
Expand Down
Loading

0 comments on commit 6d9fbd5

Please sign in to comment.