UNPKG

@babylonjs/core

Version:

Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.

169 lines 6.25 kB
import { NodeGeometryBlock } from "../nodeGeometryBlock.js"; import { RegisterClass } from "../../../Misc/typeStore.js"; import { NodeGeometryBlockConnectionPointTypes } from "../Enums/nodeGeometryConnectionPointTypes.js"; import { Vector3 } from "../../../Maths/math.vector.js"; import { Clamp } from "../../../Maths/math.scalar.functions.js"; import { NodeGeometryContextualSources } from "../Enums/nodeGeometryContextualSources.js"; /** * Block used to get a noise value */ export class NoiseBlock extends NodeGeometryBlock { /** * Create a new NoiseBlock * @param name defines the block name */ constructor(name) { super(name); this.registerInput("offset", NodeGeometryBlockConnectionPointTypes.Vector3, true, Vector3.Zero()); this.registerInput("scale", NodeGeometryBlockConnectionPointTypes.Float, true, 1); this.registerInput("octaves", NodeGeometryBlockConnectionPointTypes.Float, true, 2, 0, 16); this.registerInput("roughness", NodeGeometryBlockConnectionPointTypes.Float, true, 0.5, 0, 1); this.registerOutput("output", NodeGeometryBlockConnectionPointTypes.Float); } /** * Gets the current class name * @returns the class name */ getClassName() { return "NoiseBlock"; } /** * Gets the offset input component */ get offset() { return this._inputs[0]; } /** * Gets the scale input component */ get scale() { return this._inputs[1]; } /** * Gets the octaves input component */ get octaves() { return this._inputs[2]; } /** * Gets the roughtness input component */ get roughness() { return this._inputs[3]; } /** * Gets the geometry output component */ get output() { return this._outputs[0]; } _negateIf(value, condition) { return condition !== 0 ? -value : value; } _noiseGrad(hash, x, y, z) { const h = hash & 15; const u = h < 8 ? x : y; const vt = h === 12 || h == 14 ? x : z; const v = h < 4 ? y : vt; return this._negateIf(u, h & u) + this._negateIf(v, h & 2); } _fade(t) { return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); } _hashBitRotate(x, k) { return (x << k) | (x >> (32 - k)); } _hash(kx, ky, kz) { let a, b, c; a = b = c = 0xdeadbeef + (3 << 2) + 13; c += kz; b += ky; a += kx; c ^= b; c -= this._hashBitRotate(b, 14); a ^= c; a -= this._hashBitRotate(c, 11); b ^= a; b -= this._hashBitRotate(a, 25); c ^= b; c -= this._hashBitRotate(b, 16); a ^= c; a -= this._hashBitRotate(c, 4); b ^= a; b -= this._hashBitRotate(a, 14); c ^= b; c -= this._hashBitRotate(b, 24); return c; } _mix(v0, v1, v2, v3, v4, v5, v6, v7, x, y, z) { const x1 = 1.0 - x; const y1 = 1.0 - y; const z1 = 1.0 - z; return z1 * (y1 * (v0 * x1 + v1 * x) + y * (v2 * x1 + v3 * x)) + z * (y1 * (v4 * x1 + v5 * x) + y * (v6 * x1 + v7 * x)); } _perlinNoise(position) { const x = (position.x | 0) - (position.x < 0 ? 1 : 0); const y = (position.y | 0) - (position.y < 0 ? 1 : 0); const z = (position.z | 0) - (position.z < 0 ? 1 : 0); const fx = position.x - x; const fy = position.y - y; const fz = position.z - z; const u = this._fade(fx); const v = this._fade(fy); const w = this._fade(fz); return this._mix(this._noiseGrad(this._hash(x, y, z), fx, fy, fz), this._noiseGrad(this._hash(x + 1, y, z), fx - 1, fy, fz), this._noiseGrad(this._hash(x, y + 1, z), fx, fy - 1, fz), this._noiseGrad(this._hash(x + 1, y + 1, z), fx - 1, fy - 1, fz), this._noiseGrad(this._hash(x, y, z + 1), fx, fy, fz - 1), this._noiseGrad(this._hash(x + 1, y, z + 1), fx - 1, fy, fz - 1), this._noiseGrad(this._hash(x, y + 1, z + 1), fx, fy - 1, fz - 1), this._noiseGrad(this._hash(x + 1, y + 1, z + 1), fx - 1, fy - 1, fz - 1), u, v, w); } _perlinSigned(position) { return this._perlinNoise(position) * 0.982; } _perlin(position) { return this._perlinSigned(position) / 2.0 + 0.5; } /** * Gets a perlin noise value * @param octaves number of octaves * @param roughness roughness * @param _position position vector * @param offset offset vector * @param scale scale value * @returns a value between 0 and 1 * @see Based on https://github.com/blender/blender/blob/main/source/blender/blenlib/intern/noise.cc#L533 */ noise(octaves, roughness, _position, offset, scale) { const position = new Vector3(_position.x * scale + offset.x, _position.y * scale + offset.y, _position.z * scale + offset.z); let fscale = 1.0; let amp = 1.0; let maxamp = 0.0; let sum = 0.0; octaves = Clamp(octaves, 0, 15.0); const step = octaves | 0; for (let i = 0; i <= step; i++) { const t = this._perlin(position.scale(fscale)); sum += t * amp; maxamp += amp; amp *= Clamp(roughness, 0.0, 1.0); fscale *= 2.0; } const rmd = octaves - Math.floor(octaves); if (rmd == 0.0) { return sum / maxamp; } const t = this._perlin(position.scale(fscale)); let sum2 = sum + t * amp; sum /= maxamp; sum2 /= maxamp + amp; return (1.0 - rmd) * sum + rmd * sum2; } _buildBlock() { this.output._storedFunction = (state) => { const position = state.getContextualValue(NodeGeometryContextualSources.Positions); const octaves = this.octaves.getConnectedValue(state); const roughness = this.roughness.getConnectedValue(state); const offset = this.offset.getConnectedValue(state); const scale = this.scale.getConnectedValue(state); return this.noise(octaves, roughness, position, offset, scale); }; } } RegisterClass("BABYLON.NoiseBlock", NoiseBlock); //# sourceMappingURL=noiseBlock.js.map