X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fnoise.cpp;h=c0249a4373678075bbe7575f1b12897f8a0d87ce;hb=ec5188a49a2ae5d69b8ab0df51ba1086b51e7891;hp=35057146da9c919c7bb8d90f64451bc51dd0431c;hpb=4e1f50035e860a00636ca5d804c267119df99601;p=dragonfireclient.git diff --git a/src/noise.cpp b/src/noise.cpp index 35057146d..c0249a437 100644 --- a/src/noise.cpp +++ b/src/noise.cpp @@ -1,22 +1,27 @@ /* -Minetest -Copyright (C) 2010-2013 celeron55, Perttu Ahola -Copyright (C) 2010-2013 kwolekr, Ryan Kwolek - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ + * Minetest + * Copyright (C) 2010-2014 celeron55, Perttu Ahola + * Copyright (C) 2010-2014 kwolekr, Ryan Kwolek + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #include #include "noise.h" @@ -30,6 +35,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #define NOISE_MAGIC_Z 52591 #define NOISE_MAGIC_SEED 1013 +typedef float (*Interp3dFxn)( + float v000, float v100, float v010, float v110, + float v001, float v101, float v011, float v111, + float x, float y, float z); + float cos_lookup[16] = { 1.0, 0.9238, 0.7071, 0.3826, 0, -0.3826, -0.7071, -0.9238, 1.0, -0.9238, -0.7071, -0.3826, 0, 0.3826, 0.7071, 0.9238 @@ -40,7 +50,8 @@ float cos_lookup[16] = { //noise poly: p(n) = 60493n^3 + 19990303n + 137612589 -float noise2d(int x, int y, int seed) { +float noise2d(int x, int y, int seed) +{ int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y + NOISE_MAGIC_SEED * seed) & 0x7fffffff; n = (n >> 13) ^ n; @@ -49,7 +60,8 @@ float noise2d(int x, int y, int seed) { } -float noise3d(int x, int y, int z, int seed) { +float noise3d(int x, int y, int z, int seed) +{ int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y + NOISE_MAGIC_Z * z + NOISE_MAGIC_SEED * seed) & 0x7fffffff; n = (n >> 13) ^ n; @@ -58,19 +70,23 @@ float noise3d(int x, int y, int z, int seed) { } -float dotProduct(float vx, float vy, float wx, float wy) { +float dotProduct(float vx, float vy, float wx, float wy) +{ return vx * wx + vy * wy; } -inline float linearInterpolation(float v0, float v1, float t) { +inline float linearInterpolation(float v0, float v1, float t) +{ return v0 + (v1 - v0) * t; } -float biLinearInterpolation(float v00, float v10, - float v01, float v11, - float x, float y) { +float biLinearInterpolation( + float v00, float v10, + float v01, float v11, + float x, float y) +{ float tx = easeCurve(x); float ty = easeCurve(y); float u = linearInterpolation(v00, v10, tx); @@ -79,38 +95,70 @@ float biLinearInterpolation(float v00, float v10, } -float biLinearInterpolationNoEase(float x0y0, float x1y0, - float x0y1, float x1y1, - float x, float y) { +float biLinearInterpolationNoEase( + float x0y0, float x1y0, + float x0y1, float x1y1, + float x, float y) +{ float u = linearInterpolation(x0y0, x1y0, x); float v = linearInterpolation(x0y1, x1y1, x); return linearInterpolation(u, v, y); } - +/* float triLinearInterpolation( float v000, float v100, float v010, float v110, float v001, float v101, float v011, float v111, - float x, float y, float z) { + float x, float y, float z) +{ + float u = biLinearInterpolation(v000, v100, v010, v110, x, y); + float v = biLinearInterpolation(v001, v101, v011, v111, x, y); + return linearInterpolation(u, v, z); +} + + +float triLinearInterpolationNoEase( + float v000, float v100, float v010, float v110, + float v001, float v101, float v011, float v111, + float x, float y, float z) +{ float u = biLinearInterpolationNoEase(v000, v100, v010, v110, x, y); float v = biLinearInterpolationNoEase(v001, v101, v011, v111, x, y); return linearInterpolation(u, v, z); } +*/ -#if 0 float triLinearInterpolation( float v000, float v100, float v010, float v110, float v001, float v101, float v011, float v111, float x, float y, float z) { - /*float tx = easeCurve(x); + float tx = easeCurve(x); float ty = easeCurve(y); - float tz = easeCurve(z);*/ + float tz = easeCurve(z); + + return ( + v000 * (1 - tx) * (1 - ty) * (1 - tz) + + v100 * tx * (1 - ty) * (1 - tz) + + v010 * (1 - tx) * ty * (1 - tz) + + v110 * tx * ty * (1 - tz) + + v001 * (1 - tx) * (1 - ty) * tz + + v101 * tx * (1 - ty) * tz + + v011 * (1 - tx) * ty * tz + + v111 * tx * ty * tz + ); +} + +float triLinearInterpolationNoEase( + float v000, float v100, float v010, float v110, + float v001, float v101, float v011, float v111, + float x, float y, float z) +{ float tx = x; float ty = y; float tz = z; - return( + return ( v000 * (1 - tx) * (1 - ty) * (1 - tz) + v100 * tx * (1 - ty) * (1 - tz) + v010 * (1 - tx) * ty * (1 - tz) + @@ -121,7 +169,6 @@ float triLinearInterpolation( v111 * tx * ty * tz ); } -#endif #if 0 @@ -164,11 +211,11 @@ float noise2d_gradient(float x, float y, int seed) float v01 = noise2d(x0, y0+1, seed); float v11 = noise2d(x0+1, y0+1, seed); // Interpolate - return biLinearInterpolation(v00,v10,v01,v11,xl,yl); + return biLinearInterpolation(v00, v10, v01, v11, xl, yl); } -float noise3d_gradient(float x, float y, float z, int seed) +float noise3d_gradient(float x, float y, float z, int seed, bool eased) { // Calculate the integer coordinates int x0 = myfloor(x); @@ -188,9 +235,17 @@ float noise3d_gradient(float x, float y, float z, int seed) float v011 = noise3d(x0, y0 + 1, z0 + 1, seed); float v111 = noise3d(x0 + 1, y0 + 1, z0 + 1, seed); // Interpolate - return triLinearInterpolation(v000, v100, v010, v110, - v001, v101, v011, v111, - xl, yl, zl); + if (eased) { + return triLinearInterpolation( + v000, v100, v010, v110, + v001, v101, v011, v111, + xl, yl, zl); + } else { + return triLinearInterpolationNoEase( + v000, v100, v010, v110, + v001, v101, v011, v111, + xl, yl, zl); + } } @@ -227,14 +282,14 @@ float noise2d_perlin_abs(float x, float y, int seed, float noise3d_perlin(float x, float y, float z, int seed, - int octaves, float persistence) + int octaves, float persistence, bool eased) { float a = 0; float f = 1.0; float g = 1.0; for (int i = 0; i < octaves; i++) { - a += g * noise3d_gradient(x * f, y * f, z * f, seed + i); + a += g * noise3d_gradient(x * f, y * f, z * f, seed + i, eased); f *= 2.0; g *= persistence; } @@ -243,14 +298,14 @@ float noise3d_perlin(float x, float y, float z, int seed, float noise3d_perlin_abs(float x, float y, float z, int seed, - int octaves, float persistence) + int octaves, float persistence, bool eased) { float a = 0; float f = 1.0; float g = 1.0; for (int i = 0; i < octaves; i++) { - a += g * fabs(noise3d_gradient(x * f, y * f, z * f, seed + i)); + a += g * fabs(noise3d_gradient(x * f, y * f, z * f, seed + i, eased)); f *= 2.0; g *= persistence; } @@ -258,30 +313,20 @@ float noise3d_perlin_abs(float x, float y, float z, int seed, } -// -1->0, 0->1, 1->0 float contour(float v) { v = fabs(v); if(v >= 1.0) return 0.0; - return (1.0-v); + return (1.0 - v); } ///////////////////////// [ New perlin stuff ] //////////////////////////// -Noise::Noise(NoiseParams *np, int seed, int sx, int sy) { - init(np, seed, sx, sy, 1); -} - - -Noise::Noise(NoiseParams *np, int seed, int sx, int sy, int sz) { - init(np, seed, sx, sy, sz); -} - - -void Noise::init(NoiseParams *np, int seed, int sx, int sy, int sz) { +Noise::Noise(NoiseParams *np, int seed, int sx, int sy, int sz) +{ this->np = np; this->seed = seed; this->sx = sx; @@ -296,19 +341,16 @@ void Noise::init(NoiseParams *np, int seed, int sx, int sy, int sz) { } -Noise::~Noise() { +Noise::~Noise() +{ delete[] buf; delete[] result; delete[] noisebuf; } -void Noise::setSize(int sx, int sy) { - setSize(sx, sy, 1); -} - - -void Noise::setSize(int sx, int sy, int sz) { +void Noise::setSize(int sx, int sy, int sz) +{ this->sx = sx; this->sy = sy; this->sz = sz; @@ -323,21 +365,24 @@ void Noise::setSize(int sx, int sy, int sz) { } -void Noise::setSpreadFactor(v3f spread) { +void Noise::setSpreadFactor(v3f spread) +{ this->np->spread = spread; resizeNoiseBuf(sz > 1); } -void Noise::setOctaves(int octaves) { +void Noise::setOctaves(int octaves) +{ this->np->octaves = octaves; resizeNoiseBuf(sz > 1); } -void Noise::resizeNoiseBuf(bool is3d) { +void Noise::resizeNoiseBuf(bool is3d) +{ int nlx, nly, nlz; float ofactor; @@ -370,7 +415,11 @@ void Noise::resizeNoiseBuf(bool is3d) { * next octave. */ #define idx(x, y) ((y) * nlx + (x)) -void Noise::gradientMap2D(float x, float y, float step_x, float step_y, int seed) { +void Noise::gradientMap2D( + float x, float y, + float step_x, float step_y, + int seed) +{ float v00, v01, v10, v11, u, v, orig_u; int index, i, j, x0, y0, noisex, noisey; int nlx, nly; @@ -424,15 +473,20 @@ void Noise::gradientMap2D(float x, float y, float step_x, float step_y, int seed #define idx(x, y, z) ((z) * nly * nlx + (y) * nlx + (x)) -void Noise::gradientMap3D(float x, float y, float z, - float step_x, float step_y, float step_z, - int seed) { +void Noise::gradientMap3D( + float x, float y, float z, + float step_x, float step_y, float step_z, + int seed, bool eased) +{ float v000, v010, v100, v110; float v001, v011, v101, v111; float u, v, w, orig_u, orig_v; int index, i, j, k, x0, y0, z0, noisex, noisey, noisez; int nlx, nly, nlz; + Interp3dFxn interpolate = eased ? + triLinearInterpolation : triLinearInterpolationNoEase; + x0 = floor(x); y0 = floor(y); z0 = floor(z); @@ -472,10 +526,11 @@ void Noise::gradientMap3D(float x, float y, float z, u = orig_u; noisex = 0; for (i = 0; i != sx; i++) { - buf[index++] = triLinearInterpolation( + buf[index++] = interpolate( v000, v100, v010, v110, v001, v101, v011, v111, u, v, w); + u += step_x; if (u >= 1.0) { u -= 1.0; @@ -508,27 +563,23 @@ void Noise::gradientMap3D(float x, float y, float z, #undef idx -float *Noise::perlinMap2D(float x, float y) { +float *Noise::perlinMap2D(float x, float y) +{ float f = 1.0, g = 1.0; - int i, j, index, oct; + size_t bufsize = sx * sy; x /= np->spread.X; y /= np->spread.Y; - memset(result, 0, sizeof(float) * sx * sy); + memset(result, 0, sizeof(float) * bufsize); - for (oct = 0; oct < np->octaves; oct++) { + for (int oct = 0; oct < np->octaves; oct++) { gradientMap2D(x * f, y * f, f / np->spread.X, f / np->spread.Y, seed + np->seed + oct); - index = 0; - for (j = 0; j != sy; j++) { - for (i = 0; i != sx; i++) { - result[index] += g * buf[index]; - index++; - } - } + for (size_t i = 0; i != bufsize; i++) + result[i] += g * buf[i]; f *= 2.0; g *= np->persist; @@ -538,31 +589,28 @@ float *Noise::perlinMap2D(float x, float y) { } -float *Noise::perlinMap2DModulated(float x, float y, float *persist_map) { +float *Noise::perlinMap2DModulated(float x, float y, float *persist_map) +{ float f = 1.0; - int i, j, index, oct; + size_t bufsize = sx * sy; x /= np->spread.X; y /= np->spread.Y; - memset(result, 0, sizeof(float) * sx * sy); - - float *g = new float[sx * sy]; - for (index = 0; index != sx * sy; index++) - g[index] = 1.0; + memset(result, 0, sizeof(float) * bufsize); + + float *g = new float[bufsize]; + for (size_t i = 0; i != bufsize; i++) + g[i] = 1.0; - for (oct = 0; oct < np->octaves; oct++) { + for (int oct = 0; oct < np->octaves; oct++) { gradientMap2D(x * f, y * f, f / np->spread.X, f / np->spread.Y, seed + np->seed + oct); - index = 0; - for (j = 0; j != sy; j++) { - for (i = 0; i != sx; i++) { - result[index] += g[index] * buf[index]; - g[index] *= persist_map[index]; - index++; - } + for (size_t i = 0; i != bufsize; i++) { + result[i] += g[i] * buf[i]; + g[i] *= persist_map[i]; } f *= 2.0; @@ -573,30 +621,24 @@ float *Noise::perlinMap2DModulated(float x, float y, float *persist_map) { } -float *Noise::perlinMap3D(float x, float y, float z) { +float *Noise::perlinMap3D(float x, float y, float z, bool eased) +{ float f = 1.0, g = 1.0; - int i, j, k, index, oct; + size_t bufsize = sx * sy * sz; x /= np->spread.X; y /= np->spread.Y; z /= np->spread.Z; - memset(result, 0, sizeof(float) * sx * sy * sz); + memset(result, 0, sizeof(float) * bufsize); - for (oct = 0; oct < np->octaves; oct++) { + for (int oct = 0; oct < np->octaves; oct++) { gradientMap3D(x * f, y * f, z * f, f / np->spread.X, f / np->spread.Y, f / np->spread.Z, - seed + np->seed + oct); + seed + np->seed + oct, eased); - index = 0; - for (k = 0; k != sz; k++) { - for (j = 0; j != sy; j++) { - for (i = 0; i != sx; i++) { - result[index] += g * buf[index]; - index++; - } - } - } + for (size_t i = 0; i != bufsize; i++) + result[i] += g * buf[i]; f *= 2.0; g *= np->persist; @@ -606,14 +648,15 @@ float *Noise::perlinMap3D(float x, float y, float z) { } -void Noise::transformNoiseMap() { - int i = 0; - for (int z = 0; z != sz; z++) { - for (int y = 0; y != sy; y++) { - for (int x = 0; x != sx; x++) { - result[i] = result[i] * np->scale + np->offset; - i++; - } - } +void Noise::transformNoiseMap() +{ + size_t i = 0; + + for (int z = 0; z != sz; z++) + for (int y = 0; y != sy; y++) + for (int x = 0; x != sx; x++) { + result[i] = result[i] * np->scale + np->offset; + i++; } } +