From 32c83c1b36cbcbcf9390d7f3947ef7930ef83506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Fri, 22 Jan 2016 01:27:14 +0100 Subject: [PATCH] Optimized NoiseFunctionSimplex by inlining This causes duplicated code, but it should be removed when NoiseGenerator is not used anymore --- src/basics/NoiseFunctionSimplex.cpp | 184 +++++++++++++++++++++++++++- 1 file changed, 182 insertions(+), 2 deletions(-) diff --git a/src/basics/NoiseFunctionSimplex.cpp b/src/basics/NoiseFunctionSimplex.cpp index 4f42cae..018cc53 100644 --- a/src/basics/NoiseFunctionSimplex.cpp +++ b/src/basics/NoiseFunctionSimplex.cpp @@ -141,6 +141,7 @@ double noiseSimplexGet1DValue(double x) { } double noiseSimplexGet2DValue(double x, double y) { + // FIXME duplicated double n0, n1, n2; /* Noise contributions from the three corners */ /* Skew the input space to determine which simplex cell we're in */ double s = (x + y) * _F2; /* Hairy factor for 2D */ @@ -203,6 +204,7 @@ double noiseSimplexGet2DValue(double x, double y) { } double noiseSimplexGet3DValue(double x, double y, double z) { + // FIXME duplicated double n0, n1, n2, n3; /* Noise contributions from the four corners */ /* Skew the input space to determine which simplex cell we're in */ double s = (x + y + z) * _F3; /* Very nice and simple skew factor for 3D */ @@ -469,11 +471,189 @@ double noiseSimplexGet4DValue(double x, double y, double z, double w) { } double NoiseFunctionSimplex::getBase2d(double x, double y) const { - return noiseSimplexGet2DValue(x, y) - 0.5; + double n0, n1, n2; /* Noise contributions from the three corners */ + /* Skew the input space to determine which simplex cell we're in */ + double s = (x + y) * _F2; /* Hairy factor for 2D */ + int i = _fastfloor(x + s); + int j = _fastfloor(y + s); + double t = (i + j) * _G2; + double X0 = i - t; /* Unskew the cell origin back to (x,y) space */ + double Y0 = j - t; + double x0 = x - X0; /* The x,y distances from the cell origin */ + double y0 = y - Y0; + /* For the 2D case, the simplex shape is an equilateral triangle. + Determine which simplex we are in. */ + int i1, j1; /* Offsets for second (middle) corner of simplex in (i,j) coords */ + if (x0 > y0) { + i1 = 1; + j1 = 0; + } /* lower triangle, XY order: (0,0)->(1,0)->(1,1) */ + else { + i1 = 0; + j1 = 1; + } /* upper triangle, YX order: (0,0)->(0,1)->(1,1) */ + /* A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and + a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where + c = (3-sqrt(3))/6 */ + double x1 = x0 - i1 + _G2; /* Offsets for middle corner in (x,y) unskewed coords */ + double y1 = y0 - j1 + _G2; + double x2 = x0 - 1.0 + 2.0 * _G2; /* Offsets for last corner in (x,y) unskewed coords */ + double y2 = y0 - 1.0 + 2.0 * _G2; + /* Work out the hashed gradient indices of the three simplex corners */ + int ii = i & 255; + int jj = j & 255; + int gi0 = _permutationsMod12[ii + _permutations2[jj]]; + int gi1 = _permutationsMod12[ii + i1 + _permutations2[jj + j1]]; + int gi2 = _permutationsMod12[ii + 1 + _permutations2[jj + 1]]; + /* Calculate the contribution from the three corners */ + double t0 = 0.5 - x0 * x0 - y0 * y0; + if (t0 < 0) + n0 = 0.0; + else { + t0 *= t0; + n0 = t0 * t0 * _dot2(_grad3[gi0], x0, y0); /* (x,y) of _grad3 used for 2D gradient */ + } + double t1 = 0.5 - x1 * x1 - y1 * y1; + if (t1 < 0) + n1 = 0.0; + else { + t1 *= t1; + n1 = t1 * t1 * _dot2(_grad3[gi1], x1, y1); + } + double t2 = 0.5 - x2 * x2 - y2 * y2; + if (t2 < 0) + n2 = 0.0; + else { + t2 *= t2; + n2 = t2 * t2 * _dot2(_grad3[gi2], x2, y2); + } + /* Add contributions from each corner to get the final noise value. + The result is scaled to return values in the interval [-0.5,0.5]. */ + return 35.0 * (n0 + n1 + n2); } double NoiseFunctionSimplex::getBase3d(double x, double y, double z) const { - return noiseSimplexGet3DValue(x, y, z) - 0.5; + double n0, n1, n2, n3; /* Noise contributions from the four corners */ + /* Skew the input space to determine which simplex cell we're in */ + double s = (x + y + z) * _F3; /* Very nice and simple skew factor for 3D */ + int i = _fastfloor(x + s); + int j = _fastfloor(y + s); + int k = _fastfloor(z + s); + double t = (i + j + k) * _G3; + double X0 = i - t; /* Unskew the cell origin back to (x,y,z) space */ + double Y0 = j - t; + double Z0 = k - t; + double x0 = x - X0; /* The x,y,z distances from the cell origin */ + double y0 = y - Y0; + double z0 = z - Z0; + /* For the 3D case, the simplex shape is a slightly irregular tetrahedron. + Determine which simplex we are in. */ + int i1, j1, k1; /* Offsets for second corner of simplex in (i,j,k) coords */ + int i2, j2, k2; /* Offsets for third corner of simplex in (i,j,k) coords */ + if (x0 >= y0) { + if (y0 >= z0) { + i1 = 1; + j1 = 0; + k1 = 0; + i2 = 1; + j2 = 1; + k2 = 0; + } /* X Y Z order */ + else if (x0 >= z0) { + i1 = 1; + j1 = 0; + k1 = 0; + i2 = 1; + j2 = 0; + k2 = 1; + } /* X Z Y order */ + else { + i1 = 0; + j1 = 0; + k1 = 1; + i2 = 1; + j2 = 0; + k2 = 1; + } /* Z X Y order */ + } else { /* x0