Last active
March 8, 2019 10:14
-
-
Save pofulu/545bc58645003afba13478e8f43bb4e8 to your computer and use it in GitHub Desktop.
Rewrite keijiro's BrownianMotion to ReactiveStyle for Spark AR.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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