Skip to content

Instantly share code, notes, and snippets.

@pofulu
Last active March 8, 2019 10:14
Show Gist options
  • Save pofulu/545bc58645003afba13478e8f43bb4e8 to your computer and use it in GitHub Desktop.
Save pofulu/545bc58645003afba13478e8f43bb4e8 to your computer and use it in GitHub Desktop.
Rewrite keijiro's BrownianMotion to ReactiveStyle for Spark AR.
// C# version source by keijiro: https://github.com/keijiro/Klak/blob/master/Assets/Klak/Motion/Runtime/BrownianMotion.cs
const Scene = require('Scene');
BrownianMotion(Scene.root.find('bubble'),
{
enablePositionNoise: true,
enableRotationNoise: false,
enableScaleNoise: false,
positionAmplitude: 10
});
// The config means "only enable position noise and set _positionAmplitude value = 10"
function BrownianMotion(obj, config) {
// Configurable parameters
let _positionScale = new Vector3(1, 1, 0);
let _positionAmplitude = 1;
let _positionFractalLevel = 3;
let _positionFrequency = 0.06;
let _rotationScale = new Vector3(1, 1, 1);
let _rotationAmplitude = 3;
let _rotationFractalLevel = 3;
let _rotationFrequency = 0.08;
let _scaleScale = new Vector3(1, 1, 1);
let _scaleAmplitude = 0.5;
let _scaleFractalLevel = 3;
let _scaleFrequency = 0.05;
let _enablePositionNoise = true;
let _enableRotationNoise = true;
let _enableScaleNoise = true;
// Interanl implementation
const _fbmNorm = 1 / 0.75;
const perm = [
151, 160, 137, 91, 90, 15,
131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23,
190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33,
88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166,
77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244,
102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196,
135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123,
5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42,
223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9,
129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228,
251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107,
49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254,
138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180,
151
];
let _time = [];
let _basePosition, _baseRotation, _baseScale;
Rehash();
Init();
LoadConfig();
if (_enablePositionNoise) {
_time[0] = _time[0].add(Time.ms.div(1000).mul(_positionFrequency));
_time[1] = _time[1].add(Time.ms.div(1000).mul(_positionFrequency));
_time[2] = _time[2].add(Time.ms.div(1000).mul(_positionFrequency));
let n = new Vector3(
Fbm(_time[0], _positionFractalLevel),
Fbm(_time[1], _positionFractalLevel),
Fbm(_time[2], _positionFractalLevel)
)
.scale(_positionScale)
.mul(_positionAmplitude)
.mul(_fbmNorm);
obj.transform.x = n.x.add(_basePosition.x);
obj.transform.y = n.y.add(_basePosition.y);
obj.transform.z = n.z.add(_basePosition.z);
}
if (_enableRotationNoise) {
_time[3] = _time[3].add(Time.ms.div(1000).mul(_rotationFrequency));
_time[4] = _time[4].add(Time.ms.div(1000).mul(_rotationFrequency));
_time[5] = _time[5].add(Time.ms.div(1000).mul(_rotationFrequency));
let n = new Vector3(
Fbm(_time[3], _rotationFractalLevel),
Fbm(_time[4], _rotationFractalLevel),
Fbm(_time[5], _rotationFractalLevel)
)
.scale(_rotationScale)
.mul(_rotationAmplitude)
.mul(_fbmNorm);
obj.transform.rotationX = RotationSignal(n.x).add(_baseRotation.x);
obj.transform.rotationY = RotationSignal(n.y).add(_baseRotation.y);
obj.transform.rotationZ = RotationSignal(n.z).add(_baseRotation.z);
}
if (_enableScaleNoise) {
_time[6] = _time[6].add(Time.ms.div(1000).mul(_scaleFrequency));
_time[7] = _time[7].add(Time.ms.div(1000).mul(_scaleFrequency));
_time[8] = _time[8].add(Time.ms.div(1000).mul(_scaleFrequency));
let n = new Vector3(
Fbm(_time[6], _scaleFractalLevel),
Fbm(_time[7], _scaleFractalLevel),
Fbm(_time[8], _scaleFractalLevel)
)
.scale(_scaleScale)
.mul(_scaleAmplitude)
.mul(_fbmNorm);
obj.transform.scaleX = n.x.add(_baseScale.x);
obj.transform.scaleY = n.y.add(_baseScale.y);
obj.transform.scaleZ = n.z.add(_baseScale.z);
}
function Init() {
_basePosition = new Vector3(
obj.transform.x.pinLastValue(),
obj.transform.y.pinLastValue(),
obj.transform.z.pinLastValue()
);
_baseRotation = new Vector3(
obj.transform.rotationX.pinLastValue(),
obj.transform.rotationY.pinLastValue(),
obj.transform.rotationZ.pinLastValue(),
);
_baseScale = new Vector3(
obj.transform.scaleX.pinLastValue(),
obj.transform.scaleY.pinLastValue(),
obj.transform.scaleZ.pinLastValue()
);
}
function LoadConfig() {
if (config != null) {
if (config.enablePositionNoise != undefined) _enablePositionNoise = config.enablePositionNoise;
if (config.enableRotationNoise != undefined) _enableRotationNoise = config.enableRotationNoise;
if (config.enableScaleNoise != undefined) _enableScaleNoise = config.enableScaleNoise;
if (config.positionScale != undefined) _positionScale = config.positionScale;
if (config.positionAmplitude != undefined) _positionAmplitude = config.positionAmplitude;
if (config.positionFractalLevel != undefined) _positionFractalLevel = config.positionFractalLevel;
if (config.positionFrequency != undefined) _positionFrequency = config.positionFrequency;
if (config.rotationScale != undefined) _rotationScale = config.rotationScale;
if (config.rotationAmplitude != undefined) _rotationAmplitude = config.rotationAmplitude;
if (config.rotationFractalLevel != undefined) _rotationFractalLevel = config.rotationFractalLevel;
if (config.rotationFrequency != undefined) _rotationFrequency = config.rotationFrequency;
if (config.scaleScale != undefined) _scaleScale = config.scaleScale;
if (config.scaleAmplitude != undefined) _scaleAmplitude = config.scaleAmplitude;
if (config.scaleFractalLevel != undefined) _scaleFractalLevel = config.scaleFractalLevel;
if (config.scaleFrequency != undefined) _scaleFrequency = config.scaleFrequency;
if (config.basePosition != undefined) _basePosition = config.basePosition;
if (config.baseRotation != undefined) _baseRotation = config.baseRotation;
if (config.baseScale != undefined) _baseScale = config.baseScale;
}
}
function Rehash() {
for (var i = 0; i < 9; i++)
_time[i] = Reactive.val(Math.random() * 10000 - 10000);
}
function Noise(x) {
let X = x.ceil().pinLastValue() & 0xff;
// let X = Math.floor(x) & 0xff;
x = x.sub(x.floor());
// x -= Math.floor(x);
let u = Fade(x);
let t = u;
let a = Grad(perm[X], x);
let b = Grad(perm[X + 1], x.sub(1));
return LerpSignal(t, a, b).mul(2);
// return Lerp(u, Grad(perm[X], x), Grad(perm[X + 1], x - 1)) * 2;
}
function Fbm(x, octave) {
let f = Reactive.val(0);
let w = Reactive.val(0.5);
for (let i = 0; i < octave; i++) {
f = w.mul(Noise(x)).add(f);
// f += w * Noise(x);
x = x.mul(2);
// x *= 2.0;
w = w.mul(0.5);
// w *= 0.5;
}
return f;
}
function Fade(t) {
return t.mul(6).sub(15).mul(t).add(10).mul(t).mul(t).mul(t);
// return t * t * t * (t * (t * 6 - 15) + 10);
}
function Grad(hash, x) {
if ((hash & 1) == 0) {
return x;
} else {
return x.mul(-1);
}
}
function Vector3(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
this.mul = function (multiplier) {
return new Vector3(this.x.mul(multiplier), this.y.mul(multiplier), this.z.mul(multiplier));
};
this.scale = function (anotherVector3) {
return new Vector3(this.x.mul(anotherVector3.x), this.y.mul(anotherVector3.y), this.z.mul(anotherVector3.z));
}
this.add = function (anotherVector3) {
return new Vector3(this.x.add(anotherVector3.x), this.y.add(anotherVector3.y), this.z.add(anotherVector3.z));
}
this.dot = function (anotherVector3) {
return this.x.mul(anotherVector3.x).add(this.y.mul(anotherVector3.y)).add(this.z.mul(anotherVector3.z));
}
this.sub = function (anotherVector3) {
return new Vector3(this.x.sub(anotherVector3.x), this.y.sub(anotherVector3.y), this.z.sub(anotherVector3.z));
}
return this;
}
function LerpSignal(t, a, b) {
return b.sub(a).mul(t).add(a);
}
function RotationSignal(signal) {
return RemapSignal(signal, Reactive.val(-180), Reactive.val(180), Reactive.val(Math.PI * -1), Reactive.val(Math.PI));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment