Advertisement
Guest User

Perlin class

a guest
Jul 30th, 2016
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 5 15.49 KB | None | 0 0
  1. /*****************************************************************************
  2.  *                        J3D.org Copyright (c) 2000
  3.  *                               Java Source
  4.  *
  5.  * This source is licensed under the GNU LGPL v2.1
  6.  * Please read http://www.gnu.org/copyleft/lgpl.html for more information
  7.  *
  8.  * This software comes with the standard NO WARRANTY disclaimer for any
  9.  * purpose. Use it at your own risk. If there's a problem you get to fix it.
  10.  *
  11.  ****************************************************************************/
  12. package io.github.blubdalegend.realm.world;
  13.  
  14. import java.util.Random;
  15.  
  16. /**
  17.  * Computes Perlin Noise for three dimensions.
  18.  * <p>
  19.  *
  20.  * The result is a continuous function that interpolates a smooth path along a
  21.  * series random points. The function is consitent, so given the same
  22.  * parameters, it will always return the same value. The smoothing function is
  23.  * based on the Improving Noise paper presented at Siggraph 2002.
  24.  * <p>
  25.  * Computing noise for one and two dimensions can make use of the 3D problem
  26.  * space by just setting the un-needed dimensions to a fixed value.
  27.  *
  28.  * @author Justin Couch
  29.  * @version $Revision: 1.4 $
  30.  */
  31. public class Perlin {
  32.     // Constants for setting up the Perlin-1 noise functions
  33.     private static final int B = 0x1000;
  34.     private static final int BM = 0xff;
  35.  
  36.     private static final int N = 0x1000;
  37.  
  38.     /** Default seed to use for the random number generation */
  39.     private static final int DEFAULT_SEED = 100;
  40.  
  41.     /** Default sample size to work with */
  42.     private static final int DEFAULT_SAMPLE_SIZE = 256;
  43.  
  44.  
  45.     /** Permutation array for the improved noise function */
  46.     private int[] p_imp;
  47.  
  48.     /** P array for perline 1 noise */
  49.     private int[] p;
  50.     private float[][] g3;
  51.     private float[][] g2;
  52.     private float[] g1;
  53.  
  54.     /**
  55.      * Create a new noise creator with the default seed value
  56.      */
  57.     public Perlin() {
  58.         this(DEFAULT_SEED);
  59.     }
  60.  
  61.     /**
  62.      * Create a new noise creator with the given seed value for the randomness
  63.      *
  64.      * @param seed
  65.      *            The seed value to use
  66.      */
  67.     public Perlin(int seed) {
  68.         p_imp = new int[DEFAULT_SAMPLE_SIZE << 1];
  69.  
  70.         int i, j, k;
  71.         Random rand = new Random(seed);
  72.  
  73.         // Calculate the table of psuedo-random coefficients.
  74.         for (i = 0; i < DEFAULT_SAMPLE_SIZE; i++)
  75.             p_imp[i] = i;
  76.  
  77.         // generate the psuedo-random permutation table.
  78.         while (--i > 0) {
  79.             k = p_imp[i];
  80.             j = (int) (rand.nextLong() & DEFAULT_SAMPLE_SIZE);
  81.             p_imp[i] = p_imp[j];
  82.             p_imp[j] = k;
  83.         }
  84.  
  85.         initPerlin1();
  86.     }
  87.  
  88.     /**
  89.      * Computes noise function for three dimensions at the point (x,y,z).
  90.      *
  91.      * @param x
  92.      *            x dimension parameter
  93.      * @param y
  94.      *            y dimension parameter
  95.      * @param z
  96.      *            z dimension parameter
  97.      * @return the noise value at the point (x, y, z)
  98.      */
  99.     public double improvedNoise(double x, double y, double z) {
  100.         // Constraint the point to a unit cube
  101.         int uc_x = (int) Math.floor(x) & 255;
  102.         int uc_y = (int) Math.floor(y) & 255;
  103.         int uc_z = (int) Math.floor(z) & 255;
  104.  
  105.         // Relative location of the point in the unit cube
  106.         double xo = x - Math.floor(x);
  107.         double yo = y - Math.floor(y);
  108.         double zo = z - Math.floor(z);
  109.  
  110.         // Fade curves for x, y and z
  111.         double u = fade(xo);
  112.         double v = fade(yo);
  113.         double w = fade(zo);
  114.  
  115.         // Generate a hash for each coordinate to find out where in the cube
  116.         // it lies.
  117.         int a = p_imp[uc_x] + uc_y;
  118.         int aa = p_imp[a] + uc_z;
  119.         int ab = p_imp[a + 1] + uc_z;
  120.  
  121.         int b = p_imp[uc_x + 1] + uc_y;
  122.         int ba = p_imp[b] + uc_z;
  123.         int bb = p_imp[b + 1] + uc_z;
  124.  
  125.         // blend results from the 8 corners based on the noise function
  126.         double c1 = grad(p_imp[aa], xo, yo, zo);
  127.         double c2 = grad(p_imp[ba], xo - 1, yo, zo);
  128.         double c3 = grad(p_imp[ab], xo, yo - 1, zo);
  129.         double c4 = grad(p_imp[bb], xo - 1, yo - 1, zo);
  130.         double c5 = grad(p_imp[aa + 1], xo, yo, zo - 1);
  131.         double c6 = grad(p_imp[ba + 1], xo - 1, yo, zo - 1);
  132.         double c7 = grad(p_imp[ab + 1], xo, yo - 1, zo - 1);
  133.         double c8 = grad(p_imp[bb + 1], xo - 1, yo - 1, zo - 1);
  134.  
  135.         return lerp(w, lerp(v, lerp(u, c1, c2), lerp(u, c3, c4)), lerp(v, lerp(u, c5, c6), lerp(u, c7, c8)));
  136.     }
  137.  
  138.     /**
  139.      * 1-D noise generation function using the original perlin algorithm.
  140.      *
  141.      * @param x
  142.      *            Seed for the noise function
  143.      * @return The noisy output
  144.      */
  145.     public float noise1(float x) {
  146.         float t = x + N;
  147.         int bx0 = ((int) t) & BM;
  148.         int bx1 = (bx0 + 1) & BM;
  149.         float rx0 = t - (int) t;
  150.         float rx1 = rx0 - 1;
  151.  
  152.         float sx = sCurve(rx0);
  153.  
  154.         float u = rx0 * g1[p[bx0]];
  155.         float v = rx1 * g1[p[bx1]];
  156.  
  157.         return lerp(sx, u, v);
  158.     }
  159.  
  160.     /**
  161.      * Create noise in a 2D space using the orignal perlin noise algorithm.
  162.      *
  163.      * @param x
  164.      *            The X coordinate of the location to sample
  165.      * @param y
  166.      *            The Y coordinate of the location to sample
  167.      * @return A noisy value at the given position
  168.      */
  169.     public float noise2(float x, float y) {
  170.         float t = x + N;
  171.         int bx0 = ((int) t) & BM;
  172.         int bx1 = (bx0 + 1) & BM;
  173.         float rx0 = t - (int) t;
  174.         float rx1 = rx0 - 1;
  175.  
  176.         t = y + N;
  177.         int by0 = ((int) t) & BM;
  178.         int by1 = (by0 + 1) & BM;
  179.         float ry0 = t - (int) t;
  180.         float ry1 = ry0 - 1;
  181.  
  182.         int i = p[bx0];
  183.         int j = p[bx1];
  184.  
  185.         int b00 = p[i + by0];
  186.         int b10 = p[j + by0];
  187.         int b01 = p[i + by1];
  188.         int b11 = p[j + by1];
  189.  
  190.         float sx = sCurve(rx0);
  191.         float sy = sCurve(ry0);
  192.  
  193.         float[] q = g2[b00];
  194.         float u = rx0 * q[0] + ry0 * q[1];
  195.         q = g2[b10];
  196.         float v = rx1 * q[0] + ry0 * q[1];
  197.         float a = lerp(sx, u, v);
  198.  
  199.         q = g2[b01];
  200.         u = rx0 * q[0] + ry1 * q[1];
  201.         q = g2[b11];
  202.         v = rx1 * q[0] + ry1 * q[1];
  203.         float b = lerp(sx, u, v);
  204.  
  205.         return lerp(sy, a, b);
  206.     }
  207.  
  208.     /**
  209.      * Create noise in a 3D space using the orignal perlin noise algorithm.
  210.      *
  211.      * @param x
  212.      *            The X coordinate of the location to sample
  213.      * @param y
  214.      *            The Y coordinate of the location to sample
  215.      * @param z
  216.      *            The Z coordinate of the location to sample
  217.      * @return A noisy value at the given position
  218.      */
  219.     public float noise3(float x, float y, float z) {
  220.         float t = x + (float) N;
  221.         int bx0 = ((int) t) & BM;
  222.         int bx1 = (bx0 + 1) & BM;
  223.         float rx0 = (float) (t - (int) t);
  224.         float rx1 = rx0 - 1;
  225.  
  226.         t = y + (float) N;
  227.         int by0 = ((int) t) & BM;
  228.         int by1 = (by0 + 1) & BM;
  229.         float ry0 = (float) (t - (int) t);
  230.         float ry1 = ry0 - 1;
  231.  
  232.         t = z + (float) N;
  233.         int bz0 = ((int) t) & BM;
  234.         int bz1 = (bz0 + 1) & BM;
  235.         float rz0 = (float) (t - (int) t);
  236.         float rz1 = rz0 - 1;
  237.  
  238.         int i = p[bx0];
  239.         int j = p[bx1];
  240.  
  241.         int b00 = p[i + by0];
  242.         int b10 = p[j + by0];
  243.         int b01 = p[i + by1];
  244.         int b11 = p[j + by1];
  245.  
  246.         t = sCurve(rx0);
  247.         float sy = sCurve(ry0);
  248.         float sz = sCurve(rz0);
  249.  
  250.         float[] q = g3[b00 + bz0];
  251.         float u = (rx0 * q[0] + ry0 * q[1] + rz0 * q[2]);
  252.         q = g3[b10 + bz0];
  253.         float v = (rx1 * q[0] + ry0 * q[1] + rz0 * q[2]);
  254.         float a = lerp(t, u, v);
  255.  
  256.         q = g3[b01 + bz0];
  257.         u = (rx0 * q[0] + ry1 * q[1] + rz0 * q[2]);
  258.         q = g3[b11 + bz0];
  259.         v = (rx1 * q[0] + ry1 * q[1] + rz0 * q[2]);
  260.         float b = lerp(t, u, v);
  261.  
  262.         float c = lerp(sy, a, b);
  263.  
  264.         q = g3[b00 + bz1];
  265.         u = (rx0 * q[0] + ry0 * q[1] + rz1 * q[2]);
  266.         q = g3[b10 + bz1];
  267.         v = (rx1 * q[0] + ry0 * q[1] + rz1 * q[2]);
  268.         a = lerp(t, u, v);
  269.  
  270.         q = g3[b01 + bz1];
  271.         u = (rx0 * q[0] + ry1 * q[1] + rz1 * q[2]);
  272.         q = g3[b11 + bz1];
  273.         v = (rx1 * q[0] + ry1 * q[1] + rz1 * q[2]);
  274.         b = lerp(t, u, v);
  275.  
  276.         float d = lerp(sy, a, b);
  277.  
  278.         return lerp(sz, c, d);
  279.     }
  280.  
  281.     /**
  282.      * Create a turbulent noise output based on the core noise function. This
  283.      * uses the noise as a base function and is suitable for creating clouds,
  284.      * marble and explosion effects. For example, a typical marble effect would
  285.      * set the colour to be:
  286.      *
  287.      * <pre>
  288.      * sin(point + turbulence(point) * point.x);
  289.      * </pre>
  290.      */
  291.     public double imporvedTurbulence(double x, double y, double z, float loF, float hiF) {
  292.         double p_x = x + 123.456f;
  293.         double p_y = y;
  294.         double p_z = z;
  295.         double t = 0;
  296.         double f;
  297.  
  298.         for (f = loF; f < hiF; f *= 2) {
  299.             t += Math.abs(improvedNoise(p_x, p_y, p_z)) / f;
  300.  
  301.             p_x *= 2;
  302.             p_y *= 2;
  303.             p_z *= 2;
  304.         }
  305.  
  306.         return t - 0.3;
  307.     }
  308.  
  309.     /**
  310.      * Create a turbulance function in 2D using the original perlin noise
  311.      * function.
  312.      *
  313.      * @param x
  314.      *            The X coordinate of the location to sample
  315.      * @param y
  316.      *            The Y coordinate of the location to sample
  317.      * @param freq
  318.      *            The frequency of the turbluance to create
  319.      * @return The value at the given coordinates
  320.      */
  321.     public float turbulence2(float x, float y, float freq) {
  322.         float t = 0;
  323.  
  324.         do {
  325.             t += noise2(freq * x, freq * y) / freq;
  326.             freq *= 0.5f;
  327.         } while (freq >= 1);
  328.  
  329.         return t;
  330.     }
  331.  
  332.     /**
  333.      * Create a turbulance function in 3D using the original perlin noise
  334.      * function.
  335.      *
  336.      * @param x
  337.      *            The X coordinate of the location to sample
  338.      * @param y
  339.      *            The Y coordinate of the location to sample
  340.      * @param z
  341.      *            The Z coordinate of the location to sample
  342.      * @param freq
  343.      *            The frequency of the turbluance to create
  344.      * @return The value at the given coordinates
  345.      */
  346.     public float turbulence3(float x, float y, float z, float freq) {
  347.         float t = 0;
  348.  
  349.         do {
  350.             t += noise3(freq * x, freq * y, freq * z) / freq;
  351.             freq *= 0.5f;
  352.         } while (freq >= 1);
  353.  
  354.         return t;
  355.     }
  356.  
  357.     /**
  358.      * Create a 1D tileable noise function for the given width.
  359.      *
  360.      * @param x
  361.      *            The X coordinate to generate the noise for
  362.      * @param w
  363.      *            The width of the tiled block
  364.      * @return The value of the noise at the given coordinate
  365.      */
  366.     public float tileableNoise1(float x, float w) {
  367.         return (noise1(x) * (w - x) + noise1(x - w) * x) / w;
  368.     }
  369.  
  370.     /**
  371.      * Create a 2D tileable noise function for the given width and height.
  372.      *
  373.      * @param x
  374.      *            The X coordinate to generate the noise for
  375.      * @param y
  376.      *            The Y coordinate to generate the noise for
  377.      * @param w
  378.      *            The width of the tiled block
  379.      * @param h
  380.      *            The height of the tiled block
  381.      * @return The value of the noise at the given coordinate
  382.      */
  383.     public float tileableNoise2(float x, float y, float w, float h) {
  384.         return (noise2(x, y) * (w - x) * (h - y) + noise2(x - w, y) * x * (h - y) + noise2(x, y - h) * (w - x) * y
  385.                 + noise2(x - w, y - h) * x * y) / (w * h);
  386.     }
  387.  
  388.     /**
  389.      * Create a 3D tileable noise function for the given width, height and
  390.      * depth.
  391.      *
  392.      * @param x
  393.      *            The X coordinate to generate the noise for
  394.      * @param y
  395.      *            The Y coordinate to generate the noise for
  396.      * @param z
  397.      *            The Z coordinate to generate the noise for
  398.      * @param w
  399.      *            The width of the tiled block
  400.      * @param h
  401.      *            The height of the tiled block
  402.      * @param d
  403.      *            The depth of the tiled block
  404.      * @return The value of the noise at the given coordinate
  405.      */
  406.     public float tileableNoise3(float x, float y, float z, float w, float h, float d) {
  407.         return (noise3(x, y, z) * (w - x) * (h - y) * (d - z) + noise3(x - w, y, z) * x * (h - y) * (d - z)
  408.                 + noise3(x, y - h, z) * (w - x) * y * (d - z) + noise3(x - w, y - h, z) * x * y * (d - z)
  409.                 + noise3(x, y, z - d) * (w - x) * (h - y) * z + noise3(x - w, y, z - d) * x * (h - y) * z
  410.                 + noise3(x, y - h, z - d) * (w - x) * y * z + noise3(x - w, y - h, z - d) * x * y * z) / (w * h * d);
  411.     }
  412.  
  413.     /**
  414.      * Create a turbulance function that can be tiled across a surface in 2D.
  415.      *
  416.      * @param x
  417.      *            The X coordinate of the location to sample
  418.      * @param y
  419.      *            The Y coordinate of the location to sample
  420.      * @param w
  421.      *            The width to tile over
  422.      * @param h
  423.      *            The height to tile over
  424.      * @param freq
  425.      *            The frequency of the turbluance to create
  426.      * @return The value at the given coordinates
  427.      */
  428.     public float tileableTurbulence2(float x, float y, float w, float h, float freq) {
  429.         float t = 0;
  430.  
  431.         do {
  432.             t += tileableNoise2(freq * x, freq * y, w * freq, h * freq) / freq;
  433.             freq *= 0.5f;
  434.         } while (freq >= 1);
  435.  
  436.         return t;
  437.     }
  438.  
  439.     /**
  440.      * Create a turbulance function that can be tiled across a surface in 3D.
  441.      *
  442.      * @param x
  443.      *            The X coordinate of the location to sample
  444.      * @param y
  445.      *            The Y coordinate of the location to sample
  446.      * @param z
  447.      *            The Z coordinate of the location to sample
  448.      * @param w
  449.      *            The width to tile over
  450.      * @param h
  451.      *            The height to tile over
  452.      * @param d
  453.      *            The depth to tile over
  454.      * @param freq
  455.      *            The frequency of the turbluance to create
  456.      * @return The value at the given coordinates
  457.      */
  458.     public float tileableTurbulence3(float x, float y, float z, float w, float h, float d, float freq) {
  459.         float t = 0;
  460.  
  461.         do {
  462.             t += tileableNoise3(freq * x, freq * y, freq * z, w * freq, h * freq, d * freq) / freq;
  463.             freq *= 0.5f;
  464.         } while (freq >= 1);
  465.  
  466.         return t;
  467.     }
  468.  
  469.     /**
  470.      * Simple lerp function using doubles.
  471.      */
  472.     private double lerp(double t, double a, double b) {
  473.         return a + t * (b - a);
  474.     }
  475.  
  476.     /**
  477.      * Simple lerp function using floats.
  478.      */
  479.     private float lerp(float t, float a, float b) {
  480.         return a + t * (b - a);
  481.     }
  482.  
  483.     /**
  484.      * Fade curve calculation which is 6t^5 - 15t^4 + 10t^3. This is the new
  485.      * algorithm, where the old one used to be 3t^2 - 2t^3.
  486.      *
  487.      * @param t
  488.      *            The t parameter to calculate the fade for
  489.      * @return the drop-off amount.
  490.      */
  491.     private double fade(double t) {
  492.         return t * t * t * (t * (t * 6 - 15) + 10);
  493.     }
  494.  
  495.     /**
  496.      * Calculate the gradient function based on the hash code.
  497.      */
  498.     private double grad(int hash, double x, double y, double z) {
  499.         // Convert low 4 bits of hash code into 12 gradient directions.
  500.         int h = hash & 15;
  501.         double u = (h < 8 || h == 12 || h == 13) ? x : y;
  502.         double v = (h < 4 || h == 12 || h == 13) ? y : z;
  503.  
  504.         return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
  505.     }
  506.  
  507.     /**
  508.      * Simple bias generator using exponents.
  509.      */
  510.  
  511.     /**
  512.      * S-curve function for value distribution for Perlin-1 noise function.
  513.      */
  514.     private float sCurve(float t) {
  515.         return (t * t * (3 - 2 * t));
  516.     }
  517.  
  518.     /**
  519.      * 2D-vector normalisation function.
  520.      */
  521.     private void normalize2(float[] v) {
  522.         float s = (float) (1 / Math.sqrt(v[0] * v[0] + v[1] * v[1]));
  523.         v[0] *= s;
  524.         v[1] *= s;
  525.     }
  526.  
  527.     /**
  528.      * 3D-vector normalisation function.
  529.      */
  530.     private void normalize3(float[] v) {
  531.         float s = (float) (1 / Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]));
  532.         v[0] *= s;
  533.         v[1] *= s;
  534.         v[2] *= s;
  535.     }
  536.  
  537.     /**
  538.      * Initialise the lookup arrays used by Perlin 1 function.
  539.      */
  540.     private void initPerlin1() {
  541.         p = new int[B + B + 2];
  542.         g3 = new float[B + B + 2][3];
  543.         g2 = new float[B + B + 2][2];
  544.         g1 = new float[B + B + 2];
  545.         int i, j, k;
  546.  
  547.         for (i = 0; i < B; i++) {
  548.             p[i] = i;
  549.  
  550.             g1[i] = (float) (((Math.random() * Integer.MAX_VALUE) % (B + B)) - B) / B;
  551.  
  552.             for (j = 0; j < 2; j++)
  553.                 g2[i][j] = (float) (((Math.random() * Integer.MAX_VALUE) % (B + B)) - B) / B;
  554.             normalize2(g2[i]);
  555.  
  556.             for (j = 0; j < 3; j++)
  557.                 g3[i][j] = (float) (((Math.random() * Integer.MAX_VALUE) % (B + B)) - B) / B;
  558.             normalize3(g3[i]);
  559.         }
  560.  
  561.         while (--i > 0) {
  562.             k = p[i];
  563.             j = (int) ((Math.random() * Integer.MAX_VALUE) % B);
  564.             p[i] = p[j];
  565.             p[j] = k;
  566.         }
  567.  
  568.         for (i = 0; i < B + 2; i++) {
  569.             p[B + i] = p[i];
  570.             g1[B + i] = g1[i];
  571.             for (j = 0; j < 2; j++)
  572.                 g2[B + i][j] = g2[i][j];
  573.             for (j = 0; j < 3; j++)
  574.                 g3[B + i][j] = g3[i][j];
  575.         }
  576.     }
  577. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement