Home Reference Source

src/volume/sdf/FractalNoise.js

import { Box3, Vector3 } from "three";
import { SignedDistanceFunction } from "./SignedDistanceFunction";
import { SDFType } from "./SDFType";

/**
 * Fades a given value.
 *
 * @param {Number} t - A value.
 * @return {Number} The faded value.
 */

function fade(t) {

	return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);

}

/**
 * Computes a gradient for a given integer.
 *
 * @param {Number} p - An arbitrary integer.
 * @return {Number} The gradient, 1 or -1.
 */

function gradient(p) {

	/* const v = gradients[p % 256];

	return (v > 0.5) ? 1.0 : -1.0; */

	return 0;

}

/**
 * Computes a noise value for a given number.
 *
 * @param {Number} p - An arbitrary number.
 * @return {Number} The noise value.
 */

function noise(p) {

	const p0 = Math.trunc(p);
	const p1 = p0 + 1;

	const t = p - p0;
	const fadeT = fade(t);

	const g0 = gradient(p0);
	const g1 = fade(p1);

	return (1.0 - fadeT) * g0 * (p - p0) + fadeT * g1 * (p - p1);

}

/**
 * Fractal noise based on Perlin's technique.
 *
 * Reference:
 *  https://gpfault.net/posts/perlin-noise.txt.html
 */

export class FractalNoise extends SignedDistanceFunction {

	/**
	 * Constructs a new perlin noise density field.
	 *
	 * @param {Object} parameters - The parameters.
	 * @param {Number} [material] - A material index.
	 */

	constructor(parameters = {}, material) {

		super(SDFType.PERLIN_NOISE, material);

		/**
		 * The upper bounds of this density field.
		 *
		 * @type {Vector3}
		 */

		this.min = new Vector3(...parameters.min);

		/**
		 * The upper bounds of this density field.
		 *
		 * @type {Vector3}
		 */

		this.max = new Vector3(...parameters.max);

	}

	/**
	 * Calculates the bounding box of this density field.
	 *
	 * @return {Box3} The bounding box.
	 */

	computeBoundingBox() {

		this.bbox = new Box3(this.min, this.max);

		return this.bbox;

	}

	/**
	 * Samples the volume's density at the given point in space.
	 *
	 * @param {Vector3} position - A position.
	 * @return {Number} The euclidean distance to the surface.
	 */

	sample(position) {

	}

	/**
	 * Serialises this SDF.
	 *
	 * @param {Boolean} [toJSON=false] - Whether the serialised data will be stringified.
	 * @return {Object} A serialised description of this SDF.
	 */

	serialize(toJSON = false) {

		const result = super.serialize();

		result.parameters = {
			min: this.min.toArray(),
			max: this.max.toArray()
		};

		return result;

	}

}