Newer
Older
perlin_noise / script.js
window.addEventListener('load', function() {

    const canvas = this.document.getElementById('canvas1');
    const ctx = canvas.getContext('2d');
    canvas.width = 1500;
    canvas.height = 500;

    class Perlin {

        // number of points to generate
        #NUM_POINTS = 101;

        // number of prime numbers in each array
        #NUM_PRIMES = 5;

	    #PRIME5  =  [     15731,      16069,      17579,      31963,      22453];
	    #PRIME6  =  [    789221,     790289,     811081,     211777,     566173];
	    #PRIME10 =  [1376312589, 1480028201, 1500450271, 1000075057, 1023465798];
	
        constructor(persist, octave) {
            this.persist = persist;
            this.octave = octave;

            this.#init();
            console.log("points:");
            console.log(this.points);
        }

        #init() {
            this.points = [];

            this.p5d = this.#PRIME5[Math.floor(Math.random() * 5)];
            this.p6d = this.#PRIME6[Math.floor(Math.random() * 5)];
            this.p10d = this.#PRIME10[Math.floor(Math.random() * 5)];

            for(let i = 0; i < this.#NUM_POINTS; i++) {
                this.points[i] = this.#perlin1D(this.persist, this.octave, 0.1 * i);
            }

        }

        #perlin1D(persist, octave, x) {
            let total = 0.0;
            let freq = 0.0;
            let amp = 0.0;

            for(let i = 0; i < octave; i++) {
                freq = Math.pow(2,i);
                amp = Math.pow(persist, i);
                total += this.#interpolateNoise(x * freq) * amp;
            }

            return total;
        }

        /*
         * #interpolateNoise - performs a successive smoothing function on
         *      the input value.
         * ARGUMENT:
         * x:   float value to be smoothed.
        */
        #interpolateNoise(x) {
            let intX = Math.floor(x);
            let fractionX = x - intX;

            let v1 = this.#smoothedNoise(intX);
            let v2 = this.#smoothedNoise(intX + 1);

            return this.#cosineInterpolation(v1, v2, fractionX);
        }

        /*
         * #smoothedNoise - smooths the output to make it look less random
         * 
         * ARGUMENTS:
         * x: integer value to be smoothed.  It is done by averaging between
         *      the points before and after the given point.
         * 
         * RETURNS:
         * a float value that has been "smoothed".
        */

        #smoothedNoise(x) {
            return (this.#findNoise(x) /2) + (this.#findNoise(x - 1) / 4) + (this.#findNoise(x+1)/4);
        }

        #cosineInterpolation(a, b, x) {
            let ft = (x * Math.PI);
		    let f = (1 - Math.cos(ft)) * 0.5;
		
		    return a * (1 - f) + (b * f);
        }

        /*
         * findNoise - Random number generator.  Unlike other RNG this method
         * 		will return the same number for the same input.
         * 
         * ARGUMENTS:
         * x: an integer value
         * 
         * RETURNS:
         * returns a floating point number between -1.0 and 1.0.  
         * 
         * NOTE:
         * original return value as published on 
		 * http://freespace.virgin.net/hugo.elias/models/m_perlin.htm
        */
        #findNoise(x) {
            let z = (x << 13) ^ x;
		
		    let y = (1.0 - (( z * (z * z * this.p5d + this.p6d) + this.p10d)
                    & 0x7fffffff ) / 1073741824.0);
            return y;
        }

    }

    let perlin1 = new Perlin(0.3, 4);
    let perlin2 = new Perlin(0.3, 0.4);

});