diff --git a/src/basics/FractalNoise.cpp b/src/basics/FractalNoise.cpp index 003e22c..2671c4c 100644 --- a/src/basics/FractalNoise.cpp +++ b/src/basics/FractalNoise.cpp @@ -1,8 +1,11 @@ #include "FractalNoise.h" +#include #include +#include #include "PackStream.h" #include "Vector3.h" +#include "RandomGenerator.h" FractalNoise::FractalNoise() { scaling = 1.0; @@ -50,6 +53,11 @@ void FractalNoise::setScaling(double scaling, double height) { void FractalNoise::setStep(double scaling_factor, double height_factor) { this->step_scaling = scaling_factor < 0.00000001 ? 0.0 : 1.0 / scaling_factor; this->step_height = scaling_factor * height_factor; + + // Ensure height will converge to 0 + if (this->step_height >= 0.99) { + this->step_height = 0.99; + } } void FractalNoise::setState(const NoiseState &state) { @@ -64,7 +72,7 @@ double FractalNoise::get1d(double detail, double x) const { decltype(state_level_count) i = 0; while (current_height >= detail) { - const NoiseState::NoiseOffset &offset = state.level_offsets[i]; + auto offset = state.level_offsets[i]; result += getBase1d(offset.x + x * current_scaling) * current_height; @@ -88,7 +96,7 @@ double FractalNoise::get2d(double detail, double x, double y) const { decltype(state_level_count) i = 0; while (current_height >= detail) { - const NoiseState::NoiseOffset &offset = state.level_offsets[i]; + auto offset = state.level_offsets[i]; result += getBase2d(offset.x + x * current_scaling, offset.y + y * current_scaling) * current_height; @@ -146,10 +154,16 @@ double FractalNoise::getTriplanar(double detail, const Vector3 &location, const return noiseXY * mXY + noiseXZ * mXZ + noiseYZ * mYZ; } -void FractalNoise::estimateRange(double *min, double *max) const { - // TODO Better estimate - *max = height; - *min = -*max; +void FractalNoise::estimateRange(double *min, double *max, double detail) const { + *min = 0.0; + *max = 0.0; + + double current_height = height; + while (current_height >= detail) { + *min += -0.5 * current_height; + *max += 0.5 * current_height; + current_height *= step_height; + } } double FractalNoise::getBase1d(double x) const { @@ -159,3 +173,48 @@ double FractalNoise::getBase1d(double x) const { double FractalNoise::getBase2d(double x, double y) const { return getBase3d(x, y, 0.0); } + +string FractalNoise::checkDistribution() { + stringstream result; + + double val, min, max, mean; + RandomGenerator random; + + int samples = 10000000; + double factor = 1.0 / to_double(samples); + + min = 0.0; + max = 0.0; + mean = 0.0; + for (int i = 0; i < samples; i++) { + val = getBase1d((random.genDouble() - 0.5) * 10.0); + min = std::min(val, min); + max = std::max(val, max); + mean += val * factor; + } + result << "1d : min=" << min << " max=" << max << " mean=" << mean << endl; + + min = 0.0; + max = 0.0; + mean = 0.0; + for (int i = 0; i < samples; i++) { + val = getBase2d((random.genDouble() - 0.5) * 10.0, (random.genDouble() - 0.5) * 10.0); + min = std::min(val, min); + max = std::max(val, max); + mean += val * factor; + } + result << "2d : min=" << min << " max=" << max << " mean=" << mean << endl; + + min = 0.0; + max = 0.0; + mean = 0.0; + for (int i = 0; i < samples; i++) { + val = getBase3d((random.genDouble() - 0.5) * 10.0, (random.genDouble() - 0.5) * 10.0, (random.genDouble() - 0.5) * 10.0); + min = std::min(val, min); + max = std::max(val, max); + mean += val * factor; + } + result << "3d : min=" << min << " max=" << max << " mean=" << mean << endl; + + return result.str(); +} diff --git a/src/basics/FractalNoise.h b/src/basics/FractalNoise.h index 90626c4..74c8bd1 100644 --- a/src/basics/FractalNoise.h +++ b/src/basics/FractalNoise.h @@ -3,6 +3,7 @@ #include "basics_global.h" +#include #include "NoiseState.h" namespace paysages { @@ -56,7 +57,7 @@ class BASICSSHARED_EXPORT FractalNoise { /** * Estimate the range of values this generator will yield with a very small detail value. */ - void estimateRange(double *min, double *max) const; + void estimateRange(double *min, double *max, double detail=0.000001) const; virtual double getBase1d(double x) const; virtual double getBase2d(double x, double y) const; @@ -67,6 +68,11 @@ class BASICSSHARED_EXPORT FractalNoise { */ virtual double getBase3d(double x, double y, double z) const = 0; + /** + * Test the noise distribution, and return the report. + */ + string checkDistribution(); + private: NoiseState state; diff --git a/src/definition/NoiseNode.cpp b/src/definition/NoiseNode.cpp index d7b3897..5105476 100644 --- a/src/definition/NoiseNode.cpp +++ b/src/definition/NoiseNode.cpp @@ -20,6 +20,11 @@ void NoiseNode::setConfig(double scaling, double height, double step_scaling, do noise->setStep(step_scaling, step_height); } +void NoiseNode::forceSetGenerator(FractalNoise *noise) { + delete this->noise; + this->noise = noise; +} + void NoiseNode::save(PackStream *stream) const { noise->save(stream); } @@ -43,5 +48,5 @@ void NoiseNode::copy(DefinitionNode *destination) const { string NoiseNode::toString(int indent) const { return DefinitionNode::toString(indent) + " - scaling: " + to_string(noise->getScaling()) + " step " + to_string(noise->getStepScaling()) + " - height: " + to_string(noise->getHeight()) + " step " + - to_string(noise->getStepScaling()); + to_string(noise->getStepHeight()); } diff --git a/src/definition/NoiseNode.h b/src/definition/NoiseNode.h index 1383586..b14b98d 100644 --- a/src/definition/NoiseNode.h +++ b/src/definition/NoiseNode.h @@ -30,6 +30,15 @@ class DEFINITIONSHARED_EXPORT NoiseNode : public DefinitionNode { */ void setConfig(double scaling, double height = 1.0, double step_scaling = 0.5, double step_height = 1.0); + /** + * Force the noise generator to use. + * + * This should only be needed in testing, and is not thread-safe. + * + * The node will take ownership of the generator and will take care of its destruction. + */ + void forceSetGenerator(FractalNoise *noise); + protected: virtual void save(PackStream *stream) const override; virtual void load(PackStream *stream) override; diff --git a/src/definition/TerrainDefinition.cpp b/src/definition/TerrainDefinition.cpp index 5bf6eba..75039e9 100644 --- a/src/definition/TerrainDefinition.cpp +++ b/src/definition/TerrainDefinition.cpp @@ -5,9 +5,10 @@ #include "NoiseGenerator.h" #include "PackStream.h" #include "FloatNode.h" +#include "NoiseNode.h" +#include "FractalNoise.h" TerrainDefinition::TerrainDefinition(DefinitionNode *parent) : DefinitionNode(parent, "terrain", "terrain") { - height = 1.0; shadow_smoothing = 0.0; height_map = new TerrainHeightMap(this); @@ -15,57 +16,42 @@ TerrainDefinition::TerrainDefinition(DefinitionNode *parent) : DefinitionNode(pa addChild(height_map); water_height = new FloatNode(this, "water_height"); - - _height_noise = new NoiseGenerator; + height_noise = new NoiseNode(this, "height_noise"); } TerrainDefinition::~TerrainDefinition() { - delete _height_noise; } void TerrainDefinition::validate() { - _height_noise->validate(); + DefinitionNode::validate(); - if (height < 1.0) { - height = 1.0; - } + // Get base noise range + height_noise->getGenerator()->estimateRange(&_min_height, &_max_height, 0.1); + // TODO Alter limits with heightmap min/max, and displacement textures - /* Get minimal and maximal height */ - _height_noise->getRange(&_min_height, &_max_height); - _min_height *= height; - _max_height *= height; - - /* TODO Alter limits with heightmap min/max */ has_painting = height_map->hasPainting(); } void TerrainDefinition::copy(DefinitionNode *_destination) const { - TerrainDefinition *destination = (TerrainDefinition *)_destination; + if (auto destination = static_cast(_destination)) { + destination->shadow_smoothing = shadow_smoothing; - destination->height = height; - destination->shadow_smoothing = shadow_smoothing; + height_map->copy(destination->height_map); - height_map->copy(destination->height_map); - - _height_noise->copy(destination->_height_noise); - - destination->validate(); + destination->validate(); + } } void TerrainDefinition::save(PackStream *stream) const { DefinitionNode::save(stream); - stream->write(&height); stream->write(&shadow_smoothing); - _height_noise->save(stream); } void TerrainDefinition::load(PackStream *stream) { DefinitionNode::load(stream); - stream->read(&height); stream->read(&shadow_smoothing); - _height_noise->load(stream); validate(); } @@ -74,29 +60,26 @@ double TerrainDefinition::getGridHeight(int x, int z, bool with_painting) { double h; if (!with_painting || !has_painting || !height_map->getGridValue(x, z, &h)) { - h = _height_noise->get2DTotal(to_double(x), to_double(z)); + h = height_noise->getGenerator()->get2d(0.1, to_double(x), to_double(z)); } return h; } -double TerrainDefinition::getInterpolatedHeight(double x, double z, bool scaled, bool with_painting, +double TerrainDefinition::getInterpolatedHeight(double x, double z, bool with_painting, bool water_offset) { double h; if (!with_painting || !has_painting || !height_map->getInterpolatedValue(x, z, &h)) { - h = _height_noise->get2DTotal(x, z); + h = height_noise->getGenerator()->get2d(0.1, x, z); } - if (scaled) { - return (water_offset ? (h - water_height->getValue()) : h) * height; - } else { - return h; - } + return (water_offset ? (h + getWaterOffset()) : h); } double TerrainDefinition::getWaterOffset() const { - return -water_height->getValue() * height; + double height_power = (_max_height - _min_height) * 0.5; + return -water_height->getValue() * height_power; } HeightInfo TerrainDefinition::getHeightInfo() { @@ -114,20 +97,12 @@ unsigned long TerrainDefinition::getMemoryStats() { } void TerrainDefinition::applyPreset(TerrainPreset preset, RandomGenerator &random) { - int resolution = 8; switch (preset) { case TERRAIN_PRESET_STANDARD: - _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); - _height_noise->normalizeAmplitude(-1.0, 1.0, 0); - _height_noise->setFunctionParams(NoiseGenerator::NOISE_FUNCTION_SIMPLEX, 0.0, 0.0); - height = 30.0; + height_noise->randomize(random); + height_noise->setConfig(400.0, 0.1, 0.5, 1.02); shadow_smoothing = 0.03; break; - default: - ; } water_height->setValue(-0.3); diff --git a/src/definition/TerrainDefinition.h b/src/definition/TerrainDefinition.h index 689d2ec..478a4cc 100644 --- a/src/definition/TerrainDefinition.h +++ b/src/definition/TerrainDefinition.h @@ -28,9 +28,12 @@ class DEFINITIONSHARED_EXPORT TerrainDefinition : public DefinitionNode { inline FloatNode *propWaterHeight() const { return water_height; } + inline NoiseNode *propHeightNoise() const { + return height_noise; + } double getGridHeight(int x, int z, bool with_painting); - double getInterpolatedHeight(double x, double z, bool scaled, bool with_painting, bool water_offset = true); + double getInterpolatedHeight(double x, double z, bool with_painting, bool water_offset = true); double getWaterOffset() const; unsigned long getMemoryStats(); HeightInfo getHeightInfo(); @@ -40,19 +43,17 @@ class DEFINITIONSHARED_EXPORT TerrainDefinition : public DefinitionNode { void applyPreset(TerrainPreset preset, RandomGenerator &random = RandomGeneratorDefault); public: - double height; double shadow_smoothing; TerrainHeightMap *height_map; bool has_painting; - double _detail; - NoiseGenerator *_height_noise; double _min_height; double _max_height; private: FloatNode *water_height; + NoiseNode *height_noise; }; } } diff --git a/src/definition/TerrainHeightMap.cpp b/src/definition/TerrainHeightMap.cpp index 33f731e..83f0312 100644 --- a/src/definition/TerrainHeightMap.cpp +++ b/src/definition/TerrainHeightMap.cpp @@ -20,29 +20,29 @@ double TerrainHeightMap::getInitialValue(double x, double y) const { void TerrainHeightMap::brushElevation(const PaintedGridBrush &brush, double x, double y, double value, bool commit) { PaintedGridBrushRaiseLower sbrush(brush); - applyBrush(sbrush, x, y, value / terrain->height, commit); + applyBrush(sbrush, x, y, value, commit); } void TerrainHeightMap::brushFlatten(const PaintedGridBrush &brush, double x, double y, double height, double force, bool commit) { PaintedGridBrushFlatten sbrush(brush, height); - applyBrush(sbrush, x, y, force / terrain->height, commit); + applyBrush(sbrush, x, y, force, commit); } void TerrainHeightMap::brushSmooth(const PaintedGridBrush &brush, double x, double y, double value, bool commit) { PaintedGridBrushSmooth sbrush(brush); - applyBrush(sbrush, x, y, value / terrain->height, commit); + applyBrush(sbrush, x, y, value, commit); } void TerrainHeightMap::brushAddNoise(const PaintedGridBrush &brush, double x, double y, NoiseGenerator *generator, double value, bool commit) { PaintedGridBrushAddNoise sbrush(brush, generator); - applyBrush(sbrush, x, y, value / terrain->height, commit); + applyBrush(sbrush, x, y, value, commit); } void TerrainHeightMap::brushReset(const PaintedGridBrush &brush, double x, double y, double value, bool commit) { PaintedGridBrushReset sbrush(brush); - applyBrush(sbrush, x, y, value / terrain->height, commit); + applyBrush(sbrush, x, y, value, commit); } void TerrainHeightMap::clearPainting() { diff --git a/src/definition/TextureLayerDefinition.cpp b/src/definition/TextureLayerDefinition.cpp index 1ca65f0..033a3c8 100644 --- a/src/definition/TextureLayerDefinition.cpp +++ b/src/definition/TextureLayerDefinition.cpp @@ -32,9 +32,8 @@ void TextureLayerDefinition::validate() { material->validate(); - /* Update zone height range */ - const Scenery *scenery = getScenery(); - if (scenery) { + // Update zone height range + if (auto scenery = getScenery()) { TerrainDefinition *terrain = scenery->getTerrain(); HeightInfo height_info = terrain->getHeightInfo(); terrain_zone->setRelativeHeight(height_info.min_height, height_info.base_height, height_info.max_height); @@ -80,15 +79,15 @@ void TextureLayerDefinition::applyPreset(TextureLayerPreset preset, RandomGenera material->shininess = 4.0; break; case TEXTURES_LAYER_PRESET_ROCK: - terrain_zone->addHeightRangeQuick(1.0, 0.55, 0.7, 0.9, 1.0); - displacement_noise->setConfig(1.0, 0.3, 0.5, 0.85); + terrain_zone->addHeightRangeQuick(1.0, 0.6, 0.7, 0.87, 0.95); + displacement_noise->setConfig(1.0, 0.4, 0.5, 0.85); detail_noise->setConfig(0.02, 0.04); material->setColor(0.6, 0.55, 0.57, 1.0); material->reflection = 0.006; material->shininess = 6.0; break; case TEXTURES_LAYER_PRESET_GRASS: - terrain_zone->addHeightRangeQuick(1.0, 0.45, 0.5, 0.8, 1.0); + terrain_zone->addHeightRangeQuick(1.0, 0.45, 0.5, 0.7, 0.9); terrain_zone->addSlopeRangeQuick(1.0, 0.0, 0.0, 0.05, 0.4); displacement_noise->setConfig(0.4, 0.05); detail_noise->setConfig(0.01, 0.1); @@ -98,7 +97,7 @@ void TextureLayerDefinition::applyPreset(TextureLayerPreset preset, RandomGenera break; case TEXTURES_LAYER_PRESET_SAND: terrain_zone->addHeightRangeQuick(1.0, 0.495, 0.505, 0.56, 0.63); - terrain_zone->addSlopeRangeQuick(1.0, 0.0, 0.0, 0.1, 0.4); + terrain_zone->addSlopeRangeQuick(1.0, 0.0, 0.0, 0.05, 0.3); displacement_noise->setConfig(0.04, 0.1, 0.5, 0.3); detail_noise->setConfig(0.004, 0.08); material->setColor(1.2, 1.1, 0.9, 1.0); @@ -106,8 +105,8 @@ void TextureLayerDefinition::applyPreset(TextureLayerPreset preset, RandomGenera material->shininess = 1.0; break; case TEXTURES_LAYER_PRESET_SNOW: - terrain_zone->addHeightRangeQuick(1.0, 0.77, 0.85, 1.0, 1.0); - terrain_zone->addSlopeRangeQuick(1.0, 0.0, 0.0, 0.2, 1.0); + terrain_zone->addHeightRangeQuick(1.0, 0.87, 0.95, 10.0, 100.0); + terrain_zone->addSlopeRangeQuick(1.0, 0.0, 0.0, 0.1, 1.0); displacement_noise->setConfig(0.4, 0.07); detail_noise->setConfig(0.01, 0.03); material->setColor(5.0, 5.0, 5.0, 1.0); diff --git a/src/definition/Zone.cpp b/src/definition/Zone.cpp index b9aaab7..dfa892a 100644 --- a/src/definition/Zone.cpp +++ b/src/definition/Zone.cpp @@ -1,6 +1,5 @@ #include "Zone.h" -#include #include "Curve.h" #include "PackStream.h" #include "Vector3.h" @@ -39,15 +38,15 @@ void Zone::load(PackStream *stream) { } void Zone::copy(DefinitionNode *_destination) const { - Zone *destination = (Zone *)_destination; + if (auto destination = static_cast(_destination)) { + destination->absolute_height = absolute_height; + destination->relative_height_min = relative_height_min; + destination->relative_height_middle = relative_height_middle; + destination->relative_height_max = relative_height_max; - destination->absolute_height = absolute_height; - destination->relative_height_min = relative_height_min; - destination->relative_height_middle = relative_height_middle; - destination->relative_height_max = relative_height_max; - - value_by_height->copy(destination->value_by_height); - value_by_slope->copy(destination->value_by_slope); + value_by_height->copy(destination->value_by_height); + value_by_slope->copy(destination->value_by_slope); + } } void Zone::clear() { diff --git a/src/interface/commandline/tests.cpp b/src/interface/commandline/tests.cpp index bb0ca6c..5c554da 100644 --- a/src/interface/commandline/tests.cpp +++ b/src/interface/commandline/tests.cpp @@ -59,8 +59,14 @@ static void startTestRender(SoftwareCanvasRenderer *renderer, const string &name } static void testNoise() { + // TODO Test all noise functions similarly + NoiseFunctionSimplex noise; + cout << "Testing simplex distribution..." << endl; + auto report = noise.checkDistribution(); + cout << report; + string filename = getFileName("noise_simplex_cache_value"); cout << "Rendering " << filename << "..." << endl; noise.getValueTexture()->saveToFile(filename); @@ -136,7 +142,7 @@ static void testCloudQuality() { scenery.autoPreset(3); scenery.getCamera()->setLocation(Vector3(5.0, 5.0, 5.0)); scenery.getCamera()->setTarget(Vector3(8.0, 7.25, 8.0)); - scenery.getTerrain()->height = 0.0; + scenery.getTerrain()->propHeightNoise()->setConfig(0.0); scenery.getTerrain()->validate(); SoftwareCanvasRenderer renderer(&scenery); @@ -182,7 +188,7 @@ static void testGodRays() { scenery.getAtmosphere()->setDayTime(12); scenery.getCamera()->setLocation(Vector3(0.0, 1.0, -50.0)); scenery.getCamera()->setTarget(Vector3(0.0, 15.0, 0.0)); - scenery.getTerrain()->height = 0.0; + scenery.getTerrain()->propHeightNoise()->setConfig(0.0); scenery.getTerrain()->validate(); scenery.getClouds()->clear(); @@ -408,15 +414,15 @@ static void testTextures() { } void runTestSuite() { - testAtmosphereBruneton(); - testCloudQuality(); - testCloudsNearGround(); - testGodRays(); - testGroundShadowQuality(); - testNearFrustum(); testNoise(); + testTextures(); + testGodRays(); + testNearFrustum(); + testCloudsNearGround(); + testVegetationModels(); testOpenGLVegetationImpostor(); testRasterizationQuality(); - testTextures(); - testVegetationModels(); + testGroundShadowQuality(); + testCloudQuality(); + testAtmosphereBruneton(); } diff --git a/src/render/software/TerrainRenderer.cpp b/src/render/software/TerrainRenderer.cpp index 339d4a2..5bb0ecd 100644 --- a/src/render/software/TerrainRenderer.cpp +++ b/src/render/software/TerrainRenderer.cpp @@ -38,7 +38,7 @@ void TerrainRenderer::setQuality(double factor) { } double TerrainRenderer::getHeight(double x, double z, bool with_painting, bool water_offset) { - return parent->getScenery()->getTerrain()->getInterpolatedHeight(x, z, true, with_painting, water_offset); + return parent->getScenery()->getTerrain()->getInterpolatedHeight(x, z, with_painting, water_offset); } TerrainRenderer::TerrainResult TerrainRenderer::getResult(double x, double z, bool with_painting) { diff --git a/src/tests/FractalNoise_Test.cpp b/src/tests/FractalNoise_Test.cpp index 7983e64..04a908e 100644 --- a/src/tests/FractalNoise_Test.cpp +++ b/src/tests/FractalNoise_Test.cpp @@ -204,3 +204,27 @@ TEST(FractalNoise, Noise3d) { ASSERT_EQ(2, noise.calls); EXPECT_DOUBLE_EQ(3.2 + 3.25, result); } + +TEST(FractalNoise, estimateRange) { + TestFractalNoise noise(0.8); + noise.setScaling(1.0, 1.0); + noise.setStep(0.1); + + double min, max; + + noise.estimateRange(&min, &max, 10.0); + EXPECT_DOUBLE_EQ(0.0, min); + EXPECT_DOUBLE_EQ(0.0, max); + + noise.estimateRange(&min, &max, 0.5); + EXPECT_DOUBLE_EQ(-0.5, min); + EXPECT_DOUBLE_EQ(0.5, max); + + noise.estimateRange(&min, &max, 0.05); + EXPECT_DOUBLE_EQ(-0.55, min); + EXPECT_DOUBLE_EQ(0.55, max); + + noise.estimateRange(&min, &max, 0.005); + EXPECT_DOUBLE_EQ(-0.555, min); + EXPECT_DOUBLE_EQ(0.555, max); +} diff --git a/src/tests/OpenGLTerrainChunk_Test.cpp b/src/tests/OpenGLTerrainChunk_Test.cpp index a294dfe..0bffe12 100644 --- a/src/tests/OpenGLTerrainChunk_Test.cpp +++ b/src/tests/OpenGLTerrainChunk_Test.cpp @@ -4,6 +4,9 @@ #include "Scenery.h" #include "OpenGLRenderer.h" #include "OpenGLVertexArray.h" +#include "TerrainDefinition.h" +#include "NoiseNode.h" +#include "TestToolNoise.h" #include "Vector3.h" static void checkVertex(const OpenGLVertexArray *array, int index, const Vector3 &expected_location, double expected_u, @@ -20,6 +23,7 @@ static void checkVertex(const OpenGLVertexArray *array, int index, const Vector3 TEST(OpenGLTerrainChunk, setFirstStepVertices) { Scenery scenery; + scenery.getTerrain()->propHeightNoise()->forceSetGenerator(new ConstantFractalNoise(0.0)); OpenGLRenderer renderer(&scenery); OpenGLTerrainChunk chunk(&renderer, 0.0, 0.0, 1.0, 1); @@ -40,6 +44,7 @@ TEST(OpenGLTerrainChunk, setFirstStepVertices) { TEST(OpenGLTerrainChunk, augmentVertices) { Scenery scenery; + scenery.getTerrain()->propHeightNoise()->forceSetGenerator(new ConstantFractalNoise(0.0)); OpenGLRenderer renderer(&scenery); OpenGLTerrainChunk chunk(&renderer, 0.0, 0.0, 1.0, 1); diff --git a/src/tests/OpenGLVariable_Test.cpp b/src/tests/OpenGLVariable_Test.cpp index 56950c3..ed21062 100644 --- a/src/tests/OpenGLVariable_Test.cpp +++ b/src/tests/OpenGLVariable_Test.cpp @@ -8,13 +8,13 @@ TEST(OpenGLVariable, setNoise) { NoiseFunctionSimplex noise; noise.setScaling(0.5, 2.0); - noise.setStep(3.0, 0.4); + noise.setStep(0.5, 0.4); var.set(noise); EXPECT_EQ(4, var.getIntValue()); EXPECT_FLOAT_EQ(2.0f, var.getFloatArrayValue(0)); EXPECT_FLOAT_EQ(1.0f, var.getFloatArrayValue(1)); - EXPECT_FLOAT_EQ(1.0f / 3.0f, var.getFloatArrayValue(2)); - EXPECT_FLOAT_EQ(1.2f, var.getFloatArrayValue(3)); + EXPECT_FLOAT_EQ(2.0f, var.getFloatArrayValue(2)); + EXPECT_FLOAT_EQ(0.2f, var.getFloatArrayValue(3)); } diff --git a/src/tests/TerrainPainting_Test.cpp b/src/tests/TerrainPainting_Test.cpp index f333a50..76cb8d0 100644 --- a/src/tests/TerrainPainting_Test.cpp +++ b/src/tests/TerrainPainting_Test.cpp @@ -2,39 +2,51 @@ #include #include "Maths.h" -#include "NoiseGenerator.h" +#include "NoiseNode.h" +#include "TestToolNoise.h" #include "TerrainDefinition.h" #include "TerrainHeightMap.h" #include "PaintedGridBrush.h" #include "FloatNode.h" -/* Noise sin period is defined at 20.0 */ -#define X_FACTOR (Maths::PI / 10.0) +// Noise sin period is defined at 20.0 +static constexpr double X_FACTOR = Maths::PI / 10.0; -static double _noise1dMock(double x) { - return sin(x * X_FACTOR) * 0.5 + 0.5; -} +namespace { +class SinFractalNoise : public FractalNoise { + public: + SinFractalNoise() { + setScaling(1.0, 2.0); + setStep(0.0); + NoiseState state; + state.setLevelCount(1); + state.setLevel(0, 0.0, 0.0, 0.0); + setState(state); + } + virtual ~SinFractalNoise(); + virtual double getBase1d(double x) const override { + return sin(x * X_FACTOR) * 0.5; + } + virtual double getBase2d(double x, double) const override { + return sin(x * X_FACTOR) * 0.5; + } + virtual double getBase3d(double x, double, double) const override { + return sin(x * X_FACTOR) * 0.5; + } +}; -static double _noise2dMock(double x, double) { - return sin(x * X_FACTOR) * 0.5 + 0.5; -} - -static double _noise3dMock(double x, double, double) { - return sin(x * X_FACTOR) * 0.5 + 0.5; +SinFractalNoise::~SinFractalNoise() { } class TerrainPainting_Test : public BaseTestCase { + public: + virtual ~TerrainPainting_Test(); + protected: virtual void SetUp() { terrain = new TerrainDefinition(NULL); - terrain->height = 3.0; - terrain->_height_noise->clearLevels(); + terrain->propHeightNoise()->forceSetGenerator(new SinFractalNoise); terrain->propWaterHeight()->setValue(0.0); - NoiseGenerator::NoiseLevel level = {1.0, 2.0, -1.0}; - terrain->_height_noise->addLevel(level); - noise_state.resetOffsets(); - terrain->_height_noise->setState(noise_state); - terrain->_height_noise->setCustomFunction(_noise1dMock, _noise2dMock, _noise3dMock); } virtual void TearDown() { @@ -44,6 +56,9 @@ class TerrainPainting_Test : public BaseTestCase { TerrainDefinition *terrain; NoiseState noise_state; }; +TerrainPainting_Test::~TerrainPainting_Test() { +} +} TEST_F(TerrainPainting_Test, grid) { /* Test base grid */ @@ -63,12 +78,9 @@ TEST_F(TerrainPainting_Test, grid) { EXPECT_DOUBLE_EQ(-1.0, terrain->getGridHeight(-5, 0, 0)); /* Test interpolated result */ - EXPECT_DOUBLE_EQ(terrain->getInterpolatedHeight(0.0, 0.0, 0, 0), 0.0); - EXPECT_DOUBLE_IN_RANGE(terrain->getInterpolatedHeight(0.5, 0.0, 0, 0), 0.1564, 0.1566); - EXPECT_DOUBLE_EQ(terrain->getInterpolatedHeight(1.0, 0.0, 0, 0), sin(1.0 * X_FACTOR)); - EXPECT_DOUBLE_EQ(terrain->getInterpolatedHeight(0.0, 0.0, 1, 0), 0.0); - EXPECT_DOUBLE_IN_RANGE(terrain->getInterpolatedHeight(0.5, 0.0, 1, 0), 3.0 * 0.1564, 3.0 * 0.1566); - EXPECT_DOUBLE_EQ(terrain->getInterpolatedHeight(1.0, 0.0, 1, 0), 3.0 * sin(1.0 * X_FACTOR)); + EXPECT_DOUBLE_EQ(terrain->getInterpolatedHeight(0.0, 0.0, false, false), 0.0); + EXPECT_DOUBLE_IN_RANGE(terrain->getInterpolatedHeight(0.5, 0.0, false, false), 0.1564, 0.1566); + EXPECT_DOUBLE_EQ(terrain->getInterpolatedHeight(1.0, 0.0, false, false), sin(X_FACTOR)); } static void _checkBrushResultSides(TerrainDefinition *terrain, PaintedGridBrush *, double center, double midhard, @@ -103,8 +115,7 @@ static void _checkBrushResult(TerrainDefinition *terrain, PaintedGridBrush *brus TEST_F(TerrainPainting_Test, brush_flatten) { /* Set up */ PaintedGridBrush brush(2.0, 2.0, 4.0); - terrain->height = 1.0; - terrain->_height_noise->forceValue(0.0); + terrain->propHeightNoise()->forceSetGenerator(new ConstantFractalNoise(0.0)); /* Test flattening center at 0.5 */ _checkBrushResult(terrain, &brush, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0); @@ -120,21 +131,13 @@ TEST_F(TerrainPainting_Test, brush_flatten) { /* Test cumulative effect */ terrain->height_map->brushFlatten(brush, 0.0, 0.0, 0.5, 0.01, true); _checkBrushResult(terrain, &brush, 0.00995, 0.00995, 0.00995, 0.0049875, 0.0, 0.0, 0); - - /* Test with height modifier */ - terrain->height = 10.0; - terrain->height_map->clearPainting(); - _checkBrushResult(terrain, &brush, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0); - terrain->height_map->brushFlatten(brush, 0.0, 0.0, 0.5, 1.0, true); - _checkBrushResult(terrain, &brush, 0.05, 0.05, 0.05, 0.025, 0.0, 0.0, 0); } TEST_F(TerrainPainting_Test, brush_reset) { /* Set up */ PaintedGridBrush brush(2.0, 2.0, 4.0); PaintedGridBrush brush_full(4.0, 0.0, 4.0); - terrain->height = 1.0; - terrain->_height_noise->forceValue(1.0); + terrain->propHeightNoise()->forceSetGenerator(new ConstantFractalNoise(1.0)); /* Test resetting at center */ _checkBrushResult(terrain, &brush, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0); @@ -154,13 +157,4 @@ TEST_F(TerrainPainting_Test, brush_reset) { /* Test cumulative effect */ terrain->height_map->brushReset(brush, 0.0, 0.0, 0.1, true); _checkBrushResult(terrain, &brush, 1.81, 1.81, 1.81, 1.9025, 2.0, 1.0, 0); - - /* Test with height modifier */ - terrain->height = 10.0; - terrain->height_map->clearPainting(); - _checkBrushResult(terrain, &brush, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0); - terrain->height_map->brushFlatten(brush_full, 0.0, 0.0, 2.0, 1.0, true); - _checkBrushResult(terrain, &brush, 1.1, 1.1, 1.1, 1.1, 1.1, 1.0, 0); - terrain->height_map->brushReset(brush, 0.0, 0.0, 0.1, true); - _checkBrushResult(terrain, &brush, 1.099, 1.099, 1.099, 1.0995, 1.1, 1.0, 0); } diff --git a/src/tests/TestToolNoise.h b/src/tests/TestToolNoise.h index 4307d20..b8d5d23 100644 --- a/src/tests/TestToolNoise.h +++ b/src/tests/TestToolNoise.h @@ -10,10 +10,10 @@ namespace { class ConstantFractalNoise : public FractalNoise { public: ConstantFractalNoise(double value) : value(value) { - // The noise will yield its value at first iteration, then its height will collapse to 0 - setScaling(1.0, 0.0); + // The noise will yield its value at first iteration, then will collapse to 0 + setStep(0.0); } - virtual double getBase3d(double, double, double) const { + virtual double getBase3d(double, double, double) const override { return value; }