diff --git a/src/basics/NoiseGenerator.cpp b/src/basics/NoiseGenerator.cpp index 549d95a..ac6fac5 100644 --- a/src/basics/NoiseGenerator.cpp +++ b/src/basics/NoiseGenerator.cpp @@ -135,8 +135,8 @@ void NoiseGenerator::setState(const NoiseState &state) { state.copy(&this->state); } -void NoiseGenerator::randomizeOffsets() { - state.randomizeOffsets(); +void NoiseGenerator::randomizeOffsets(RandomGenerator &random) { + state.randomizeOffsets(random); } NoiseGenerator::NoiseFunction NoiseGenerator::getFunction() { diff --git a/src/basics/NoiseGenerator.h b/src/basics/NoiseGenerator.h index 1d28850..cfcec14 100644 --- a/src/basics/NoiseGenerator.h +++ b/src/basics/NoiseGenerator.h @@ -39,7 +39,7 @@ class BASICSSHARED_EXPORT NoiseGenerator { } void setState(const NoiseState &state); - void randomizeOffsets(); + void randomizeOffsets(RandomGenerator &random = RandomGeneratorDefault); NoiseFunction getFunction(); void setCustomFunction(double (*func1d)(double x), double (*func2d)(double x, double y), double (*func3d)(double x, double y, double z)); diff --git a/src/basics/NoiseState.cpp b/src/basics/NoiseState.cpp index 4678947..e799737 100644 --- a/src/basics/NoiseState.cpp +++ b/src/basics/NoiseState.cpp @@ -42,11 +42,11 @@ void NoiseState::copy(NoiseState *destination) const { destination->level_offsets = level_offsets; } -void NoiseState::randomizeOffsets() { +void NoiseState::randomizeOffsets(RandomGenerator &random) { for (auto &level_offset : level_offsets) { - level_offset.x = RandomGenerator::random(); - level_offset.y = RandomGenerator::random(); - level_offset.z = RandomGenerator::random(); + level_offset.x = random.genDouble(); + level_offset.y = random.genDouble(); + level_offset.z = random.genDouble(); } } diff --git a/src/basics/NoiseState.h b/src/basics/NoiseState.h index f336095..d0bfae2 100644 --- a/src/basics/NoiseState.h +++ b/src/basics/NoiseState.h @@ -28,7 +28,7 @@ class BASICSSHARED_EXPORT NoiseState { void load(PackStream *stream); void copy(NoiseState *destination) const; - void randomizeOffsets(); + void randomizeOffsets(RandomGenerator &random = RandomGeneratorDefault); void resetOffsets(double x = 0.0, double y = 0.0, double z = 0.0); void setLevel(int level, double x, double y, double z); diff --git a/src/basics/Vector3.cpp b/src/basics/Vector3.cpp index 1902d14..41e84ee 100644 --- a/src/basics/Vector3.cpp +++ b/src/basics/Vector3.cpp @@ -19,7 +19,6 @@ Vector3::Vector3(const VectorSpherical &v) Vector3::Vector3(double x, double y, double z) : x(x), y(y), z(z) { } - void Vector3::save(PackStream *stream) const { stream->write(&x); stream->write(&y); @@ -115,10 +114,10 @@ Vector3 Vector3::midPointTo(const Vector3 &other) const { return Vector3((other.x + x) * 0.5, (other.y + y) * 0.5, (other.z + z) * 0.5); } -Vector3 Vector3::randomInSphere(double radius, bool only_surface) { +Vector3 Vector3::randomInSphere(double radius, bool only_surface, RandomGenerator &random) { // TODO More uniform spatial repartition // The current randomization clusters result near the center and at the poles - VectorSpherical vec = {only_surface ? radius : RandomGenerator::random() * radius, - (RandomGenerator::random() - 0.5) * M_PI, RandomGenerator::random() * M_2PI}; + VectorSpherical vec = {only_surface ? radius : random.genDouble() * radius, + (random.genDouble() - 0.5) * M_PI, random.genDouble() * M_2PI}; return Vector3(vec); } diff --git a/src/basics/Vector3.h b/src/basics/Vector3.h index 3b87ce3..c04b9d0 100644 --- a/src/basics/Vector3.h +++ b/src/basics/Vector3.h @@ -71,7 +71,7 @@ class BASICSSHARED_EXPORT Vector3 { * * If *only_surface* is true, produce a vector with *radius* as length. */ - static Vector3 randomInSphere(double radius = 1.0, bool only_surface = false); + static Vector3 randomInSphere(double radius = 1.0, bool only_surface = false, RandomGenerator &random = RandomGeneratorDefault); public: // TODO Make private diff --git a/src/definition/AtmosphereDefinition.cpp b/src/definition/AtmosphereDefinition.cpp index 08232cc..9d4e691 100644 --- a/src/definition/AtmosphereDefinition.cpp +++ b/src/definition/AtmosphereDefinition.cpp @@ -100,7 +100,7 @@ void AtmosphereDefinition::getHMS(int *hour, int *minute, int *second) const { *second = value - *minute * 60.0; } -void AtmosphereDefinition::applyPreset(AtmospherePreset preset) { +void AtmosphereDefinition::applyPreset(AtmospherePreset preset, RandomGenerator &random) { sun_color.r = 1.0; sun_color.g = 0.95; sun_color.b = 0.9; @@ -142,28 +142,28 @@ void AtmosphereDefinition::applyPreset(AtmospherePreset preset) { ; } - generateStars(2000); + generateStars(2000, random); validate(); } -void AtmosphereDefinition::generateStars(int count) { +void AtmosphereDefinition::generateStars(int count, RandomGenerator &random) { stars.clear(); for (int i = 0; i < count; ++i) { Star star; star.location = - Vector3((RandomGenerator::random() - 0.5) * 100000.0, (RandomGenerator::random() * 0.5) * 100000.0, - (RandomGenerator::random() - 0.5) * 100000.0); + Vector3((random.genDouble() - 0.5) * 100000.0, (random.genDouble() * 0.5) * 100000.0, + (random.genDouble() - 0.5) * 100000.0); if (star.location.getNorm() < 30000.0) { i--; continue; } - double brillance = RandomGenerator::random() * 0.05 + 0.1; - star.col = Color(brillance + RandomGenerator::random() * 0.03, brillance + RandomGenerator::random() * 0.03, - brillance + RandomGenerator::random() * 0.03, 1.0); - star.radius = 30.0 + RandomGenerator::random() * 20.0; + double brillance = random.genDouble() * 0.05 + 0.1; + star.col = Color(brillance + random.genDouble() * 0.03, brillance + random.genDouble() * 0.03, + brillance + random.genDouble() * 0.03, 1.0); + star.radius = 30.0 + random.genDouble() * 20.0; stars.push_back(star); } diff --git a/src/definition/AtmosphereDefinition.h b/src/definition/AtmosphereDefinition.h index a4affb0..5d614b6 100644 --- a/src/definition/AtmosphereDefinition.h +++ b/src/definition/AtmosphereDefinition.h @@ -64,8 +64,8 @@ class DEFINITIONSHARED_EXPORT AtmosphereDefinition : public DefinitionNode { */ void getHMS(int *hour, int *minute, int *second) const; - void applyPreset(AtmospherePreset preset); - void generateStars(int count); + void applyPreset(AtmospherePreset preset, RandomGenerator &random = RandomGeneratorDefault); + void generateStars(int count, RandomGenerator &random = RandomGeneratorDefault); public: AtmosphereModel model; diff --git a/src/definition/CloudsDefinition.cpp b/src/definition/CloudsDefinition.cpp index a73595a..abdd862 100644 --- a/src/definition/CloudsDefinition.cpp +++ b/src/definition/CloudsDefinition.cpp @@ -9,12 +9,13 @@ static DefinitionNode *_layerConstructor(Layers *parent, const std::string &name CloudsDefinition::CloudsDefinition(DefinitionNode *parent) : Layers(parent, "clouds", _layerConstructor) { } -void CloudsDefinition::applyPreset(CloudsPreset preset) { +void CloudsDefinition::applyPreset(CloudsPreset preset, RandomGenerator &random) { clear(); if (preset == CLOUDS_PRESET_PARTLY_CLOUDY) { CloudLayerDefinition layer(NULL, "Strato-cumulus"); layer.type = CloudLayerDefinition::STRATOCUMULUS; + layer.noise_state.randomizeOffsets(random); addLayer(layer); } } diff --git a/src/definition/CloudsDefinition.h b/src/definition/CloudsDefinition.h index f032c9d..08eaf3f 100644 --- a/src/definition/CloudsDefinition.h +++ b/src/definition/CloudsDefinition.h @@ -17,7 +17,7 @@ class DEFINITIONSHARED_EXPORT CloudsDefinition : public Layers { } typedef enum { CLOUDS_PRESET_PARTLY_CLOUDY } CloudsPreset; - void applyPreset(CloudsPreset preset); + void applyPreset(CloudsPreset preset, RandomGenerator &random = RandomGeneratorDefault); }; } } diff --git a/src/definition/Scenery.cpp b/src/definition/Scenery.cpp index 23236e1..ea9b3ec 100644 --- a/src/definition/Scenery.cpp +++ b/src/definition/Scenery.cpp @@ -1,6 +1,5 @@ #include "Scenery.h" -#include #include #include "PackStream.h" @@ -12,6 +11,7 @@ #include "VegetationDefinition.h" #include "WaterDefinition.h" #include "Logs.h" +#include "RandomGenerator.h" static const double APP_HEADER = 19866544632.125; static const int DATA_VERSION = 1; @@ -95,25 +95,26 @@ const Scenery *Scenery::getScenery() const { return this; } -void Scenery::autoPreset(int seed) { - if (!seed) { - seed = time(NULL); - } - srand(seed); - - terrain->applyPreset(TerrainDefinition::TERRAIN_PRESET_STANDARD); - textures->applyPreset(TexturesDefinition::TEXTURES_PRESET_FULL); - atmosphere->applyPreset(AtmosphereDefinition::ATMOSPHERE_PRESET_CLEAR_DAY); - water->applyPreset(WaterDefinition::WATER_PRESET_LAKE); - clouds->applyPreset(CloudsDefinition::CLOUDS_PRESET_PARTLY_CLOUDY); - vegetation->applyPreset(VegetationDefinition::VEGETATION_PRESET_TEMPERATE); +void Scenery::autoPreset(RandomGenerator &random) { + terrain->applyPreset(TerrainDefinition::TERRAIN_PRESET_STANDARD, random); + textures->applyPreset(TexturesDefinition::TEXTURES_PRESET_FULL, random); + atmosphere->applyPreset(AtmosphereDefinition::ATMOSPHERE_PRESET_CLEAR_DAY, random); + water->applyPreset(WaterDefinition::WATER_PRESET_LAKE, random); + clouds->applyPreset(CloudsDefinition::CLOUDS_PRESET_PARTLY_CLOUDY, random); + vegetation->applyPreset(VegetationDefinition::VEGETATION_PRESET_TEMPERATE, random); camera->setLocation(VECTOR_ZERO); camera->setTarget(VECTOR_NORTH); validate(); - Logs::debug() << "[Definition] New scenery generated from seed " << seed << std::endl; + Logs::debug() << "[Definition] New scenery generated from seed " << random.getSeed() << std::endl; +} + +void Scenery::autoPreset(unsigned int seed) +{ + RandomGenerator random(seed); + autoPreset(random); } void Scenery::setAtmosphere(AtmosphereDefinition *atmosphere) { diff --git a/src/definition/Scenery.h b/src/definition/Scenery.h index bd1f815..a5545e0 100644 --- a/src/definition/Scenery.h +++ b/src/definition/Scenery.h @@ -34,7 +34,8 @@ class DEFINITIONSHARED_EXPORT Scenery : public DefinitionNode { virtual const Scenery *getScenery() const override; - void autoPreset(int seed = 0); + void autoPreset(RandomGenerator &random = RandomGeneratorDefault); + void autoPreset(unsigned int seed); void setAtmosphere(AtmosphereDefinition *atmosphere); inline AtmosphereDefinition *getAtmosphere() const { diff --git a/src/definition/TerrainDefinition.cpp b/src/definition/TerrainDefinition.cpp index 2bb7bcf..56c0895 100644 --- a/src/definition/TerrainDefinition.cpp +++ b/src/definition/TerrainDefinition.cpp @@ -113,11 +113,11 @@ unsigned long TerrainDefinition::getMemoryStats() { return height_map->getMemoryStats(); } -void TerrainDefinition::applyPreset(TerrainPreset preset) { +void TerrainDefinition::applyPreset(TerrainPreset preset, RandomGenerator &random) { int resolution = 8; switch (preset) { case TERRAIN_PRESET_STANDARD: - _height_noise->randomizeOffsets(); + _height_noise->randomizeOffsets(random); _height_noise->clearLevels(); _height_noise->addLevelSimple(pow(2.0, resolution + 1), -1.0, 1.0); _height_noise->addLevelsSimple(resolution - 2, pow(2.0, resolution - 1), -0.7, 0.7, 0.5); diff --git a/src/definition/TerrainDefinition.h b/src/definition/TerrainDefinition.h index e787192..689d2ec 100644 --- a/src/definition/TerrainDefinition.h +++ b/src/definition/TerrainDefinition.h @@ -37,7 +37,7 @@ class DEFINITIONSHARED_EXPORT TerrainDefinition : public DefinitionNode { public: typedef enum { TERRAIN_PRESET_STANDARD } TerrainPreset; - void applyPreset(TerrainPreset preset); + void applyPreset(TerrainPreset preset, RandomGenerator &random = RandomGeneratorDefault); public: double height; diff --git a/src/definition/TextureLayerDefinition.cpp b/src/definition/TextureLayerDefinition.cpp index ca5f5c0..86c512b 100644 --- a/src/definition/TextureLayerDefinition.cpp +++ b/src/definition/TextureLayerDefinition.cpp @@ -96,9 +96,9 @@ void TextureLayerDefinition::load(PackStream *stream) { _detail_noise->load(stream); } -void TextureLayerDefinition::applyPreset(TextureLayerPreset preset) { - _displacement_noise->randomizeOffsets(); - _detail_noise->randomizeOffsets(); +void TextureLayerDefinition::applyPreset(TextureLayerPreset preset, RandomGenerator &random) { + _displacement_noise->randomizeOffsets(random); + _detail_noise->randomizeOffsets(random); terrain_zone->clear(); diff --git a/src/definition/TextureLayerDefinition.h b/src/definition/TextureLayerDefinition.h index fc38ed2..6b52d1d 100644 --- a/src/definition/TextureLayerDefinition.h +++ b/src/definition/TextureLayerDefinition.h @@ -29,7 +29,7 @@ class DEFINITIONSHARED_EXPORT TextureLayerDefinition : public DefinitionNode { virtual void copy(DefinitionNode *destination) const override; virtual void validate() override; - void applyPreset(TextureLayerPreset preset); + void applyPreset(TextureLayerPreset preset, RandomGenerator &random = RandomGeneratorDefault); public: Zone *terrain_zone; diff --git a/src/definition/TexturesDefinition.cpp b/src/definition/TexturesDefinition.cpp index 92d1e77..77c10bc 100644 --- a/src/definition/TexturesDefinition.cpp +++ b/src/definition/TexturesDefinition.cpp @@ -9,44 +9,44 @@ static DefinitionNode *_layer_constructor(Layers *parent, const std::string &nam TexturesDefinition::TexturesDefinition(DefinitionNode *parent) : Layers(parent, "textures", _layer_constructor) { } -void TexturesDefinition::applyPreset(TexturesPreset preset) { +void TexturesDefinition::applyPreset(TexturesPreset preset, RandomGenerator &random) { TextureLayerDefinition layer(NULL, "temp"); clear(); - layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_MUD); + layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_MUD, random); layer.setName("Mud"); addLayer(layer); if (preset == TEXTURES_PRESET_FULL) { - layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK); + layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK, random); layer.setName("Ground"); addLayer(layer); - layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_GRASS); + layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_GRASS, random); layer.setName("Grass"); addLayer(layer); - layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SAND); + layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SAND, random); layer.setName("Sand"); addLayer(layer); - layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SNOW); + layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SNOW, random); layer.setName("Snow"); addLayer(layer); } else if (preset == TEXTURES_PRESET_IRELAND) { - layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK); + layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK, random); layer.setName("Ground"); addLayer(layer); - layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_GRASS); + layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_GRASS, random); layer.setName("Grass"); addLayer(layer); } else if (preset == TEXTURES_PRESET_ALPS) { - layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK); + layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK, random); layer.setName("Ground"); addLayer(layer); - layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SNOW); + layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SNOW, random); layer.setName("Snow"); addLayer(layer); } else if (preset == TEXTURES_PRESET_CANYON) { diff --git a/src/definition/TexturesDefinition.h b/src/definition/TexturesDefinition.h index 3b78f78..7c9d9ac 100644 --- a/src/definition/TexturesDefinition.h +++ b/src/definition/TexturesDefinition.h @@ -22,7 +22,7 @@ class DEFINITIONSHARED_EXPORT TexturesDefinition : public Layers { TEXTURES_PRESET_ALPS, TEXTURES_PRESET_CANYON } TexturesPreset; - void applyPreset(TexturesPreset preset); + void applyPreset(TexturesPreset preset, RandomGenerator &random = RandomGeneratorDefault); double getMaximalDisplacement(); }; diff --git a/src/definition/VegetationDefinition.cpp b/src/definition/VegetationDefinition.cpp index 07f86bb..ac4d92a 100644 --- a/src/definition/VegetationDefinition.cpp +++ b/src/definition/VegetationDefinition.cpp @@ -24,13 +24,13 @@ double VegetationDefinition::getMaxHeight() const { return max_height; } -void VegetationDefinition::applyPreset(VegetationPreset preset) { +void VegetationDefinition::applyPreset(VegetationPreset preset, RandomGenerator &random) { VegetationLayerDefinition layer(this, "temp"); clear(); if (preset == VEGETATION_PRESET_TEMPERATE) { - layer.applyPreset(VegetationLayerDefinition::VEGETATION_BASIC_TREES); + layer.applyPreset(VegetationLayerDefinition::VEGETATION_BASIC_TREES, random); layer.setName("Basic tree"); addLayer(layer); } diff --git a/src/definition/VegetationDefinition.h b/src/definition/VegetationDefinition.h index e87d34a..cbf926e 100644 --- a/src/definition/VegetationDefinition.h +++ b/src/definition/VegetationDefinition.h @@ -28,7 +28,7 @@ class DEFINITIONSHARED_EXPORT VegetationDefinition : public Layers { double getMaxHeight() const; typedef enum { VEGETATION_PRESET_TEMPERATE } VegetationPreset; - void applyPreset(VegetationPreset preset); + void applyPreset(VegetationPreset preset, RandomGenerator &random = RandomGeneratorDefault); }; } } diff --git a/src/definition/VegetationLayerDefinition.cpp b/src/definition/VegetationLayerDefinition.cpp index 661b4fa..a4035cd 100644 --- a/src/definition/VegetationLayerDefinition.cpp +++ b/src/definition/VegetationLayerDefinition.cpp @@ -13,6 +13,6 @@ double VegetationLayerDefinition::getMaxHeight() const { return presence->getMaxHeight(); } -void VegetationLayerDefinition::applyPreset(VegetationLayerPreset) { - model->randomize(); +void VegetationLayerDefinition::applyPreset(VegetationLayerPreset, RandomGenerator &random) { + model->randomize(random); } diff --git a/src/definition/VegetationLayerDefinition.h b/src/definition/VegetationLayerDefinition.h index d1e559e..e32356e 100644 --- a/src/definition/VegetationLayerDefinition.h +++ b/src/definition/VegetationLayerDefinition.h @@ -25,7 +25,7 @@ class DEFINITIONSHARED_EXPORT VegetationLayerDefinition : public DefinitionNode double getMaxHeight() const; typedef enum { VEGETATION_BASIC_TREES } VegetationLayerPreset; - void applyPreset(VegetationLayerPreset preset); + void applyPreset(VegetationLayerPreset preset, RandomGenerator &random = RandomGeneratorDefault); private: /** diff --git a/src/definition/VegetationModelDefinition.cpp b/src/definition/VegetationModelDefinition.cpp index 11dfba3..0cd2149 100644 --- a/src/definition/VegetationModelDefinition.cpp +++ b/src/definition/VegetationModelDefinition.cpp @@ -101,41 +101,41 @@ void VegetationModelDefinition::copy(DefinitionNode *destination_) const { void VegetationModelDefinition::validate() { } -static inline double randomizeValue(double base, double min_factor, double max_factor) { - return base * (min_factor + RandomGenerator::random() * (max_factor - min_factor)); +static inline double randomizeValue(RandomGenerator &random, double base, double min_factor, double max_factor) { + return base * (min_factor + random.genDouble() * (max_factor - min_factor)); } -static void addBranchRecurse(std::vector &branches, const Vector3 &base, const Vector3 &direction, - double radius, double length) { +static void addBranchRecurse(RandomGenerator &random, std::vector &branches, const Vector3 &base, + const Vector3 &direction, double radius, double length) { branches.push_back(CappedCylinder(base, direction, radius, length)); if (length > 0.1) { int split_count = 3; - Matrix4 pivot1 = Matrix4::newRotateAxis(randomizeValue(1.0 - 0.6 * length, 0.9, 1.1), VECTOR_EAST); + Matrix4 pivot1 = Matrix4::newRotateAxis(randomizeValue(random, 1.0 - 0.6 * length, 0.9, 1.1), VECTOR_EAST); Vector3 new_direction = pivot1.multPoint(direction); for (int i = 0; i < split_count; i++) { Matrix4 pivot2 = - Matrix4::newRotateAxis(randomizeValue(M_PI * 2.0 / (double)split_count, 0.9, 1.1), direction); + Matrix4::newRotateAxis(randomizeValue(random, M_PI * 2.0 / (double)split_count, 0.9, 1.1), direction); new_direction = pivot2.multPoint(new_direction); - Vector3 new_base = base.add(direction.scale(randomizeValue(length, 0.4, 1.0))); + Vector3 new_base = base.add(direction.scale(randomizeValue(random, length, 0.4, 1.0))); if (new_base.add(new_direction).y > 0.1) { - addBranchRecurse(branches, new_base, new_direction, randomizeValue(radius, 0.45, 0.6), - randomizeValue(length, 0.55, 0.85)); + addBranchRecurse(random, branches, new_base, new_direction, randomizeValue(random, radius, 0.45, 0.6), + randomizeValue(random, length, 0.55, 0.85)); } } } } -void VegetationModelDefinition::randomize() { +void VegetationModelDefinition::randomize(RandomGenerator &random) { // Clear structure solid_volumes.clear(); foliage_groups.clear(); foliage_items.clear(); // Add trunk and branches - addBranchRecurse(solid_volumes, VECTOR_ZERO, VECTOR_UP, randomizeValue(0.05, 0.6, 1.0), - randomizeValue(0.5, 0.8, 1.0)); + addBranchRecurse(random, solid_volumes, VECTOR_ZERO, VECTOR_UP, randomizeValue(random, 0.05, 0.6, 1.0), + randomizeValue(random, 0.5, 0.8, 1.0)); // Add foliage groups for (const auto &branch : solid_volumes) { @@ -150,9 +150,9 @@ void VegetationModelDefinition::randomize() { // Add foliage items for (int i = 0; i < 30; i++) { double radius = 0.15; - double scale = randomizeValue(radius, 0.5, 1.0); - Vector3 dir = Vector3::randomInSphere(1.0 - radius); - Vector3 normal = dir.add(Vector3::randomInSphere(0.4)).add(Vector3(0.0, 0.3, 0.0)).normalize(); + double scale = randomizeValue(random, radius, 0.5, 1.0); + Vector3 dir = Vector3::randomInSphere(1.0 - radius, false, random); + Vector3 normal = dir.add(Vector3::randomInSphere(0.4, false, random)).add(Vector3(0.0, 0.3, 0.0)).normalize(); Disk leaf(dir, normal, scale); foliage_items.push_back(leaf); } diff --git a/src/definition/VegetationModelDefinition.h b/src/definition/VegetationModelDefinition.h index 38e307f..e6b37df 100644 --- a/src/definition/VegetationModelDefinition.h +++ b/src/definition/VegetationModelDefinition.h @@ -45,7 +45,7 @@ class DEFINITIONSHARED_EXPORT VegetationModelDefinition : public DefinitionNode /** * Randomize the model geometry. */ - void randomize(); + void randomize(RandomGenerator &random = RandomGeneratorDefault); private: SurfaceMaterial *solid_material; diff --git a/src/definition/WaterDefinition.cpp b/src/definition/WaterDefinition.cpp index ccd275b..4753571 100644 --- a/src/definition/WaterDefinition.cpp +++ b/src/definition/WaterDefinition.cpp @@ -154,7 +154,7 @@ void WaterDefinition::nodeChanged(const DefinitionNode *node, const DefinitionDi } } -void WaterDefinition::applyPreset(WaterPreset preset) { +void WaterDefinition::applyPreset(WaterPreset preset, RandomGenerator &random) { if (preset == WATER_PRESET_LAKE) { model->setValue(0); } else if (preset == WATER_PRESET_SEA) { diff --git a/src/definition/WaterDefinition.h b/src/definition/WaterDefinition.h index e191045..4b4b4da 100644 --- a/src/definition/WaterDefinition.h +++ b/src/definition/WaterDefinition.h @@ -36,7 +36,7 @@ class DEFINITIONSHARED_EXPORT WaterDefinition : public DefinitionNode, public De virtual void nodeChanged(const DefinitionNode *node, const DefinitionDiff *diff); typedef enum { WATER_PRESET_LAKE, WATER_PRESET_SEA } WaterPreset; - void applyPreset(WaterPreset preset); + void applyPreset(WaterPreset preset, RandomGenerator &random = RandomGeneratorDefault); public: double transparency; diff --git a/src/interface/commandline/tests.cpp b/src/interface/commandline/tests.cpp index 3a919af..7680061 100644 --- a/src/interface/commandline/tests.cpp +++ b/src/interface/commandline/tests.cpp @@ -25,6 +25,7 @@ #include "RayCastingResult.h" #include "OpenGLVegetationImpostor.h" #include "Texture2D.h" +#include "RandomGenerator.h" #include #include @@ -52,8 +53,8 @@ static void startTestRender(SoftwareCanvasRenderer *renderer, const std::string static void testGroundShadowQuality() { Scenery scenery; - srand(5); - scenery.getTerrain()->applyPreset(TerrainDefinition::TERRAIN_PRESET_STANDARD); + RandomGenerator random(5); + scenery.getTerrain()->applyPreset(TerrainDefinition::TERRAIN_PRESET_STANDARD, random); scenery.getTerrain()->propWaterHeight()->setValue(-0.5); scenery.getWater()->propReflection()->setValue(0.0); scenery.getWater()->material->base->r = 0.0; @@ -62,7 +63,7 @@ static void testGroundShadowQuality() { scenery.getWater()->material->reflection = 0.0; scenery.getWater()->foam_coverage = 0.0; scenery.getWater()->transparency = 0.0; - scenery.getAtmosphere()->applyPreset(AtmosphereDefinition::ATMOSPHERE_PRESET_CLEAR_SUNSET); + scenery.getAtmosphere()->applyPreset(AtmosphereDefinition::ATMOSPHERE_PRESET_CLEAR_SUNSET, random); scenery.getAtmosphere()->setDayTime(16, 45); scenery.getTextures()->clear(); TextureLayerDefinition texture(NULL, "test"); diff --git a/src/system/RandomGenerator.cpp b/src/system/RandomGenerator.cpp index 5b2fb36..dcaf023 100644 --- a/src/system/RandomGenerator.cpp +++ b/src/system/RandomGenerator.cpp @@ -1 +1,38 @@ #include "RandomGenerator.h" + +#include +#include + +static RandomGenerator _RandomGeneratorDefault; +RandomGenerator& paysages::system::RandomGeneratorDefault = _RandomGeneratorDefault; + +class RandomGenerator::RandomGeneratorPrivate { + public: + RandomGeneratorPrivate(unsigned int seed): generator(seed) { + } + + std::default_random_engine generator; + std::uniform_real_distribution distribution_double; +}; + +RandomGenerator::RandomGenerator(RandomGenerator::Seed seed) { + if (not seed) { + std::random_device true_random; + if (true_random.entropy()) { + seed = true_random(); + } else { + seed = std::chrono::system_clock::now().time_since_epoch().count(); + } + } + data = new RandomGeneratorPrivate(seed); +} + +RandomGenerator::~RandomGenerator() +{ + delete data; +} + +double RandomGenerator::genDouble() +{ + return data->distribution_double(data->generator); +} diff --git a/src/system/RandomGenerator.h b/src/system/RandomGenerator.h index ffe9b01..b871a61 100644 --- a/src/system/RandomGenerator.h +++ b/src/system/RandomGenerator.h @@ -3,18 +3,30 @@ #include "system_global.h" -#include - namespace paysages { namespace system { class SYSTEMSHARED_EXPORT RandomGenerator { public: - RandomGenerator(); + typedef unsigned long Seed; + class RandomGeneratorPrivate; - static inline double random() { - return ((double)rand()) / (double)RAND_MAX; + public: + RandomGenerator(Seed seed = 0); + ~RandomGenerator(); + + inline Seed getSeed() const { + return seed; } + + /** + * Generate a 0.0-1.0 random double value. + */ + double genDouble(); + + private: + Seed seed; + RandomGeneratorPrivate *data; }; } } diff --git a/src/system/system_global.h b/src/system/system_global.h index 7daa901..154f1ab 100644 --- a/src/system/system_global.h +++ b/src/system/system_global.h @@ -29,6 +29,9 @@ class Mutex; class Semaphore; class PictureWriter; class Time; +class RandomGenerator; + +extern RandomGenerator& RandomGeneratorDefault; } } using namespace paysages::system;