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("p5d: " + this.p5d);
            console.log("p6d: " + this.p6d);
            console.log("p10d: " + this.p10d);
            console.log("points:");
            console.log(this.points);
        }

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

            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)];
        }

        #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);
                console.log("freq: " + freq);
                amp = Math.pow(persist, i);
                console.log("amp: " + amp);
                total += this.#interpolateNoise(x * freq) * amp;
                console.log("total: " + total);
            }

            return total;
        }

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

            let v1 = this.#smoothedNoise(intX);
            console.log("v1: " + v1);
            let v2 = this.#smoothedNoise(intX + 1);
            console.log("v2: " + v2);

            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);
            console.log("ft: " + ft);
		    let f = (1 - Math.cos(ft)) * 0.5;
            console.log("f: " + f);
            console.log("#cosineInterp: " + (a * (1 - f) + (b * f)));
		
		    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) {
            console.log("findNoise: " + x);
            let z = (x << 13) ^ x;
            console.log("z: " + z);
		
		    let y = 1.0 - ( z * (z * z * this.p5d + this.p6d) + this.p10d);
            console.log("y: " + y);
            return y;
        }

    }

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

});