001    package org.bukkit.util.noise;
002    
003    import java.util.Random;
004    import org.bukkit.World;
005    
006    /**
007     * Creates simplex noise through unbiased octaves
008     */
009    public class SimplexOctaveGenerator extends OctaveGenerator {
010        private double wScale = 1;
011    
012        /**
013         * Creates a simplex octave generator for the given world
014         *
015         * @param world World to construct this generator for
016         * @param octaves Amount of octaves to create
017         */
018        public SimplexOctaveGenerator(World world, int octaves) {
019            this(new Random(world.getSeed()), octaves);
020        }
021    
022        /**
023         * Creates a simplex octave generator for the given world
024         *
025         * @param seed Seed to construct this generator for
026         * @param octaves Amount of octaves to create
027         */
028        public SimplexOctaveGenerator(long seed, int octaves) {
029            this(new Random(seed), octaves);
030        }
031    
032        /**
033         * Creates a simplex octave generator for the given {@link Random}
034         *
035         * @param rand Random object to construct this generator for
036         * @param octaves Amount of octaves to create
037         */
038        public SimplexOctaveGenerator(Random rand, int octaves) {
039            super(createOctaves(rand, octaves));
040        }
041    
042        @Override
043        public void setScale(double scale) {
044            super.setScale(scale);
045            setWScale(scale);
046        }
047    
048        /**
049         * Gets the scale used for each W-coordinates passed
050         *
051         * @return W scale
052         */
053        public double getWScale() {
054            return wScale;
055        }
056    
057        /**
058         * Sets the scale used for each W-coordinates passed
059         *
060         * @param scale New W scale
061         */
062        public void setWScale(double scale) {
063            wScale = scale;
064        }
065    
066        /**
067         * Generates noise for the 3D coordinates using the specified number of
068         * octaves and parameters
069         *
070         * @param x X-coordinate
071         * @param y Y-coordinate
072         * @param z Z-coordinate
073         * @param w W-coordinate
074         * @param frequency How much to alter the frequency by each octave
075         * @param amplitude How much to alter the amplitude by each octave
076         * @return Resulting noise
077         */
078        public double noise(double x, double y, double z, double w, double frequency, double amplitude) {
079            return noise(x, y, z, w, frequency, amplitude, false);
080        }
081    
082        /**
083         * Generates noise for the 3D coordinates using the specified number of
084         * octaves and parameters
085         *
086         * @param x X-coordinate
087         * @param y Y-coordinate
088         * @param z Z-coordinate
089         * @param w W-coordinate
090         * @param frequency How much to alter the frequency by each octave
091         * @param amplitude How much to alter the amplitude by each octave
092         * @param normalized If true, normalize the value to [-1, 1]
093         * @return Resulting noise
094         */
095        public double noise(double x, double y, double z, double w, double frequency, double amplitude, boolean normalized) {
096            double result = 0;
097            double amp = 1;
098            double freq = 1;
099            double max = 0;
100    
101            x *= xScale;
102            y *= yScale;
103            z *= zScale;
104            w *= wScale;
105    
106            for (NoiseGenerator octave : octaves) {
107                result += ((SimplexNoiseGenerator) octave).noise(x * freq, y * freq, z * freq, w * freq) * amp;
108                max += amp;
109                freq *= frequency;
110                amp *= amplitude;
111            }
112    
113            if (normalized) {
114                result /= max;
115            }
116    
117            return result;
118        }
119    
120        private static NoiseGenerator[] createOctaves(Random rand, int octaves) {
121            NoiseGenerator[] result = new NoiseGenerator[octaves];
122    
123            for (int i = 0; i < octaves; i++) {
124                result[i] = new SimplexNoiseGenerator(rand);
125            }
126    
127            return result;
128        }
129    }