1 /** 2 * Copyright (c) 2011, Novyon Events 3 * 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * - Redistributions of source code must retain the above copyright notice, this 10 * list of conditions and the following disclaimer. 11 * 12 * - Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * @author Anthyon 29 */ 30 package com.jme3.terrain.noise.basis; 31 32 import com.jme3.terrain.noise.ShaderUtils; 33 34 // JAVA REFERENCE IMPLEMENTATION OF IMPROVED NOISE - COPYRIGHT 2002 KEN PERLIN. 35 /** 36 * Perlin's default implementation of Improved Perlin Noise 37 * designed to work with Noise base 38 */ 39 public final class ImprovedNoise extends Noise { 40 41 @Override init()42 public void init() { 43 44 } 45 noise(float x, float y, float z)46 static public float noise(float x, float y, float z) { 47 int X = ShaderUtils.floor(x), // FIND UNIT CUBE THAT 48 Y = ShaderUtils.floor(y), // CONTAINS POINT. 49 Z = ShaderUtils.floor(z); 50 x -= X; // FIND RELATIVE X,Y,Z 51 y -= Y; // OF POINT IN CUBE. 52 z -= Z; 53 X = X & 255; 54 Y = Y & 255; 55 Z = Z & 255; 56 float u = ImprovedNoise.fade(x), // COMPUTE FADE CURVES 57 v = ImprovedNoise.fade(y), // FOR EACH OF X,Y,Z. 58 w = ImprovedNoise.fade(z); 59 int A = ImprovedNoise.p[X] + Y; 60 int AA = ImprovedNoise.p[A] + Z; 61 int AB = ImprovedNoise.p[A + 1] + Z; 62 int B = ImprovedNoise.p[X + 1] + Y; 63 int BA = ImprovedNoise.p[B] + Z; 64 int BB = ImprovedNoise.p[B + 1] + Z; 65 66 return ImprovedNoise.lerp( 67 w, 68 ImprovedNoise.lerp( 69 v, 70 ImprovedNoise.lerp(u, ImprovedNoise.grad3(ImprovedNoise.p[AA], x, y, z), 71 ImprovedNoise.grad3(ImprovedNoise.p[BA], x - 1, y, z)), // BLENDED 72 ImprovedNoise.lerp(u, ImprovedNoise.grad3(ImprovedNoise.p[AB], x, y - 1, z), // RESULTS 73 ImprovedNoise.grad3(ImprovedNoise.p[BB], x - 1, y - 1, z))),// FROM 74 ImprovedNoise.lerp(v, 75 ImprovedNoise.lerp(u, ImprovedNoise.grad3(ImprovedNoise.p[AA + 1], x, y, z - 1), // CORNERS 76 ImprovedNoise.grad3(ImprovedNoise.p[BA + 1], x - 1, y, z - 1)), // OF 77 ImprovedNoise.lerp(u, ImprovedNoise.grad3(ImprovedNoise.p[AB + 1], x, y - 1, z - 1), 78 ImprovedNoise.grad3(ImprovedNoise.p[BB + 1], x - 1, y - 1, z - 1)))); 79 } 80 fade(final float t)81 static final float fade(final float t) { 82 return t * t * t * (t * (t * 6 - 15) + 10); 83 } 84 lerp(final float t, final float a, final float b)85 static final float lerp(final float t, final float a, final float b) { 86 return a + t * (b - a); 87 } 88 grad(final int hash, final float x, final float y, final float z)89 static float grad(final int hash, final float x, final float y, final float z) { 90 int h = hash & 15; // CONVERT LO 4 BITS OF HASH CODE 91 float u = h < 8 ? x : y, // INTO 12 GRADIENT DIRECTIONS. 92 v = h < 4 ? y : h == 12 || h == 14 ? x : z; 93 return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v); 94 } 95 96 static final float grad3(final int hash, final float x, final float y, final float z) { 97 int h = hash & 15; // CONVERT LO 4 BITS OF HASH CODE 98 return x * ImprovedNoise.GRAD3[h][0] + y * ImprovedNoise.GRAD3[h][1] + z * ImprovedNoise.GRAD3[h][2]; 99 } 100 101 static final int p[] = new int[512], permutation[] = { 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 102 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 103 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 104 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 105 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 106 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 107 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 108 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 109 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 110 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180 }; 111 112 private static float[][] GRAD3 = new float[][] { { 1, 1, 0 }, { -1, 1, 0 }, { 1, -1, 0 }, { -1, -1, 0 }, { 1, 0, 1 }, { -1, 0, 1 }, 113 { 1, 0, -1 }, { -1, 0, -1 }, { 0, 1, 1 }, { 0, -1, 1 }, { 0, 1, -1 }, { 0, -1, -1 }, { 1, 0, -1 }, { -1, 0, -1 }, { 0, -1, 1 }, 114 { 0, 1, 1 } }; 115 116 static { 117 for (int i = 0; i < 256; i++) { 118 ImprovedNoise.p[256 + i] = ImprovedNoise.p[i] = ImprovedNoise.permutation[i]; 119 } 120 } 121 122 @Override 123 public float value(final float x, final float y, final float z) { 124 return ImprovedNoise.noise(this.scale * x, this.scale * y, this.scale * z); 125 } 126 127 } 128