Using c++ random generators instead of cstdlib one

This commit is contained in:
Michaël Lemaire 2015-12-10 19:40:39 +01:00
parent 9c774f3817
commit 2d6c0f34c3
24 changed files with 123 additions and 68 deletions

View file

@ -135,8 +135,8 @@ void NoiseGenerator::setState(const NoiseState &state) {
state.copy(&this->state); state.copy(&this->state);
} }
void NoiseGenerator::randomizeOffsets() { void NoiseGenerator::randomizeOffsets(RandomGenerator &random) {
state.randomizeOffsets(); state.randomizeOffsets(random);
} }
NoiseGenerator::NoiseFunction NoiseGenerator::getFunction() { NoiseGenerator::NoiseFunction NoiseGenerator::getFunction() {

View file

@ -39,7 +39,7 @@ class BASICSSHARED_EXPORT NoiseGenerator {
} }
void setState(const NoiseState &state); void setState(const NoiseState &state);
void randomizeOffsets(); void randomizeOffsets(RandomGenerator &random = RandomGeneratorDefault);
NoiseFunction getFunction(); NoiseFunction getFunction();
void setCustomFunction(double (*func1d)(double x), double (*func2d)(double x, double y), void setCustomFunction(double (*func1d)(double x), double (*func2d)(double x, double y),
double (*func3d)(double x, double y, double z)); double (*func3d)(double x, double y, double z));

View file

@ -42,11 +42,11 @@ void NoiseState::copy(NoiseState *destination) const {
destination->level_offsets = level_offsets; destination->level_offsets = level_offsets;
} }
void NoiseState::randomizeOffsets() { void NoiseState::randomizeOffsets(RandomGenerator &random) {
for (auto &level_offset : level_offsets) { for (auto &level_offset : level_offsets) {
level_offset.x = RandomGenerator::random(); level_offset.x = random.genDouble();
level_offset.y = RandomGenerator::random(); level_offset.y = random.genDouble();
level_offset.z = RandomGenerator::random(); level_offset.z = random.genDouble();
} }
} }

View file

@ -28,7 +28,7 @@ class BASICSSHARED_EXPORT NoiseState {
void load(PackStream *stream); void load(PackStream *stream);
void copy(NoiseState *destination) const; 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 resetOffsets(double x = 0.0, double y = 0.0, double z = 0.0);
void setLevel(int level, double x, double y, double z); void setLevel(int level, double x, double y, double z);

View file

@ -19,7 +19,6 @@ Vector3::Vector3(const VectorSpherical &v)
Vector3::Vector3(double x, double y, double z) : x(x), y(y), z(z) { Vector3::Vector3(double x, double y, double z) : x(x), y(y), z(z) {
} }
void Vector3::save(PackStream *stream) const { void Vector3::save(PackStream *stream) const {
stream->write(&x); stream->write(&x);
stream->write(&y); 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); 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 // TODO More uniform spatial repartition
// The current randomization clusters result near the center and at the poles // The current randomization clusters result near the center and at the poles
VectorSpherical vec = {only_surface ? radius : RandomGenerator::random() * radius, VectorSpherical vec = {only_surface ? radius : random.genDouble() * radius,
(RandomGenerator::random() - 0.5) * M_PI, RandomGenerator::random() * M_2PI}; (random.genDouble() - 0.5) * M_PI, random.genDouble() * M_2PI};
return Vector3(vec); return Vector3(vec);
} }

View file

@ -71,7 +71,7 @@ class BASICSSHARED_EXPORT Vector3 {
* *
* If *only_surface* is true, produce a vector with *radius* as length. * 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: public:
// TODO Make private // TODO Make private

View file

@ -100,7 +100,7 @@ void AtmosphereDefinition::getHMS(int *hour, int *minute, int *second) const {
*second = value - *minute * 60.0; *second = value - *minute * 60.0;
} }
void AtmosphereDefinition::applyPreset(AtmospherePreset preset) { void AtmosphereDefinition::applyPreset(AtmospherePreset preset, RandomGenerator &random) {
sun_color.r = 1.0; sun_color.r = 1.0;
sun_color.g = 0.95; sun_color.g = 0.95;
sun_color.b = 0.9; sun_color.b = 0.9;
@ -142,28 +142,28 @@ void AtmosphereDefinition::applyPreset(AtmospherePreset preset) {
; ;
} }
generateStars(2000); generateStars(2000, random);
validate(); validate();
} }
void AtmosphereDefinition::generateStars(int count) { void AtmosphereDefinition::generateStars(int count, RandomGenerator &random) {
stars.clear(); stars.clear();
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
Star star; Star star;
star.location = star.location =
Vector3((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,
(RandomGenerator::random() - 0.5) * 100000.0); (random.genDouble() - 0.5) * 100000.0);
if (star.location.getNorm() < 30000.0) { if (star.location.getNorm() < 30000.0) {
i--; i--;
continue; continue;
} }
double brillance = RandomGenerator::random() * 0.05 + 0.1; double brillance = random.genDouble() * 0.05 + 0.1;
star.col = Color(brillance + RandomGenerator::random() * 0.03, brillance + RandomGenerator::random() * 0.03, star.col = Color(brillance + random.genDouble() * 0.03, brillance + random.genDouble() * 0.03,
brillance + RandomGenerator::random() * 0.03, 1.0); brillance + random.genDouble() * 0.03, 1.0);
star.radius = 30.0 + RandomGenerator::random() * 20.0; star.radius = 30.0 + random.genDouble() * 20.0;
stars.push_back(star); stars.push_back(star);
} }

View file

@ -64,8 +64,8 @@ class DEFINITIONSHARED_EXPORT AtmosphereDefinition : public DefinitionNode {
*/ */
void getHMS(int *hour, int *minute, int *second) const; void getHMS(int *hour, int *minute, int *second) const;
void applyPreset(AtmospherePreset preset); void applyPreset(AtmospherePreset preset, RandomGenerator &random = RandomGeneratorDefault);
void generateStars(int count); void generateStars(int count, RandomGenerator &random = RandomGeneratorDefault);
public: public:
AtmosphereModel model; AtmosphereModel model;

View file

@ -9,12 +9,13 @@ static DefinitionNode *_layerConstructor(Layers *parent, const std::string &name
CloudsDefinition::CloudsDefinition(DefinitionNode *parent) : Layers(parent, "clouds", _layerConstructor) { CloudsDefinition::CloudsDefinition(DefinitionNode *parent) : Layers(parent, "clouds", _layerConstructor) {
} }
void CloudsDefinition::applyPreset(CloudsPreset preset) { void CloudsDefinition::applyPreset(CloudsPreset preset, RandomGenerator &random) {
clear(); clear();
if (preset == CLOUDS_PRESET_PARTLY_CLOUDY) { if (preset == CLOUDS_PRESET_PARTLY_CLOUDY) {
CloudLayerDefinition layer(NULL, "Strato-cumulus"); CloudLayerDefinition layer(NULL, "Strato-cumulus");
layer.type = CloudLayerDefinition::STRATOCUMULUS; layer.type = CloudLayerDefinition::STRATOCUMULUS;
layer.noise_state.randomizeOffsets(random);
addLayer(layer); addLayer(layer);
} }
} }

View file

@ -17,7 +17,7 @@ class DEFINITIONSHARED_EXPORT CloudsDefinition : public Layers {
} }
typedef enum { CLOUDS_PRESET_PARTLY_CLOUDY } CloudsPreset; typedef enum { CLOUDS_PRESET_PARTLY_CLOUDY } CloudsPreset;
void applyPreset(CloudsPreset preset); void applyPreset(CloudsPreset preset, RandomGenerator &random = RandomGeneratorDefault);
}; };
} }
} }

View file

@ -1,6 +1,5 @@
#include "Scenery.h" #include "Scenery.h"
#include <ctime>
#include <map> #include <map>
#include "PackStream.h" #include "PackStream.h"
@ -11,6 +10,7 @@
#include "TexturesDefinition.h" #include "TexturesDefinition.h"
#include "WaterDefinition.h" #include "WaterDefinition.h"
#include "Logs.h" #include "Logs.h"
#include "RandomGenerator.h"
static const double APP_HEADER = 19866544632.125; static const double APP_HEADER = 19866544632.125;
static const int DATA_VERSION = 1; static const int DATA_VERSION = 1;
@ -93,24 +93,25 @@ Scenery *Scenery::getScenery() {
return this; return this;
} }
void Scenery::autoPreset(int seed) { void Scenery::autoPreset(RandomGenerator &random) {
if (!seed) { terrain->applyPreset(TerrainDefinition::TERRAIN_PRESET_STANDARD, random);
seed = time(NULL); textures->applyPreset(TexturesDefinition::TEXTURES_PRESET_FULL, random);
} atmosphere->applyPreset(AtmosphereDefinition::ATMOSPHERE_PRESET_CLEAR_DAY, random);
srand(seed); water->applyPreset(WaterDefinition::WATER_PRESET_LAKE, random);
clouds->applyPreset(CloudsDefinition::CLOUDS_PRESET_PARTLY_CLOUDY, random);
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);
camera->setLocation(VECTOR_ZERO); camera->setLocation(VECTOR_ZERO);
camera->setTarget(VECTOR_NORTH); camera->setTarget(VECTOR_NORTH);
validate(); 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) { void Scenery::setAtmosphere(AtmosphereDefinition *atmosphere) {

View file

@ -34,7 +34,8 @@ class DEFINITIONSHARED_EXPORT Scenery : public DefinitionNode {
virtual Scenery *getScenery() override; virtual Scenery *getScenery() override;
void autoPreset(int seed = 0); void autoPreset(RandomGenerator &random = RandomGeneratorDefault);
void autoPreset(unsigned int seed);
void setAtmosphere(AtmosphereDefinition *atmosphere); void setAtmosphere(AtmosphereDefinition *atmosphere);
inline AtmosphereDefinition *getAtmosphere() const { inline AtmosphereDefinition *getAtmosphere() const {

View file

@ -113,11 +113,11 @@ unsigned long TerrainDefinition::getMemoryStats() {
return height_map->getMemoryStats(); return height_map->getMemoryStats();
} }
void TerrainDefinition::applyPreset(TerrainPreset preset) { void TerrainDefinition::applyPreset(TerrainPreset preset, RandomGenerator &random) {
int resolution = 8; int resolution = 8;
switch (preset) { switch (preset) {
case TERRAIN_PRESET_STANDARD: case TERRAIN_PRESET_STANDARD:
_height_noise->randomizeOffsets(); _height_noise->randomizeOffsets(random);
_height_noise->clearLevels(); _height_noise->clearLevels();
_height_noise->addLevelSimple(pow(2.0, resolution + 1), -1.0, 1.0); _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); _height_noise->addLevelsSimple(resolution - 2, pow(2.0, resolution - 1), -0.7, 0.7, 0.5);

View file

@ -37,7 +37,7 @@ class DEFINITIONSHARED_EXPORT TerrainDefinition : public DefinitionNode {
public: public:
typedef enum { TERRAIN_PRESET_STANDARD } TerrainPreset; typedef enum { TERRAIN_PRESET_STANDARD } TerrainPreset;
void applyPreset(TerrainPreset preset); void applyPreset(TerrainPreset preset, RandomGenerator &random = RandomGeneratorDefault);
public: public:
double height; double height;

View file

@ -96,9 +96,9 @@ void TextureLayerDefinition::load(PackStream *stream) {
_detail_noise->load(stream); _detail_noise->load(stream);
} }
void TextureLayerDefinition::applyPreset(TextureLayerPreset preset) { void TextureLayerDefinition::applyPreset(TextureLayerPreset preset, RandomGenerator &random) {
_displacement_noise->randomizeOffsets(); _displacement_noise->randomizeOffsets(random);
_detail_noise->randomizeOffsets(); _detail_noise->randomizeOffsets(random);
terrain_zone->clear(); terrain_zone->clear();

View file

@ -29,7 +29,7 @@ class DEFINITIONSHARED_EXPORT TextureLayerDefinition : public DefinitionNode {
virtual void copy(DefinitionNode *destination) const override; virtual void copy(DefinitionNode *destination) const override;
virtual void validate() override; virtual void validate() override;
void applyPreset(TextureLayerPreset preset); void applyPreset(TextureLayerPreset preset, RandomGenerator &random = RandomGeneratorDefault);
public: public:
Zone *terrain_zone; Zone *terrain_zone;

View file

@ -9,44 +9,44 @@ static DefinitionNode *_layer_constructor(Layers *parent, const std::string &nam
TexturesDefinition::TexturesDefinition(DefinitionNode *parent) : Layers(parent, "textures", _layer_constructor) { 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"); TextureLayerDefinition layer(NULL, "temp");
clear(); clear();
layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_MUD); layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_MUD, random);
layer.setName("Mud"); layer.setName("Mud");
addLayer(layer); addLayer(layer);
if (preset == TEXTURES_PRESET_FULL) { if (preset == TEXTURES_PRESET_FULL) {
layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK); layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK, random);
layer.setName("Ground"); layer.setName("Ground");
addLayer(layer); addLayer(layer);
layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_GRASS); layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_GRASS, random);
layer.setName("Grass"); layer.setName("Grass");
addLayer(layer); addLayer(layer);
layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SAND); layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SAND, random);
layer.setName("Sand"); layer.setName("Sand");
addLayer(layer); addLayer(layer);
layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SNOW); layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SNOW, random);
layer.setName("Snow"); layer.setName("Snow");
addLayer(layer); addLayer(layer);
} else if (preset == TEXTURES_PRESET_IRELAND) { } else if (preset == TEXTURES_PRESET_IRELAND) {
layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK); layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK, random);
layer.setName("Ground"); layer.setName("Ground");
addLayer(layer); addLayer(layer);
layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_GRASS); layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_GRASS, random);
layer.setName("Grass"); layer.setName("Grass");
addLayer(layer); addLayer(layer);
} else if (preset == TEXTURES_PRESET_ALPS) { } else if (preset == TEXTURES_PRESET_ALPS) {
layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK); layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK, random);
layer.setName("Ground"); layer.setName("Ground");
addLayer(layer); addLayer(layer);
layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SNOW); layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SNOW, random);
layer.setName("Snow"); layer.setName("Snow");
addLayer(layer); addLayer(layer);
} else if (preset == TEXTURES_PRESET_CANYON) { } else if (preset == TEXTURES_PRESET_CANYON) {

View file

@ -22,7 +22,7 @@ class DEFINITIONSHARED_EXPORT TexturesDefinition : public Layers {
TEXTURES_PRESET_ALPS, TEXTURES_PRESET_ALPS,
TEXTURES_PRESET_CANYON TEXTURES_PRESET_CANYON
} TexturesPreset; } TexturesPreset;
void applyPreset(TexturesPreset preset); void applyPreset(TexturesPreset preset, RandomGenerator &random = RandomGeneratorDefault);
double getMaximalDisplacement(); double getMaximalDisplacement();
}; };

View file

@ -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) { if (preset == WATER_PRESET_LAKE) {
model->setValue(0); model->setValue(0);
} else if (preset == WATER_PRESET_SEA) { } else if (preset == WATER_PRESET_SEA) {

View file

@ -36,7 +36,7 @@ class DEFINITIONSHARED_EXPORT WaterDefinition : public DefinitionNode, public De
virtual void nodeChanged(const DefinitionNode *node, const DefinitionDiff *diff); virtual void nodeChanged(const DefinitionNode *node, const DefinitionDiff *diff);
typedef enum { WATER_PRESET_LAKE, WATER_PRESET_SEA } WaterPreset; typedef enum { WATER_PRESET_LAKE, WATER_PRESET_SEA } WaterPreset;
void applyPreset(WaterPreset preset); void applyPreset(WaterPreset preset, RandomGenerator &random = RandomGeneratorDefault);
public: public:
double transparency; double transparency;

View file

@ -17,6 +17,7 @@
#include "LightFilter.h" #include "LightFilter.h"
#include "GodRaysSampler.h" #include "GodRaysSampler.h"
#include "Rasterizer.h" #include "Rasterizer.h"
#include "RandomGenerator.h"
#include <sstream> #include <sstream>
@ -39,8 +40,8 @@ static void startTestRender(SoftwareCanvasRenderer *renderer, const std::string
static void testGroundShadowQuality() { static void testGroundShadowQuality() {
Scenery scenery; Scenery scenery;
srand(5); RandomGenerator random(5);
scenery.getTerrain()->applyPreset(TerrainDefinition::TERRAIN_PRESET_STANDARD); scenery.getTerrain()->applyPreset(TerrainDefinition::TERRAIN_PRESET_STANDARD, random);
scenery.getTerrain()->propWaterHeight()->setValue(-0.5); scenery.getTerrain()->propWaterHeight()->setValue(-0.5);
scenery.getWater()->propReflection()->setValue(0.0); scenery.getWater()->propReflection()->setValue(0.0);
scenery.getWater()->material->base->r = 0.0; scenery.getWater()->material->base->r = 0.0;
@ -49,7 +50,7 @@ static void testGroundShadowQuality() {
scenery.getWater()->material->reflection = 0.0; scenery.getWater()->material->reflection = 0.0;
scenery.getWater()->foam_coverage = 0.0; scenery.getWater()->foam_coverage = 0.0;
scenery.getWater()->transparency = 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.getAtmosphere()->setDayTime(16, 45);
scenery.getTextures()->clear(); scenery.getTextures()->clear();
TextureLayerDefinition texture(NULL, "test"); TextureLayerDefinition texture(NULL, "test");

View file

@ -1 +1,38 @@
#include "RandomGenerator.h" #include "RandomGenerator.h"
#include <chrono>
#include <random>
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<double> 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);
}

View file

@ -3,18 +3,30 @@
#include "system_global.h" #include "system_global.h"
#include <cstdlib>
namespace paysages { namespace paysages {
namespace system { namespace system {
class SYSTEMSHARED_EXPORT RandomGenerator { class SYSTEMSHARED_EXPORT RandomGenerator {
public: public:
RandomGenerator(); typedef unsigned long Seed;
class RandomGeneratorPrivate;
static inline double random() { public:
return ((double)rand()) / (double)RAND_MAX; 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;
}; };
} }
} }

View file

@ -29,6 +29,9 @@ class Mutex;
class Semaphore; class Semaphore;
class PictureWriter; class PictureWriter;
class Time; class Time;
class RandomGenerator;
extern RandomGenerator& RandomGeneratorDefault;
} }
} }
using namespace paysages::system; using namespace paysages::system;