1 /** 2 Holds the (mor or less) independet OpenSimplexNoise implementation - original source and implementation: https://gist.github.com/KdotJPG/b1270127455a94ac5d19 and http://uniblock.tumblr.com/ 3 */ 4 module dosimplex.osimplex2d; 5 6 import dosimplex.util; 7 8 /// "Config" enum for the noise generator 9 private enum : double { 10 STRETCH_CONSTANT_2D = -0.211324865405187, ///(1/Math.sqrt(2+1)-1)/2; 11 SQUISH_CONSTANT_2D = 0.366025403784439, ///(Math.sqrt(2+1)-1)/2; 12 NORM_CONSTANT_2D = 47., 13 } 14 15 16 /** 17 2D OpenSimplexNoise implementation. 18 */ 19 @nogc @safe pure double osNoise2D(double x, double y, const ref short[256] perm) 20 { 21 //Place input coordinates onto grid. 22 double stretchOffset = (x + y) * STRETCH_CONSTANT_2D; 23 double xs = x + stretchOffset; 24 double ys = y + stretchOffset; 25 26 //Floor to get grid coordinates of rhombus (stretched square) super-cell origin. 27 int xsb = fastFloor(xs); 28 int ysb = fastFloor(ys); 29 30 //Skew out to get actual coordinates of rhombus origin. We'll need these later. 31 double squishOffset = (xsb + ysb) * SQUISH_CONSTANT_2D; 32 double xb = xsb + squishOffset; 33 double yb = ysb + squishOffset; 34 35 //Compute grid coordinates relative to rhombus origin. 36 double xins = xs - xsb; 37 double yins = ys - ysb; 38 39 //Sum those together to get a value that determines which region we're in. 40 double inSum = xins + yins; 41 42 //Positions relative to origin point. 43 double dx0 = x - xb; 44 double dy0 = y - yb; 45 46 //We'll be defining these inside the next block and using them afterwards. 47 double dx_ext, dy_ext; 48 int xsv_ext, ysv_ext; 49 50 double value = 0; 51 52 //Contribution (1,0) 53 double dx1 = dx0 - 1 - SQUISH_CONSTANT_2D; 54 double dy1 = dy0 - 0 - SQUISH_CONSTANT_2D; 55 double attn1 = 2 - dx1 * dx1 - dy1 * dy1; 56 if (attn1 > 0) { 57 attn1 *= attn1; 58 value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, dx1, dy1, perm); 59 } 60 61 //Contribution (0,1) 62 double dx2 = dx0 - 0 - SQUISH_CONSTANT_2D; 63 double dy2 = dy0 - 1 - SQUISH_CONSTANT_2D; 64 double attn2 = 2 - dx2 * dx2 - dy2 * dy2; 65 if (attn2 > 0) { 66 attn2 *= attn2; 67 value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, dx2, dy2, perm); 68 } 69 70 if (inSum <= 1) { //We're inside the triangle (2-Simplex) at (0,0) 71 double zins = 1 - inSum; 72 if (zins > xins || zins > yins) { //(0,0) is one of the closest two triangular vertices 73 if (xins > yins) { 74 xsv_ext = xsb + 1; 75 ysv_ext = ysb - 1; 76 dx_ext = dx0 - 1; 77 dy_ext = dy0 + 1; 78 } else { 79 xsv_ext = xsb - 1; 80 ysv_ext = ysb + 1; 81 dx_ext = dx0 + 1; 82 dy_ext = dy0 - 1; 83 } 84 } else { //(1,0) and (0,1) are the closest two vertices. 85 xsv_ext = xsb + 1; 86 ysv_ext = ysb + 1; 87 dx_ext = dx0 - 1 - 2 * SQUISH_CONSTANT_2D; 88 dy_ext = dy0 - 1 - 2 * SQUISH_CONSTANT_2D; 89 } 90 } else { //We're inside the triangle (2-Simplex) at (1,1) 91 double zins = 2 - inSum; 92 if (zins < xins || zins < yins) { //(0,0) is one of the closest two triangular vertices 93 if (xins > yins) { 94 xsv_ext = xsb + 2; 95 ysv_ext = ysb + 0; 96 dx_ext = dx0 - 2 - 2 * SQUISH_CONSTANT_2D; 97 dy_ext = dy0 + 0 - 2 * SQUISH_CONSTANT_2D; 98 } else { 99 xsv_ext = xsb + 0; 100 ysv_ext = ysb + 2; 101 dx_ext = dx0 + 0 - 2 * SQUISH_CONSTANT_2D; 102 dy_ext = dy0 - 2 - 2 * SQUISH_CONSTANT_2D; 103 } 104 } else { //(1,0) and (0,1) are the closest two vertices. 105 dx_ext = dx0; 106 dy_ext = dy0; 107 xsv_ext = xsb; 108 ysv_ext = ysb; 109 } 110 xsb += 1; 111 ysb += 1; 112 dx0 = dx0 - 1 - 2 * SQUISH_CONSTANT_2D; 113 dy0 = dy0 - 1 - 2 * SQUISH_CONSTANT_2D; 114 } 115 116 //Contribution (0,0) or (1,1) 117 double attn0 = 2 - dx0 * dx0 - dy0 * dy0; 118 if (attn0 > 0) { 119 attn0 *= attn0; 120 value += attn0 * attn0 * extrapolate(xsb, ysb, dx0, dy0, perm); 121 } 122 123 //Extra Vertex 124 double attn_ext = 2 - dx_ext * dx_ext - dy_ext * dy_ext; 125 if (attn_ext > 0) { 126 attn_ext *= attn_ext; 127 value += attn_ext * attn_ext * extrapolate(xsv_ext, ysv_ext, dx_ext, dy_ext, perm); 128 } 129 130 return value / NORM_CONSTANT_2D; 131 } 132 133 /** 134 extrapolates for 2D 135 */ 136 private @nogc @safe pure double extrapolate(int xsb, int ysb, double dx, double dy, const ref short[256] perm) 137 { 138 int index = perm[(perm[xsb & 0xFF] + ysb) & 0xFF] & 0x0E; 139 return GRADIENTS.GRADIENTS_2D[index] * dx + GRADIENTS.GRADIENTS_2D[index + 1] * dy; 140 }