diff --git a/ChangeLog b/ChangeLog index 34a2c21..a3a2a4f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -21,6 +21,7 @@ Scenery : Rendering : * New texture model (perpendicular displacement and thickness). * Added full scene antialiasing (FSAA). + * Replaced old noise algorithm with Simplex Noise (up to 4 times faster). GUI : * Improved curve rendering. diff --git a/TODO b/TODO index c41109b..a7fe1b8 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,11 @@ Technology Preview 2 : +- Fully move layer management from BaseForm to BaseFormLayer. +- Replace math.h methods by optimized ones (fastfloor, fastsin...). +- Replace terrain canvas editor by full sculpting editor. + => Add a generation dialog, with fixed resolution. + => Store local terrain modifications in fully dynamic canvas. + => Add map preview with editor area. + => Allow camera move and zoom. - Finalize Preetham's model usage => Apply model to atmosphere (aerial perspective) => Find a proper model for night sky (maybe Shirley) @@ -6,15 +13,12 @@ Technology Preview 2 : - Keep skydome lights in cache for a render. - Add buttons to restore "auto" default values in tabs and dialogs. - Add "hardness to light" and shadow control ("minimum lighting") to material. + +Technlogy Preview 3 : - Add logarithmic sliders for some float values. - Improve previews. => Add user markers on OSD. => Add areas marking. -- Improve terrain canvas editor. - => Add GeoArea editor. - => Resample map on changing resolution. - => GeoAreas should not overlap. - => Map loading should not choose arbitrary resolution, choose the closer one and resample. - Improve textures (current model is greatly incorrect). => Separate models (basic texture and covering texture). => Covering texture height should inpact terrain height. @@ -29,7 +33,7 @@ Technology Preview 2 : - Lock some previews together (eg: terrain height and colored preview). - Find a new licence. -Technology Preview 3 : +Technology Preview 4 : - Restore render progress. - Store the terrain canvases in a tree to allow "multi-res" edition. - Implement High Dynamic Range. diff --git a/gui_qt/formclouds.cpp b/gui_qt/formclouds.cpp index b9313e7..8892a6c 100644 --- a/gui_qt/formclouds.cpp +++ b/gui_qt/formclouds.cpp @@ -166,9 +166,9 @@ FormClouds::FormClouds(QWidget *parent): addInputDouble(tr("Max coverage"), &_layer->base_coverage, 0.0, 1.0, 0.01, 0.1); addInputCurve(tr("Coverage by altitude"), _layer->coverage_by_altitude, 0.0, 1.0, 0.0, 1.0, tr("Altitude in cloud layer"), tr("Coverage value")); addInputNoise(tr("Shape noise"), _layer->shape_noise); - addInputDouble(tr("Shape scaling"), &_layer->shape_scaling, 1.0, 10.0, 0.1, 1.0); + addInputDouble(tr("Shape scaling"), &_layer->shape_scaling, 3.0, 30.0, 0.3, 3.0); addInputNoise(tr("Edge noise"), _layer->edge_noise); - addInputDouble(tr("Edge scaling"), &_layer->edge_scaling, 0.02, 0.5, 0.01, 0.1); + addInputDouble(tr("Edge scaling"), &_layer->edge_scaling, 0.06, 1.5, 0.03, 0.3); addInputDouble(tr("Edge length"), &_layer->edge_length, 0.0, 1.0, 0.01, 0.1); addInputMaterial(tr("Material"), &_layer->material); addInputDouble(tr("Hardness to light"), &_layer->hardness, 0.0, 1.0, 0.01, 0.1); diff --git a/gui_qt/formterrain.cpp b/gui_qt/formterrain.cpp index 9476537..ba8b99c 100644 --- a/gui_qt/formterrain.cpp +++ b/gui_qt/formterrain.cpp @@ -157,7 +157,7 @@ FormTerrain::FormTerrain(QWidget *parent): addInputNoise(tr("Noise"), _definition.height_noise); addInputDouble(tr("Height"), &_definition.height_factor, 0.0, 20.0, 0.1, 1.0); - addInputDouble(tr("Scaling"), &_definition.scaling, 1.0, 50.0, 0.1, 5.0); + addInputDouble(tr("Scaling"), &_definition.scaling, 20.0, 200.0, 1.0, 10.0); addInputDouble(tr("Shadow smoothing"), &_definition.shadow_smoothing, 0.0, 0.3, 0.003, 0.03); addInputLayers(tr("Canvases"), _definition.canvases, _formBuilderCanvas); diff --git a/gui_qt/formtextures.cpp b/gui_qt/formtextures.cpp index c51e736..bd17dad 100644 --- a/gui_qt/formtextures.cpp +++ b/gui_qt/formtextures.cpp @@ -146,7 +146,7 @@ FormTextures::FormTextures(QWidget *parent): addInputNoise(tr("Surface noise"), _layer->bump_noise); addInputDouble(tr("Surface noise height"), &_layer->bump_height, 0.0, 0.1, 0.001, 0.01); - addInputDouble(tr("Surface noise scaling"), &_layer->bump_scaling, 0.001, 0.1, 0.001, 0.01); + addInputDouble(tr("Surface noise scaling"), &_layer->bump_scaling, 0.003, 0.3, 0.003, 0.03); addInputMaterial(tr("Material"), &_layer->material); addInputCurve(tr("Coverage by altitude"), _supp.height_curve, -20.0, 20.0, 0.0, 1.0, tr("Terrain altitude"), tr("Texture coverage")); addInputCurve(tr("Coverage by slope"), _supp.slope_curve, 0.0, 5.0, 0.0, 1.0, tr("Terrain slope"), tr("Texture coverage")); diff --git a/gui_qt/formwater.cpp b/gui_qt/formwater.cpp index 15c39af..5f6e09c 100644 --- a/gui_qt/formwater.cpp +++ b/gui_qt/formwater.cpp @@ -222,7 +222,7 @@ FormWater::FormWater(QWidget *parent): addInputDouble(tr("Light-through distance"), &_definition.lighting_depth, 0.0, 20.0, 0.1, 1.0); addInputNoise(tr("Waves noise"), _definition.waves_noise); addInputDouble(tr("Waves height"), &_definition.waves_noise_height, 0.0, 0.1, 0.001, 0.01); - addInputDouble(tr("Waves scaling"), &_definition.waves_noise_scale, 0.01, 1.0, 0.01, 0.1); + addInputDouble(tr("Waves scaling"), &_definition.waves_noise_scale, 0.03, 3.0, 0.03, 0.3); revertConfig(); } diff --git a/gui_qt/widgetheightmap.cpp b/gui_qt/widgetheightmap.cpp index 5e2f263..054a387 100644 --- a/gui_qt/widgetheightmap.cpp +++ b/gui_qt/widgetheightmap.cpp @@ -38,7 +38,6 @@ WidgetHeightMap::WidgetHeightMap(QWidget *parent, HeightMap* heightmap): _brush_smoothing = 0.5; _brush_strength = 1.0; _brush_noise = noiseCreateGenerator(); - noiseGenerateBaseNoise(_brush_noise, 102400); noiseAddLevelsSimple(_brush_noise, 10, 1.0, 1.0); } diff --git a/lib_paysages/auto.c b/lib_paysages/auto.c index a062a3a..76c5332 100644 --- a/lib_paysages/auto.c +++ b/lib_paysages/auto.c @@ -96,8 +96,7 @@ void autoGenRealisticLandscape(int seed) water.depth_color.a = 1.0; water.lighting_depth = 3.0; water.waves_noise_height = 0.005; - water.waves_noise_scale = 0.07; - noiseGenerateBaseNoise(water.waves_noise, 262144); + water.waves_noise_scale = 0.21; noiseClearLevels(water.waves_noise); noiseAddLevelsSimple(water.waves_noise, 2, 1.0, 1.0); noiseAddLevelsSimple(water.waves_noise, 3, 0.15, 0.1); @@ -136,11 +135,10 @@ void autoGenRealisticLandscape(int seed) /* Terrain */ terrain = terrainCreateDefinition(); - noiseGenerateBaseNoise(terrain.height_noise, 1048576); noiseClearLevels(terrain.height_noise); noiseAddLevelsSimple(terrain.height_noise, 10, 1.0, 1.0); terrain.height_factor = 12.0 / noiseGetMaxValue(terrain.height_noise); - terrain.scaling = 20.0; + terrain.scaling = 60.0; terrain.shadow_smoothing = 0.03; scenerySetTerrain(&terrain); terrainDeleteDefinition(&terrain); @@ -150,11 +148,10 @@ void autoGenRealisticLandscape(int seed) layer = layersAddLayer(textures.layers, NULL); layersSetName(textures.layers, layer, "Ground"); texture = layersGetLayer(textures.layers, layer); - noiseGenerateBaseNoise(texture->bump_noise, 102400); noiseClearLevels(texture->bump_noise); noiseAddLevelsSimple(texture->bump_noise, 8, 1.0, 1.0); texture->bump_height = 0.01; - texture->bump_scaling = 0.015; + texture->bump_scaling = 0.045; texture->material.base.r = 0.6; texture->material.base.g = 0.55; texture->material.base.b = 0.57; @@ -168,16 +165,15 @@ void autoGenRealisticLandscape(int seed) texture = layersGetLayer(textures.layers, layer); zoneAddHeightRangeQuick(texture->zone, 1.0, -6.0, -5.0, 3.0, 15.0); zoneAddSlopeRangeQuick(texture->zone, 1.0, 0.0, 0.0, 0.05, 0.4); - noiseGenerateBaseNoise(texture->bump_noise, 102400); noiseClearLevels(texture->bump_noise); noiseAddLevelsSimple(texture->bump_noise, 5, 1.0, 0.4); noiseAddLevelsSimple(texture->bump_noise, 2, 0.03, 0.08); texture->bump_height = 0.002; - texture->bump_scaling = 0.01; + texture->bump_scaling = 0.03; texture->material.base.r = 0.12; texture->material.base.g = 0.19; texture->material.base.b = 0.035; - texture->material.reflection = 0.1; + texture->material.reflection = 0.03; texture->material.shininess = 2.0; texture->thickness = 0.02; texture->slope_range = 0.03; diff --git a/lib_paysages/clouds.c b/lib_paysages/clouds.c index e3652bc..d122cac 100644 --- a/lib_paysages/clouds.c +++ b/lib_paysages/clouds.c @@ -88,15 +88,13 @@ CloudsLayerDefinition* cloudsLayerCreateDefinition() result->transparencydepth = 1.5; result->lighttraversal = 7.0; result->minimumlight = 0.4; - result->shape_scaling = 3.5; - result->edge_scaling = 0.07; + result->shape_scaling = 10.0; + result->edge_scaling = 0.2; result->edge_length = 0.2; result->base_coverage = 0.35; result->shape_noise = noiseCreateGenerator(); - noiseGenerateBaseNoise(result->shape_noise, 200000); noiseAddLevelsSimple(result->shape_noise, 5, 1.0, 1.0); result->edge_noise = noiseCreateGenerator(); - noiseGenerateBaseNoise(result->edge_noise, 800000); noiseAddLevelsSimple(result->edge_noise, 8, 1.0, 1.0); result->_custom_coverage = _standardCoverageFunc; @@ -359,7 +357,7 @@ static int _findSegments(CloudsLayerDefinition* definition, Renderer* renderer, } render_precision = 15.2 - 1.5 * (double)renderer->render_quality; - render_precision = render_precision * definition->shape_scaling / 50.0; + render_precision = render_precision * definition->shape_scaling / 150.0; if (render_precision > max_total_length / 10.0) { render_precision = max_total_length / 10.0; diff --git a/lib_paysages/noise.c b/lib_paysages/noise.c index f758b0c..22bfd0f 100644 --- a/lib_paysages/noise.c +++ b/lib_paysages/noise.c @@ -5,6 +5,7 @@ #include #include "tools.h" +#include "simplexnoise.h" #define MAX_LEVEL_COUNT 30 @@ -12,9 +13,6 @@ struct NoiseLevel; struct NoiseGenerator { - int size1; - int size2; - int size3; double height_offset; int level_count; struct NoiseLevel levels[MAX_LEVEL_COUNT]; @@ -22,53 +20,23 @@ struct NoiseGenerator double _max_height; }; -static int _noise_pool_size; -static double* _noise_pool; - -static inline double _cubicInterpolate(double* p, double x) -{ - return p[1] + 0.5 * x * (p[2] - p[0] + x * (2.0 * p[0] - 5.0 * p[1] + 4.0 * p[2] - p[3] + x * (3.0 * (p[1] - p[2]) + p[3] - p[0]))); -} - void noiseInit() { - int i; - - _noise_pool_size = 1048576; - _noise_pool = malloc(sizeof(double) * _noise_pool_size); - - for (i = 0; i < _noise_pool_size; i++) - { - _noise_pool[i] = toolsRandom() - 0.5; - } + simplexNoiseInit(); } void noiseQuit() { - free(_noise_pool); } void noiseSave(PackStream* stream) { - int i; - - packWriteInt(stream, &_noise_pool_size); - for (i = 0; i < _noise_pool_size; i++) - { - packWriteDouble(stream, _noise_pool + i); - } + UNUSED(stream); } void noiseLoad(PackStream* stream) { - int i; - - packReadInt(stream, &_noise_pool_size); - _noise_pool = realloc(_noise_pool, sizeof(double) * _noise_pool_size); - for (i = 0; i < _noise_pool_size; i++) - { - packReadDouble(stream, _noise_pool + i); - } + UNUSED(stream); } NoiseGenerator* noiseCreateGenerator() @@ -77,9 +45,6 @@ NoiseGenerator* noiseCreateGenerator() /* initialize */ result = malloc(sizeof(NoiseGenerator)); - result->size1 = 1; - result->size2 = 1; - result->size3 = 1; result->level_count = 0; result->height_offset = 0.0; @@ -93,19 +58,16 @@ void noiseDeleteGenerator(NoiseGenerator* generator) free(generator); } -void noiseSaveGenerator(PackStream* stream, NoiseGenerator* perlin) +void noiseSaveGenerator(PackStream* stream, NoiseGenerator* generator) { int x; - packWriteInt(stream, &perlin->size1); - packWriteInt(stream, &perlin->size2); - packWriteInt(stream, &perlin->size3); - packWriteDouble(stream, &perlin->height_offset); - packWriteInt(stream, &perlin->level_count); + packWriteDouble(stream, &generator->height_offset); + packWriteInt(stream, &generator->level_count); - for (x = 0; x < perlin->level_count; x++) + for (x = 0; x < generator->level_count; x++) { - NoiseLevel* level = perlin->levels + x; + NoiseLevel* level = generator->levels + x; packWriteDouble(stream, &level->scaling); packWriteDouble(stream, &level->height); @@ -115,19 +77,16 @@ void noiseSaveGenerator(PackStream* stream, NoiseGenerator* perlin) } } -void noiseLoadGenerator(PackStream* stream, NoiseGenerator* perlin) +void noiseLoadGenerator(PackStream* stream, NoiseGenerator* generator) { int x; - packReadInt(stream, &perlin->size1); - packReadInt(stream, &perlin->size2); - packReadInt(stream, &perlin->size3); - packReadDouble(stream, &perlin->height_offset); - packReadInt(stream, &perlin->level_count); + packReadDouble(stream, &generator->height_offset); + packReadInt(stream, &generator->level_count); - for (x = 0; x < perlin->level_count; x++) + for (x = 0; x < generator->level_count; x++) { - NoiseLevel* level = perlin->levels + x; + NoiseLevel* level = generator->levels + x; packReadDouble(stream, &level->scaling); packReadDouble(stream, &level->height); @@ -136,14 +95,11 @@ void noiseLoadGenerator(PackStream* stream, NoiseGenerator* perlin) packReadDouble(stream, &level->zoffset); } - noiseValidate(perlin); + noiseValidate(generator); } void noiseCopy(NoiseGenerator* source, NoiseGenerator* destination) { - destination->size1 = source->size1; - destination->size2 = source->size2; - destination->size3 = source->size3; destination->height_offset = source->height_offset; destination->level_count = source->level_count; @@ -165,16 +121,6 @@ void noiseValidate(NoiseGenerator* generator) generator->_max_height = max_height; } -void noiseGenerateBaseNoise(NoiseGenerator* generator, int size) -{ - size = (size < 1) ? 1 : size; - size = (size > _noise_pool_size) ? _noise_pool_size : size; - - generator->size1 = size; - generator->size2 = (int)floor(sqrt((double)size)); - generator->size3 = (int)floor(cbrt((double)size)); -} - void noiseForceValue(NoiseGenerator* generator, double value) { noiseClearLevels(generator); @@ -182,11 +128,6 @@ void noiseForceValue(NoiseGenerator* generator, double value) noiseAddLevelSimple(generator, 1.0, 0.0); /* FIXME Should not be needed */ } -int noiseGetBaseSize(NoiseGenerator* generator) -{ - return generator->size1; -} - double noiseGetMaxValue(NoiseGenerator* generator) { return generator->_max_height; @@ -333,46 +274,12 @@ void noiseNormalizeHeight(NoiseGenerator* generator, double min_height, double m static inline double _get1DRawNoiseValue(NoiseGenerator* generator, double x) { - int size = generator->size1; - - int xbase = (int)floor(x); - - double xinternal = x - (double)xbase; - - int x0 = (xbase - 1) % size; - if (x0 < 0) - { - x0 += size; - } - int x1 = xbase % size; - if (x1 < 0) - { - x1 += size; - } - int x2 = (xbase + 1) % size; - if (x2 < 0) - { - x2 += size; - } - int x3 = (xbase + 2) % size; - if (x3 < 0) - { - x3 += size; - } - - double buf_cubic_x[4]; - - buf_cubic_x[0] = _noise_pool[x0 % _noise_pool_size]; - buf_cubic_x[1] = _noise_pool[x1 % _noise_pool_size]; - buf_cubic_x[2] = _noise_pool[x2 % _noise_pool_size]; - buf_cubic_x[3] = _noise_pool[x3 % _noise_pool_size]; - - return _cubicInterpolate(buf_cubic_x, xinternal); + return simplexNoiseGet2DValue(x, 0.0) * 0.5; } static inline double _get1DLevelValue(NoiseGenerator* generator, NoiseLevel* level, double x) { - return _get1DRawNoiseValue(generator, x / level->scaling + level->xoffset * generator->size1) * level->height; + return _get1DRawNoiseValue(generator, x / level->scaling + level->xoffset) * level->height; } double noiseGet1DLevel(NoiseGenerator* generator, int level, double x) @@ -429,89 +336,12 @@ double noiseGet1DDetail(NoiseGenerator* generator, double x, double detail) static inline double _get2DRawNoiseValue(NoiseGenerator* generator, double x, double y) { - int size = generator->size2; - - int xbase = (int)floor(x); - int ybase = (int)floor(y); - - double xinternal = x - (double)xbase; - double yinternal = y - (double)ybase; - - int x0 = (xbase - 1) % size; - if (x0 < 0) - { - x0 += size; - } - int x1 = xbase % size; - if (x1 < 0) - { - x1 += size; - } - int x2 = (xbase + 1) % size; - if (x2 < 0) - { - x2 += size; - } - int x3 = (xbase + 2) % size; - if (x3 < 0) - { - x3 += size; - } - - int y0 = (ybase - 1) % size; - if (y0 < 0) - { - y0 += size; - } - int y1 = ybase % size; - if (y1 < 0) - { - y1 += size; - } - int y2 = (ybase + 1) % size; - if (y2 < 0) - { - y2 += size; - } - int y3 = (ybase + 2) % size; - if (y3 < 0) - { - y3 += size; - } - - double buf_cubic_x[4]; - double buf_cubic_y[4]; - - buf_cubic_x[0] = _noise_pool[(y0 * size + x0) % _noise_pool_size]; - buf_cubic_x[1] = _noise_pool[(y0 * size + x1) % _noise_pool_size]; - buf_cubic_x[2] = _noise_pool[(y0 * size + x2) % _noise_pool_size]; - buf_cubic_x[3] = _noise_pool[(y0 * size + x3) % _noise_pool_size]; - buf_cubic_y[0] = _cubicInterpolate(buf_cubic_x, xinternal); - - buf_cubic_x[0] = _noise_pool[(y1 * size + x0) % _noise_pool_size]; - buf_cubic_x[1] = _noise_pool[(y1 * size + x1) % _noise_pool_size]; - buf_cubic_x[2] = _noise_pool[(y1 * size + x2) % _noise_pool_size]; - buf_cubic_x[3] = _noise_pool[(y1 * size + x3) % _noise_pool_size]; - buf_cubic_y[1] = _cubicInterpolate(buf_cubic_x, xinternal); - - buf_cubic_x[0] = _noise_pool[(y2 * size + x0) % _noise_pool_size]; - buf_cubic_x[1] = _noise_pool[(y2 * size + x1) % _noise_pool_size]; - buf_cubic_x[2] = _noise_pool[(y2 * size + x2) % _noise_pool_size]; - buf_cubic_x[3] = _noise_pool[(y2 * size + x3) % _noise_pool_size]; - buf_cubic_y[2] = _cubicInterpolate(buf_cubic_x, xinternal); - - buf_cubic_x[0] = _noise_pool[(y3 * size + x0) % _noise_pool_size]; - buf_cubic_x[1] = _noise_pool[(y3 * size + x1) % _noise_pool_size]; - buf_cubic_x[2] = _noise_pool[(y3 * size + x2) % _noise_pool_size]; - buf_cubic_x[3] = _noise_pool[(y3 * size + x3) % _noise_pool_size]; - buf_cubic_y[3] = _cubicInterpolate(buf_cubic_x, xinternal); - - return _cubicInterpolate(buf_cubic_y, yinternal); + return simplexNoiseGet2DValue(x, y) * 0.5; } static inline double _get2DLevelValue(NoiseGenerator* generator, NoiseLevel* level, double x, double y) { - return _get2DRawNoiseValue(generator, x / level->scaling + level->xoffset * generator->size2, y / level->scaling + level->yoffset * generator->size2) * level->height; + return _get2DRawNoiseValue(generator, x / level->scaling + level->xoffset, y / level->scaling + level->yoffset) * level->height; } double noiseGet2DLevel(NoiseGenerator* generator, int level, double x, double y) @@ -568,193 +398,12 @@ double noiseGet2DDetail(NoiseGenerator* generator, double x, double y, double de static inline double _get3DRawNoiseValue(NoiseGenerator* generator, double x, double y, double z) { - int size = generator->size3; - - int xbase = (int)floor(x); - int ybase = (int)floor(y); - int zbase = (int)floor(z); - - double xinternal = x - (double)xbase; - double yinternal = y - (double)ybase; - double zinternal = z - (double)zbase; - - int x0 = (xbase - 1) % size; - if (x0 < 0) - { - x0 += size; - } - int x1 = xbase % size; - if (x1 < 0) - { - x1 += size; - } - int x2 = (xbase + 1) % size; - if (x2 < 0) - { - x2 += size; - } - int x3 = (xbase + 2) % size; - if (x3 < 0) - { - x3 += size; - } - - int y0 = (ybase - 1) % size; - if (y0 < 0) - { - y0 += size; - } - int y1 = ybase % size; - if (y1 < 0) - { - y1 += size; - } - int y2 = (ybase + 1) % size; - if (y2 < 0) - { - y2 += size; - } - int y3 = (ybase + 2) % size; - if (y3 < 0) - { - y3 += size; - } - - int z0 = (zbase - 1) % size; - if (z0 < 0) - { - z0 += size; - } - int z1 = zbase % size; - if (z1 < 0) - { - z1 += size; - } - int z2 = (zbase + 1) % size; - if (z2 < 0) - { - z2 += size; - } - int z3 = (zbase + 2) % size; - if (z3 < 0) - { - z3 += size; - } - - double buf_cubic_x[4]; - double buf_cubic_y[4]; - double buf_cubic_z[4]; - - buf_cubic_x[0] = _noise_pool[(y0 * size * size + x0 * size + z0) % _noise_pool_size]; - buf_cubic_x[1] = _noise_pool[(y0 * size * size + x1 * size + z0) % _noise_pool_size]; - buf_cubic_x[2] = _noise_pool[(y0 * size * size + x2 * size + z0) % _noise_pool_size]; - buf_cubic_x[3] = _noise_pool[(y0 * size * size + x3 * size + z0) % _noise_pool_size]; - buf_cubic_y[0] = _cubicInterpolate(buf_cubic_x, xinternal); - - buf_cubic_x[0] = _noise_pool[(y1 * size * size + x0 * size + z0) % _noise_pool_size]; - buf_cubic_x[1] = _noise_pool[(y1 * size * size + x1 * size + z0) % _noise_pool_size]; - buf_cubic_x[2] = _noise_pool[(y1 * size * size + x2 * size + z0) % _noise_pool_size]; - buf_cubic_x[3] = _noise_pool[(y1 * size * size + x3 * size + z0) % _noise_pool_size]; - buf_cubic_y[1] = _cubicInterpolate(buf_cubic_x, xinternal); - - buf_cubic_x[0] = _noise_pool[(y2 * size * size + x0 * size + z0) % _noise_pool_size]; - buf_cubic_x[1] = _noise_pool[(y2 * size * size + x1 * size + z0) % _noise_pool_size]; - buf_cubic_x[2] = _noise_pool[(y2 * size * size + x2 * size + z0) % _noise_pool_size]; - buf_cubic_x[3] = _noise_pool[(y2 * size * size + x3 * size + z0) % _noise_pool_size]; - buf_cubic_y[2] = _cubicInterpolate(buf_cubic_x, xinternal); - - buf_cubic_x[0] = _noise_pool[(y3 * size * size + x0 * size + z0) % _noise_pool_size]; - buf_cubic_x[1] = _noise_pool[(y3 * size * size + x1 * size + z0) % _noise_pool_size]; - buf_cubic_x[2] = _noise_pool[(y3 * size * size + x2 * size + z0) % _noise_pool_size]; - buf_cubic_x[3] = _noise_pool[(y3 * size * size + x3 * size + z0) % _noise_pool_size]; - buf_cubic_y[3] = _cubicInterpolate(buf_cubic_x, xinternal); - - buf_cubic_z[0] = _cubicInterpolate(buf_cubic_y, yinternal); - - buf_cubic_x[0] = _noise_pool[(y0 * size * size + x0 * size + z1) % _noise_pool_size]; - buf_cubic_x[1] = _noise_pool[(y0 * size * size + x1 * size + z1) % _noise_pool_size]; - buf_cubic_x[2] = _noise_pool[(y0 * size * size + x2 * size + z1) % _noise_pool_size]; - buf_cubic_x[3] = _noise_pool[(y0 * size * size + x3 * size + z1) % _noise_pool_size]; - buf_cubic_y[0] = _cubicInterpolate(buf_cubic_x, xinternal); - - buf_cubic_x[0] = _noise_pool[(y1 * size * size + x0 * size + z1) % _noise_pool_size]; - buf_cubic_x[1] = _noise_pool[(y1 * size * size + x1 * size + z1) % _noise_pool_size]; - buf_cubic_x[2] = _noise_pool[(y1 * size * size + x2 * size + z1) % _noise_pool_size]; - buf_cubic_x[3] = _noise_pool[(y1 * size * size + x3 * size + z1) % _noise_pool_size]; - buf_cubic_y[1] = _cubicInterpolate(buf_cubic_x, xinternal); - - buf_cubic_x[0] = _noise_pool[(y2 * size * size + x0 * size + z1) % _noise_pool_size]; - buf_cubic_x[1] = _noise_pool[(y2 * size * size + x1 * size + z1) % _noise_pool_size]; - buf_cubic_x[2] = _noise_pool[(y2 * size * size + x2 * size + z1) % _noise_pool_size]; - buf_cubic_x[3] = _noise_pool[(y2 * size * size + x3 * size + z1) % _noise_pool_size]; - buf_cubic_y[2] = _cubicInterpolate(buf_cubic_x, xinternal); - - buf_cubic_x[0] = _noise_pool[(y3 * size * size + x0 * size + z1) % _noise_pool_size]; - buf_cubic_x[1] = _noise_pool[(y3 * size * size + x1 * size + z1) % _noise_pool_size]; - buf_cubic_x[2] = _noise_pool[(y3 * size * size + x2 * size + z1) % _noise_pool_size]; - buf_cubic_x[3] = _noise_pool[(y3 * size * size + x3 * size + z1) % _noise_pool_size]; - buf_cubic_y[3] = _cubicInterpolate(buf_cubic_x, xinternal); - - buf_cubic_z[1] = _cubicInterpolate(buf_cubic_y, yinternal); - - buf_cubic_x[0] = _noise_pool[(y0 * size * size + x0 * size + z2) % _noise_pool_size]; - buf_cubic_x[1] = _noise_pool[(y0 * size * size + x1 * size + z2) % _noise_pool_size]; - buf_cubic_x[2] = _noise_pool[(y0 * size * size + x2 * size + z2) % _noise_pool_size]; - buf_cubic_x[3] = _noise_pool[(y0 * size * size + x3 * size + z2) % _noise_pool_size]; - buf_cubic_y[0] = _cubicInterpolate(buf_cubic_x, xinternal); - - buf_cubic_x[0] = _noise_pool[(y1 * size * size + x0 * size + z2) % _noise_pool_size]; - buf_cubic_x[1] = _noise_pool[(y1 * size * size + x1 * size + z2) % _noise_pool_size]; - buf_cubic_x[2] = _noise_pool[(y1 * size * size + x2 * size + z2) % _noise_pool_size]; - buf_cubic_x[3] = _noise_pool[(y1 * size * size + x3 * size + z2) % _noise_pool_size]; - buf_cubic_y[1] = _cubicInterpolate(buf_cubic_x, xinternal); - - buf_cubic_x[0] = _noise_pool[(y2 * size * size + x0 * size + z2) % _noise_pool_size]; - buf_cubic_x[1] = _noise_pool[(y2 * size * size + x1 * size + z2) % _noise_pool_size]; - buf_cubic_x[2] = _noise_pool[(y2 * size * size + x2 * size + z2) % _noise_pool_size]; - buf_cubic_x[3] = _noise_pool[(y2 * size * size + x3 * size + z2) % _noise_pool_size]; - buf_cubic_y[2] = _cubicInterpolate(buf_cubic_x, xinternal); - - buf_cubic_x[0] = _noise_pool[(y3 * size * size + x0 * size + z2) % _noise_pool_size]; - buf_cubic_x[1] = _noise_pool[(y3 * size * size + x1 * size + z2) % _noise_pool_size]; - buf_cubic_x[2] = _noise_pool[(y3 * size * size + x2 * size + z2) % _noise_pool_size]; - buf_cubic_x[3] = _noise_pool[(y3 * size * size + x3 * size + z2) % _noise_pool_size]; - buf_cubic_y[3] = _cubicInterpolate(buf_cubic_x, xinternal); - - buf_cubic_z[2] = _cubicInterpolate(buf_cubic_y, yinternal); - - buf_cubic_x[0] = _noise_pool[(y0 * size * size + x0 * size + z3) % _noise_pool_size]; - buf_cubic_x[1] = _noise_pool[(y0 * size * size + x1 * size + z3) % _noise_pool_size]; - buf_cubic_x[2] = _noise_pool[(y0 * size * size + x2 * size + z3) % _noise_pool_size]; - buf_cubic_x[3] = _noise_pool[(y0 * size * size + x3 * size + z3) % _noise_pool_size]; - buf_cubic_y[0] = _cubicInterpolate(buf_cubic_x, xinternal); - - buf_cubic_x[0] = _noise_pool[(y1 * size * size + x0 * size + z3) % _noise_pool_size]; - buf_cubic_x[1] = _noise_pool[(y1 * size * size + x1 * size + z3) % _noise_pool_size]; - buf_cubic_x[2] = _noise_pool[(y1 * size * size + x2 * size + z3) % _noise_pool_size]; - buf_cubic_x[3] = _noise_pool[(y1 * size * size + x3 * size + z3) % _noise_pool_size]; - buf_cubic_y[1] = _cubicInterpolate(buf_cubic_x, xinternal); - - buf_cubic_x[0] = _noise_pool[(y2 * size * size + x0 * size + z3) % _noise_pool_size]; - buf_cubic_x[1] = _noise_pool[(y2 * size * size + x1 * size + z3) % _noise_pool_size]; - buf_cubic_x[2] = _noise_pool[(y2 * size * size + x2 * size + z3) % _noise_pool_size]; - buf_cubic_x[3] = _noise_pool[(y2 * size * size + x3 * size + z3) % _noise_pool_size]; - buf_cubic_y[2] = _cubicInterpolate(buf_cubic_x, xinternal); - - buf_cubic_x[0] = _noise_pool[(y3 * size * size + x0 * size + z3) % _noise_pool_size]; - buf_cubic_x[1] = _noise_pool[(y3 * size * size + x1 * size + z3) % _noise_pool_size]; - buf_cubic_x[2] = _noise_pool[(y3 * size * size + x2 * size + z3) % _noise_pool_size]; - buf_cubic_x[3] = _noise_pool[(y3 * size * size + x3 * size + z3) % _noise_pool_size]; - buf_cubic_y[3] = _cubicInterpolate(buf_cubic_x, xinternal); - - buf_cubic_z[3] = _cubicInterpolate(buf_cubic_y, yinternal); - - return _cubicInterpolate(buf_cubic_z, zinternal); + return simplexNoiseGet3DValue(x, y, z) * 0.5; } static inline double _get3DLevelValue(NoiseGenerator* generator, NoiseLevel* level, double x, double y, double z) { - return _get3DRawNoiseValue(generator, x / level->scaling + level->xoffset * generator->size3, y / level->scaling + level->yoffset * generator->size3, z / level->scaling + level->zoffset * generator->size3) * level->height; + return _get3DRawNoiseValue(generator, x / level->scaling + level->xoffset, y / level->scaling + level->yoffset, z / level->scaling + level->zoffset) * level->height; } double noiseGet3DLevel(NoiseGenerator* generator, int level, double x, double y, double z) diff --git a/lib_paysages/noise.h b/lib_paysages/noise.h index 1aed3a6..1e97d14 100644 --- a/lib_paysages/noise.h +++ b/lib_paysages/noise.h @@ -25,13 +25,11 @@ void noiseLoad(PackStream* stream); NoiseGenerator* noiseCreateGenerator(); void noiseDeleteGenerator(NoiseGenerator* generator); -void noiseSaveGenerator(PackStream* stream, NoiseGenerator* perlin); -void noiseLoadGenerator(PackStream* stream, NoiseGenerator* perlin); +void noiseSaveGenerator(PackStream* stream, NoiseGenerator* generator); +void noiseLoadGenerator(PackStream* stream, NoiseGenerator* generator); void noiseCopy(NoiseGenerator* source, NoiseGenerator* destination); void noiseValidate(NoiseGenerator* generator); -void noiseGenerateBaseNoise(NoiseGenerator* generator, int size); void noiseForceValue(NoiseGenerator* generator, double value); -int noiseGetBaseSize(NoiseGenerator* generator); double noiseGetMaxValue(NoiseGenerator* generator); int noiseGetLevelCount(NoiseGenerator* generator); void noiseClearLevels(NoiseGenerator* generator); diff --git a/lib_paysages/simplexnoise.c b/lib_paysages/simplexnoise.c new file mode 100644 index 0000000..a588ff2 --- /dev/null +++ b/lib_paysages/simplexnoise.c @@ -0,0 +1,467 @@ +#include "simplexnoise.h" + +/* + * Simplex noise implementation. + * + * Based on Stefan Gustavson implementation. + */ + +#include +#include +#include + +typedef struct +{ + double x; + double y; + double z; +} Grad3; + +typedef struct +{ + double x; + double y; + double z; + double w; +} Grad4; + +static Grad3 _grad3[] = { + {1, 1, 0}, + {-1, 1, 0}, + {1, -1, 0}, + {-1, -1, 0}, + {1, 0, 1}, + {-1, 0, 1}, + {1, 0, -1}, + {-1, 0, -1}, + {0, 1, 1}, + {0, -1, 1}, + {0, 1, -1}, + {0, -1, -1} +}; + +static Grad4 _grad4[] = { + {0, 1, 1, 1}, + {0, 1, 1, -1}, + {0, 1, -1, 1}, + {0, 1, -1, -1}, + {0, -1, 1, 1}, + {0, -1, 1, -1}, + {0, -1, -1, 1}, + {0, -1, -1, -1}, + {1, 0, 1, 1}, + {1, 0, 1, -1}, + {1, 0, -1, 1}, + {1, 0, -1, -1}, + {-1, 0, 1, 1}, + {-1, 0, 1, -1}, + {-1, 0, -1, 1}, + {-1, 0, -1, -1}, + {1, 1, 0, 1}, + {1, 1, 0, -1}, + {1, -1, 0, 1}, + {1, -1, 0, -1}, + {-1, 1, 0, 1}, + {-1, 1, 0, -1}, + {-1, -1, 0, 1}, + {-1, -1, 0, -1}, + {1, 1, 1, 0}, + {1, 1, -1, 0}, + {1, -1, 1, 0}, + {1, -1, -1, 0}, + {-1, 1, 1, 0}, + {-1, 1, -1, 0}, + {-1, -1, 1, 0}, + {-1, -1, -1, 0} +}; + +static short _permutations[] = {151, 160, 137, 91, 90, 15, + 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 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, 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, 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, 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, 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, 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, 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, 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, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180}; +static short _permutations2[512]; +static short _permutationsMod12[512]; + +static double _F2; +static double _G2; +static double _F3; +static double _G3; +static double _F4; +static double _G4; + +static inline int _fastfloor(double x) +{ + int xi = (int) x; + return x < xi ? xi - 1 : xi; +} + +static double _dot2(Grad3 g, double x, double y) +{ + return g.x * x + g.y * y; +} + +static double _dot3(Grad3 g, double x, double y, double z) +{ + return g.x * x + g.y * y + g.z * z; +} + +static double _dot4(Grad4 g, double x, double y, double z, double w) +{ + return g.x * x + g.y * y + g.z * z + g.w * w; +} + +void simplexNoiseInit() +{ + int i; + + /* To remove the need for index wrapping, double the permutation table length */ + for (i = 0; i < 512; i++) + { + _permutations2[i] = _permutations[i & 255]; + _permutationsMod12[i] = (short) (_permutations2[i] % 12); + } + + /* Skewing and unskewing factors for 2, 3, and 4 dimensions */ + _F2 = 0.5 * (sqrt(3.0) - 1.0); + _G2 = (3.0 - sqrt(3.0)) / 6.0; + _F3 = 1.0 / 3.0; + _G3 = 1.0 / 6.0; + _F4 = (sqrt(5.0) - 1.0) / 4.0; + _G4 = (5.0 - sqrt(5.0)) / 20.0; +} + +double simplexNoiseGet2DValue(double xin, double yin) +{ + double n0, n1, n2; /* Noise contributions from the three corners */ + /* Skew the input space to determine which simplex cell we're in */ + double s = (xin + yin) * _F2; /* Hairy factor for 2D */ + int i = _fastfloor(xin + s); + int j = _fastfloor(yin + 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 = xin - X0; /* The x,y distances from the cell origin */ + double y0 = yin - 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 [-1,1]. */ + return 70.0 * (n0 + n1 + n2); +} + +double simplexNoiseGet3DValue(double xin, double yin, double zin) +{ + 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 = (xin + yin + zin) * _F3; /* Very nice and simple skew factor for 3D */ + int i = _fastfloor(xin + s); + int j = _fastfloor(yin + s); + int k = _fastfloor(zin + 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 = xin - X0; /* The x,y,z distances from the cell origin */ + double y0 = yin - Y0; + double z0 = zin - 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 y0) rankx++; + else ranky++; + if (x0 > z0) rankx++; + else rankz++; + if (x0 > w0) rankx++; + else rankw++; + if (y0 > z0) ranky++; + else rankz++; + if (y0 > w0) ranky++; + else rankw++; + if (z0 > w0) rankz++; + else rankw++; + int i1, j1, k1, l1; /* The integer offsets for the second simplex corner */ + int i2, j2, k2, l2; /* The integer offsets for the third simplex corner */ + int i3, j3, k3, l3; /* The integer offsets for the fourth simplex corner */ + /* simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order. + Many values of c will never occur, since e.g. x>y>z>w makes x= 3 ? 1 : 0; + j1 = ranky >= 3 ? 1 : 0; + k1 = rankz >= 3 ? 1 : 0; + l1 = rankw >= 3 ? 1 : 0; + /* Rank 2 denotes the second largest coordinate. */ + i2 = rankx >= 2 ? 1 : 0; + j2 = ranky >= 2 ? 1 : 0; + k2 = rankz >= 2 ? 1 : 0; + l2 = rankw >= 2 ? 1 : 0; + /* Rank 1 denotes the second smallest coordinate. */ + i3 = rankx >= 1 ? 1 : 0; + j3 = ranky >= 1 ? 1 : 0; + k3 = rankz >= 1 ? 1 : 0; + l3 = rankw >= 1 ? 1 : 0; + /* The fifth corner has all coordinate offsets = 1, so no need to compute that. */ + double x1 = x0 - i1 + _G4; /* Offsets for second corner in (x,y,z,w) coords */ + double y1 = y0 - j1 + _G4; + double z1 = z0 - k1 + _G4; + double w1 = w0 - l1 + _G4; + double x2 = x0 - i2 + 2.0 * _G4; /* Offsets for third corner in (x,y,z,w) coords */ + double y2 = y0 - j2 + 2.0 * _G4; + double z2 = z0 - k2 + 2.0 * _G4; + double w2 = w0 - l2 + 2.0 * _G4; + double x3 = x0 - i3 + 3.0 * _G4; /* Offsets for fourth corner in (x,y,z,w) coords */ + double y3 = y0 - j3 + 3.0 * _G4; + double z3 = z0 - k3 + 3.0 * _G4; + double w3 = w0 - l3 + 3.0 * _G4; + double x4 = x0 - 1.0 + 4.0 * _G4; /* Offsets for last corner in (x,y,z,w) coords */ + double y4 = y0 - 1.0 + 4.0 * _G4; + double z4 = z0 - 1.0 + 4.0 * _G4; + double w4 = w0 - 1.0 + 4.0 * _G4; + /* Work out the hashed gradient indices of the five simplex corners */ + int ii = i & 255; + int jj = j & 255; + int kk = k & 255; + int ll = l & 255; + int gi0 = _permutations2[ii + _permutations2[jj + _permutations2[kk + _permutations2[ll]]]] % 32; + int gi1 = _permutations2[ii + i1 + _permutations2[jj + j1 + _permutations2[kk + k1 + _permutations2[ll + l1]]]] % 32; + int gi2 = _permutations2[ii + i2 + _permutations2[jj + j2 + _permutations2[kk + k2 + _permutations2[ll + l2]]]] % 32; + int gi3 = _permutations2[ii + i3 + _permutations2[jj + j3 + _permutations2[kk + k3 + _permutations2[ll + l3]]]] % 32; + int gi4 = _permutations2[ii + 1 + _permutations2[jj + 1 + _permutations2[kk + 1 + _permutations2[ll + 1]]]] % 32; + /* Calculate the contribution from the five corners */ + double t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0*w0; + if (t0 < 0) n0 = 0.0; + else + { + t0 *= t0; + n0 = t0 * t0 * _dot4(_grad4[gi0], x0, y0, z0, w0); + } + double t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1*w1; + if (t1 < 0) n1 = 0.0; + else + { + t1 *= t1; + n1 = t1 * t1 * _dot4(_grad4[gi1], x1, y1, z1, w1); + } + double t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2*w2; + if (t2 < 0) n2 = 0.0; + else + { + t2 *= t2; + n2 = t2 * t2 * _dot4(_grad4[gi2], x2, y2, z2, w2); + } + double t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3*w3; + if (t3 < 0) n3 = 0.0; + else + { + t3 *= t3; + n3 = t3 * t3 * _dot4(_grad4[gi3], x3, y3, z3, w3); + } + double t4 = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4*w4; + if (t4 < 0) n4 = 0.0; + else + { + t4 *= t4; + n4 = t4 * t4 * _dot4(_grad4[gi4], x4, y4, z4, w4); + } + /* Sum up and scale the result to cover the range [-1,1] */ + return 27.0 * (n0 + n1 + n2 + n3 + n4); +} diff --git a/lib_paysages/simplexnoise.h b/lib_paysages/simplexnoise.h new file mode 100644 index 0000000..4e7be70 --- /dev/null +++ b/lib_paysages/simplexnoise.h @@ -0,0 +1,17 @@ +#ifndef _PAYSAGES_SIMPLEXNOISE_H_ +#define _PAYSAGES_SIMPLEXNOISE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void simplexNoiseInit(); +double simplexNoiseGet2DValue(double xin, double yin); +double simplexNoiseGet3DValue(double xin, double yin, double zin); +double simplexNoiseGet4DValue(double x, double y, double z, double w); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib_paysages/terraincanvas.c b/lib_paysages/terraincanvas.c index 2bf4595..8f82c07 100644 --- a/lib_paysages/terraincanvas.c +++ b/lib_paysages/terraincanvas.c @@ -15,7 +15,6 @@ TerrainCanvas* terrainCanvasCreate() heightmapChangeResolution(&result->height_map, 256, 256); result->height_factor = 1.0; result->detail_noise = noiseCreateGenerator(); - noiseGenerateBaseNoise(result->detail_noise, 1048576); noiseAddLevelsSimple(result->detail_noise, 5, 1.0, 1.0); result->detail_height_factor = 0.2; result->detail_scaling = 0.4; diff --git a/lib_paysages/textures.c b/lib_paysages/textures.c index 5e5eef6..dc9514a 100644 --- a/lib_paysages/textures.c +++ b/lib_paysages/textures.c @@ -64,7 +64,6 @@ TextureLayerDefinition* texturesLayerCreateDefinition() result->zone = zoneCreate(); result->bump_noise = noiseCreateGenerator(); - noiseGenerateBaseNoise(result->bump_noise, 102400); noiseAddLevelsSimple(result->bump_noise, 8, 1.0, 1.0); result->bump_height = 0.1; result->bump_scaling = 0.1;