Updated TerrainDefinition to use FractalNoise
This commit is contained in:
parent
a098a19ee3
commit
14143ee278
16 changed files with 224 additions and 142 deletions
|
@ -1,8 +1,11 @@
|
||||||
#include "FractalNoise.h"
|
#include "FractalNoise.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <sstream>
|
||||||
#include "PackStream.h"
|
#include "PackStream.h"
|
||||||
#include "Vector3.h"
|
#include "Vector3.h"
|
||||||
|
#include "RandomGenerator.h"
|
||||||
|
|
||||||
FractalNoise::FractalNoise() {
|
FractalNoise::FractalNoise() {
|
||||||
scaling = 1.0;
|
scaling = 1.0;
|
||||||
|
@ -50,6 +53,11 @@ void FractalNoise::setScaling(double scaling, double height) {
|
||||||
void FractalNoise::setStep(double scaling_factor, double height_factor) {
|
void FractalNoise::setStep(double scaling_factor, double height_factor) {
|
||||||
this->step_scaling = scaling_factor < 0.00000001 ? 0.0 : 1.0 / scaling_factor;
|
this->step_scaling = scaling_factor < 0.00000001 ? 0.0 : 1.0 / scaling_factor;
|
||||||
this->step_height = scaling_factor * height_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) {
|
void FractalNoise::setState(const NoiseState &state) {
|
||||||
|
@ -64,7 +72,7 @@ double FractalNoise::get1d(double detail, double x) const {
|
||||||
decltype(state_level_count) i = 0;
|
decltype(state_level_count) i = 0;
|
||||||
|
|
||||||
while (current_height >= detail) {
|
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;
|
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;
|
decltype(state_level_count) i = 0;
|
||||||
|
|
||||||
while (current_height >= detail) {
|
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;
|
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;
|
return noiseXY * mXY + noiseXZ * mXZ + noiseYZ * mYZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FractalNoise::estimateRange(double *min, double *max) const {
|
void FractalNoise::estimateRange(double *min, double *max, double detail) const {
|
||||||
// TODO Better estimate
|
*min = 0.0;
|
||||||
*max = height;
|
*max = 0.0;
|
||||||
*min = -*max;
|
|
||||||
|
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 {
|
double FractalNoise::getBase1d(double x) const {
|
||||||
|
@ -159,3 +173,48 @@ double FractalNoise::getBase1d(double x) const {
|
||||||
double FractalNoise::getBase2d(double x, double y) const {
|
double FractalNoise::getBase2d(double x, double y) const {
|
||||||
return getBase3d(x, y, 0.0);
|
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();
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "basics_global.h"
|
#include "basics_global.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include "NoiseState.h"
|
#include "NoiseState.h"
|
||||||
|
|
||||||
namespace paysages {
|
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.
|
* 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 getBase1d(double x) const;
|
||||||
virtual double getBase2d(double x, double y) 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;
|
virtual double getBase3d(double x, double y, double z) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the noise distribution, and return the report.
|
||||||
|
*/
|
||||||
|
string checkDistribution();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NoiseState state;
|
NoiseState state;
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,11 @@ void NoiseNode::setConfig(double scaling, double height, double step_scaling, do
|
||||||
noise->setStep(step_scaling, step_height);
|
noise->setStep(step_scaling, step_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NoiseNode::forceSetGenerator(FractalNoise *noise) {
|
||||||
|
delete this->noise;
|
||||||
|
this->noise = noise;
|
||||||
|
}
|
||||||
|
|
||||||
void NoiseNode::save(PackStream *stream) const {
|
void NoiseNode::save(PackStream *stream) const {
|
||||||
noise->save(stream);
|
noise->save(stream);
|
||||||
}
|
}
|
||||||
|
@ -43,5 +48,5 @@ void NoiseNode::copy(DefinitionNode *destination) const {
|
||||||
string NoiseNode::toString(int indent) const {
|
string NoiseNode::toString(int indent) const {
|
||||||
return DefinitionNode::toString(indent) + " - scaling: " + to_string(noise->getScaling()) + " step " +
|
return DefinitionNode::toString(indent) + " - scaling: " + to_string(noise->getScaling()) + " step " +
|
||||||
to_string(noise->getStepScaling()) + " - height: " + to_string(noise->getHeight()) + " step " +
|
to_string(noise->getStepScaling()) + " - height: " + to_string(noise->getHeight()) + " step " +
|
||||||
to_string(noise->getStepScaling());
|
to_string(noise->getStepHeight());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
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:
|
protected:
|
||||||
virtual void save(PackStream *stream) const override;
|
virtual void save(PackStream *stream) const override;
|
||||||
virtual void load(PackStream *stream) override;
|
virtual void load(PackStream *stream) override;
|
||||||
|
|
|
@ -5,9 +5,10 @@
|
||||||
#include "NoiseGenerator.h"
|
#include "NoiseGenerator.h"
|
||||||
#include "PackStream.h"
|
#include "PackStream.h"
|
||||||
#include "FloatNode.h"
|
#include "FloatNode.h"
|
||||||
|
#include "NoiseNode.h"
|
||||||
|
#include "FractalNoise.h"
|
||||||
|
|
||||||
TerrainDefinition::TerrainDefinition(DefinitionNode *parent) : DefinitionNode(parent, "terrain", "terrain") {
|
TerrainDefinition::TerrainDefinition(DefinitionNode *parent) : DefinitionNode(parent, "terrain", "terrain") {
|
||||||
height = 1.0;
|
|
||||||
shadow_smoothing = 0.0;
|
shadow_smoothing = 0.0;
|
||||||
|
|
||||||
height_map = new TerrainHeightMap(this);
|
height_map = new TerrainHeightMap(this);
|
||||||
|
@ -15,57 +16,42 @@ TerrainDefinition::TerrainDefinition(DefinitionNode *parent) : DefinitionNode(pa
|
||||||
addChild(height_map);
|
addChild(height_map);
|
||||||
|
|
||||||
water_height = new FloatNode(this, "water_height");
|
water_height = new FloatNode(this, "water_height");
|
||||||
|
height_noise = new NoiseNode(this, "height_noise");
|
||||||
_height_noise = new NoiseGenerator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TerrainDefinition::~TerrainDefinition() {
|
TerrainDefinition::~TerrainDefinition() {
|
||||||
delete _height_noise;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainDefinition::validate() {
|
void TerrainDefinition::validate() {
|
||||||
_height_noise->validate();
|
DefinitionNode::validate();
|
||||||
|
|
||||||
if (height < 1.0) {
|
// Get base noise range
|
||||||
height = 1.0;
|
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();
|
has_painting = height_map->hasPainting();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainDefinition::copy(DefinitionNode *_destination) const {
|
void TerrainDefinition::copy(DefinitionNode *_destination) const {
|
||||||
TerrainDefinition *destination = (TerrainDefinition *)_destination;
|
if (auto destination = static_cast<TerrainDefinition *>(_destination)) {
|
||||||
|
destination->shadow_smoothing = shadow_smoothing;
|
||||||
|
|
||||||
destination->height = height;
|
height_map->copy(destination->height_map);
|
||||||
destination->shadow_smoothing = shadow_smoothing;
|
|
||||||
|
|
||||||
height_map->copy(destination->height_map);
|
destination->validate();
|
||||||
|
}
|
||||||
_height_noise->copy(destination->_height_noise);
|
|
||||||
|
|
||||||
destination->validate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainDefinition::save(PackStream *stream) const {
|
void TerrainDefinition::save(PackStream *stream) const {
|
||||||
DefinitionNode::save(stream);
|
DefinitionNode::save(stream);
|
||||||
|
|
||||||
stream->write(&height);
|
|
||||||
stream->write(&shadow_smoothing);
|
stream->write(&shadow_smoothing);
|
||||||
_height_noise->save(stream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainDefinition::load(PackStream *stream) {
|
void TerrainDefinition::load(PackStream *stream) {
|
||||||
DefinitionNode::load(stream);
|
DefinitionNode::load(stream);
|
||||||
|
|
||||||
stream->read(&height);
|
|
||||||
stream->read(&shadow_smoothing);
|
stream->read(&shadow_smoothing);
|
||||||
_height_noise->load(stream);
|
|
||||||
|
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
@ -74,29 +60,26 @@ double TerrainDefinition::getGridHeight(int x, int z, bool with_painting) {
|
||||||
double h;
|
double h;
|
||||||
|
|
||||||
if (!with_painting || !has_painting || !height_map->getGridValue(x, z, &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;
|
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) {
|
bool water_offset) {
|
||||||
double h;
|
double h;
|
||||||
|
|
||||||
if (!with_painting || !has_painting || !height_map->getInterpolatedValue(x, z, &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 + getWaterOffset()) : h);
|
||||||
return (water_offset ? (h - water_height->getValue()) : h) * height;
|
|
||||||
} else {
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double TerrainDefinition::getWaterOffset() const {
|
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() {
|
HeightInfo TerrainDefinition::getHeightInfo() {
|
||||||
|
@ -114,20 +97,12 @@ unsigned long TerrainDefinition::getMemoryStats() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainDefinition::applyPreset(TerrainPreset preset, RandomGenerator &random) {
|
void TerrainDefinition::applyPreset(TerrainPreset preset, RandomGenerator &random) {
|
||||||
int resolution = 8;
|
|
||||||
switch (preset) {
|
switch (preset) {
|
||||||
case TERRAIN_PRESET_STANDARD:
|
case TERRAIN_PRESET_STANDARD:
|
||||||
_height_noise->randomizeOffsets(random);
|
height_noise->randomize(random);
|
||||||
_height_noise->clearLevels();
|
height_noise->setConfig(400.0, 0.1, 0.5, 1.02);
|
||||||
_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;
|
|
||||||
shadow_smoothing = 0.03;
|
shadow_smoothing = 0.03;
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
water_height->setValue(-0.3);
|
water_height->setValue(-0.3);
|
||||||
|
|
|
@ -28,9 +28,12 @@ class DEFINITIONSHARED_EXPORT TerrainDefinition : public DefinitionNode {
|
||||||
inline FloatNode *propWaterHeight() const {
|
inline FloatNode *propWaterHeight() const {
|
||||||
return water_height;
|
return water_height;
|
||||||
}
|
}
|
||||||
|
inline NoiseNode *propHeightNoise() const {
|
||||||
|
return height_noise;
|
||||||
|
}
|
||||||
|
|
||||||
double getGridHeight(int x, int z, bool with_painting);
|
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;
|
double getWaterOffset() const;
|
||||||
unsigned long getMemoryStats();
|
unsigned long getMemoryStats();
|
||||||
HeightInfo getHeightInfo();
|
HeightInfo getHeightInfo();
|
||||||
|
@ -40,19 +43,17 @@ class DEFINITIONSHARED_EXPORT TerrainDefinition : public DefinitionNode {
|
||||||
void applyPreset(TerrainPreset preset, RandomGenerator &random = RandomGeneratorDefault);
|
void applyPreset(TerrainPreset preset, RandomGenerator &random = RandomGeneratorDefault);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
double height;
|
|
||||||
double shadow_smoothing;
|
double shadow_smoothing;
|
||||||
|
|
||||||
TerrainHeightMap *height_map;
|
TerrainHeightMap *height_map;
|
||||||
bool has_painting;
|
bool has_painting;
|
||||||
|
|
||||||
double _detail;
|
|
||||||
NoiseGenerator *_height_noise;
|
|
||||||
double _min_height;
|
double _min_height;
|
||||||
double _max_height;
|
double _max_height;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FloatNode *water_height;
|
FloatNode *water_height;
|
||||||
|
NoiseNode *height_noise;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
void TerrainHeightMap::brushElevation(const PaintedGridBrush &brush, double x, double y, double value, bool commit) {
|
||||||
PaintedGridBrushRaiseLower sbrush(brush);
|
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,
|
void TerrainHeightMap::brushFlatten(const PaintedGridBrush &brush, double x, double y, double height, double force,
|
||||||
bool commit) {
|
bool commit) {
|
||||||
PaintedGridBrushFlatten sbrush(brush, height);
|
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) {
|
void TerrainHeightMap::brushSmooth(const PaintedGridBrush &brush, double x, double y, double value, bool commit) {
|
||||||
PaintedGridBrushSmooth sbrush(brush);
|
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,
|
void TerrainHeightMap::brushAddNoise(const PaintedGridBrush &brush, double x, double y, NoiseGenerator *generator,
|
||||||
double value, bool commit) {
|
double value, bool commit) {
|
||||||
PaintedGridBrushAddNoise sbrush(brush, generator);
|
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) {
|
void TerrainHeightMap::brushReset(const PaintedGridBrush &brush, double x, double y, double value, bool commit) {
|
||||||
PaintedGridBrushReset sbrush(brush);
|
PaintedGridBrushReset sbrush(brush);
|
||||||
applyBrush(sbrush, x, y, value / terrain->height, commit);
|
applyBrush(sbrush, x, y, value, commit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainHeightMap::clearPainting() {
|
void TerrainHeightMap::clearPainting() {
|
||||||
|
|
|
@ -32,9 +32,8 @@ void TextureLayerDefinition::validate() {
|
||||||
|
|
||||||
material->validate();
|
material->validate();
|
||||||
|
|
||||||
/* Update zone height range */
|
// Update zone height range
|
||||||
const Scenery *scenery = getScenery();
|
if (auto scenery = getScenery()) {
|
||||||
if (scenery) {
|
|
||||||
TerrainDefinition *terrain = scenery->getTerrain();
|
TerrainDefinition *terrain = scenery->getTerrain();
|
||||||
HeightInfo height_info = terrain->getHeightInfo();
|
HeightInfo height_info = terrain->getHeightInfo();
|
||||||
terrain_zone->setRelativeHeight(height_info.min_height, height_info.base_height, height_info.max_height);
|
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;
|
material->shininess = 4.0;
|
||||||
break;
|
break;
|
||||||
case TEXTURES_LAYER_PRESET_ROCK:
|
case TEXTURES_LAYER_PRESET_ROCK:
|
||||||
terrain_zone->addHeightRangeQuick(1.0, 0.55, 0.7, 0.9, 1.0);
|
terrain_zone->addHeightRangeQuick(1.0, 0.6, 0.7, 0.87, 0.95);
|
||||||
displacement_noise->setConfig(1.0, 0.3, 0.5, 0.85);
|
displacement_noise->setConfig(1.0, 0.4, 0.5, 0.85);
|
||||||
detail_noise->setConfig(0.02, 0.04);
|
detail_noise->setConfig(0.02, 0.04);
|
||||||
material->setColor(0.6, 0.55, 0.57, 1.0);
|
material->setColor(0.6, 0.55, 0.57, 1.0);
|
||||||
material->reflection = 0.006;
|
material->reflection = 0.006;
|
||||||
material->shininess = 6.0;
|
material->shininess = 6.0;
|
||||||
break;
|
break;
|
||||||
case TEXTURES_LAYER_PRESET_GRASS:
|
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);
|
terrain_zone->addSlopeRangeQuick(1.0, 0.0, 0.0, 0.05, 0.4);
|
||||||
displacement_noise->setConfig(0.4, 0.05);
|
displacement_noise->setConfig(0.4, 0.05);
|
||||||
detail_noise->setConfig(0.01, 0.1);
|
detail_noise->setConfig(0.01, 0.1);
|
||||||
|
@ -98,7 +97,7 @@ void TextureLayerDefinition::applyPreset(TextureLayerPreset preset, RandomGenera
|
||||||
break;
|
break;
|
||||||
case TEXTURES_LAYER_PRESET_SAND:
|
case TEXTURES_LAYER_PRESET_SAND:
|
||||||
terrain_zone->addHeightRangeQuick(1.0, 0.495, 0.505, 0.56, 0.63);
|
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);
|
displacement_noise->setConfig(0.04, 0.1, 0.5, 0.3);
|
||||||
detail_noise->setConfig(0.004, 0.08);
|
detail_noise->setConfig(0.004, 0.08);
|
||||||
material->setColor(1.2, 1.1, 0.9, 1.0);
|
material->setColor(1.2, 1.1, 0.9, 1.0);
|
||||||
|
@ -106,8 +105,8 @@ void TextureLayerDefinition::applyPreset(TextureLayerPreset preset, RandomGenera
|
||||||
material->shininess = 1.0;
|
material->shininess = 1.0;
|
||||||
break;
|
break;
|
||||||
case TEXTURES_LAYER_PRESET_SNOW:
|
case TEXTURES_LAYER_PRESET_SNOW:
|
||||||
terrain_zone->addHeightRangeQuick(1.0, 0.77, 0.85, 1.0, 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.2, 1.0);
|
terrain_zone->addSlopeRangeQuick(1.0, 0.0, 0.0, 0.1, 1.0);
|
||||||
displacement_noise->setConfig(0.4, 0.07);
|
displacement_noise->setConfig(0.4, 0.07);
|
||||||
detail_noise->setConfig(0.01, 0.03);
|
detail_noise->setConfig(0.01, 0.03);
|
||||||
material->setColor(5.0, 5.0, 5.0, 1.0);
|
material->setColor(5.0, 5.0, 5.0, 1.0);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include "Zone.h"
|
#include "Zone.h"
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#include "Curve.h"
|
#include "Curve.h"
|
||||||
#include "PackStream.h"
|
#include "PackStream.h"
|
||||||
#include "Vector3.h"
|
#include "Vector3.h"
|
||||||
|
@ -39,15 +38,15 @@ void Zone::load(PackStream *stream) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Zone::copy(DefinitionNode *_destination) const {
|
void Zone::copy(DefinitionNode *_destination) const {
|
||||||
Zone *destination = (Zone *)_destination;
|
if (auto destination = static_cast<Zone *>(_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;
|
value_by_height->copy(destination->value_by_height);
|
||||||
destination->relative_height_min = relative_height_min;
|
value_by_slope->copy(destination->value_by_slope);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Zone::clear() {
|
void Zone::clear() {
|
||||||
|
|
|
@ -59,8 +59,14 @@ static void startTestRender(SoftwareCanvasRenderer *renderer, const string &name
|
||||||
}
|
}
|
||||||
|
|
||||||
static void testNoise() {
|
static void testNoise() {
|
||||||
|
// TODO Test all noise functions similarly
|
||||||
|
|
||||||
NoiseFunctionSimplex noise;
|
NoiseFunctionSimplex noise;
|
||||||
|
|
||||||
|
cout << "Testing simplex distribution..." << endl;
|
||||||
|
auto report = noise.checkDistribution();
|
||||||
|
cout << report;
|
||||||
|
|
||||||
string filename = getFileName("noise_simplex_cache_value");
|
string filename = getFileName("noise_simplex_cache_value");
|
||||||
cout << "Rendering " << filename << "..." << endl;
|
cout << "Rendering " << filename << "..." << endl;
|
||||||
noise.getValueTexture()->saveToFile(filename);
|
noise.getValueTexture()->saveToFile(filename);
|
||||||
|
@ -136,7 +142,7 @@ static void testCloudQuality() {
|
||||||
scenery.autoPreset(3);
|
scenery.autoPreset(3);
|
||||||
scenery.getCamera()->setLocation(Vector3(5.0, 5.0, 5.0));
|
scenery.getCamera()->setLocation(Vector3(5.0, 5.0, 5.0));
|
||||||
scenery.getCamera()->setTarget(Vector3(8.0, 7.25, 8.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();
|
scenery.getTerrain()->validate();
|
||||||
|
|
||||||
SoftwareCanvasRenderer renderer(&scenery);
|
SoftwareCanvasRenderer renderer(&scenery);
|
||||||
|
@ -182,7 +188,7 @@ static void testGodRays() {
|
||||||
scenery.getAtmosphere()->setDayTime(12);
|
scenery.getAtmosphere()->setDayTime(12);
|
||||||
scenery.getCamera()->setLocation(Vector3(0.0, 1.0, -50.0));
|
scenery.getCamera()->setLocation(Vector3(0.0, 1.0, -50.0));
|
||||||
scenery.getCamera()->setTarget(Vector3(0.0, 15.0, 0.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.getTerrain()->validate();
|
||||||
scenery.getClouds()->clear();
|
scenery.getClouds()->clear();
|
||||||
|
|
||||||
|
@ -408,15 +414,15 @@ static void testTextures() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void runTestSuite() {
|
void runTestSuite() {
|
||||||
testAtmosphereBruneton();
|
|
||||||
testCloudQuality();
|
|
||||||
testCloudsNearGround();
|
|
||||||
testGodRays();
|
|
||||||
testGroundShadowQuality();
|
|
||||||
testNearFrustum();
|
|
||||||
testNoise();
|
testNoise();
|
||||||
|
testTextures();
|
||||||
|
testGodRays();
|
||||||
|
testNearFrustum();
|
||||||
|
testCloudsNearGround();
|
||||||
|
testVegetationModels();
|
||||||
testOpenGLVegetationImpostor();
|
testOpenGLVegetationImpostor();
|
||||||
testRasterizationQuality();
|
testRasterizationQuality();
|
||||||
testTextures();
|
testGroundShadowQuality();
|
||||||
testVegetationModels();
|
testCloudQuality();
|
||||||
|
testAtmosphereBruneton();
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ void TerrainRenderer::setQuality(double factor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
double TerrainRenderer::getHeight(double x, double z, bool with_painting, bool water_offset) {
|
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) {
|
TerrainRenderer::TerrainResult TerrainRenderer::getResult(double x, double z, bool with_painting) {
|
||||||
|
|
|
@ -204,3 +204,27 @@ TEST(FractalNoise, Noise3d) {
|
||||||
ASSERT_EQ(2, noise.calls);
|
ASSERT_EQ(2, noise.calls);
|
||||||
EXPECT_DOUBLE_EQ(3.2 + 3.25, result);
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
#include "Scenery.h"
|
#include "Scenery.h"
|
||||||
#include "OpenGLRenderer.h"
|
#include "OpenGLRenderer.h"
|
||||||
#include "OpenGLVertexArray.h"
|
#include "OpenGLVertexArray.h"
|
||||||
|
#include "TerrainDefinition.h"
|
||||||
|
#include "NoiseNode.h"
|
||||||
|
#include "TestToolNoise.h"
|
||||||
#include "Vector3.h"
|
#include "Vector3.h"
|
||||||
|
|
||||||
static void checkVertex(const OpenGLVertexArray *array, int index, const Vector3 &expected_location, double expected_u,
|
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) {
|
TEST(OpenGLTerrainChunk, setFirstStepVertices) {
|
||||||
Scenery scenery;
|
Scenery scenery;
|
||||||
|
scenery.getTerrain()->propHeightNoise()->forceSetGenerator(new ConstantFractalNoise(0.0));
|
||||||
OpenGLRenderer renderer(&scenery);
|
OpenGLRenderer renderer(&scenery);
|
||||||
OpenGLTerrainChunk chunk(&renderer, 0.0, 0.0, 1.0, 1);
|
OpenGLTerrainChunk chunk(&renderer, 0.0, 0.0, 1.0, 1);
|
||||||
|
|
||||||
|
@ -40,6 +44,7 @@ TEST(OpenGLTerrainChunk, setFirstStepVertices) {
|
||||||
|
|
||||||
TEST(OpenGLTerrainChunk, augmentVertices) {
|
TEST(OpenGLTerrainChunk, augmentVertices) {
|
||||||
Scenery scenery;
|
Scenery scenery;
|
||||||
|
scenery.getTerrain()->propHeightNoise()->forceSetGenerator(new ConstantFractalNoise(0.0));
|
||||||
OpenGLRenderer renderer(&scenery);
|
OpenGLRenderer renderer(&scenery);
|
||||||
OpenGLTerrainChunk chunk(&renderer, 0.0, 0.0, 1.0, 1);
|
OpenGLTerrainChunk chunk(&renderer, 0.0, 0.0, 1.0, 1);
|
||||||
|
|
||||||
|
|
|
@ -8,13 +8,13 @@ TEST(OpenGLVariable, setNoise) {
|
||||||
NoiseFunctionSimplex noise;
|
NoiseFunctionSimplex noise;
|
||||||
|
|
||||||
noise.setScaling(0.5, 2.0);
|
noise.setScaling(0.5, 2.0);
|
||||||
noise.setStep(3.0, 0.4);
|
noise.setStep(0.5, 0.4);
|
||||||
|
|
||||||
var.set(noise);
|
var.set(noise);
|
||||||
|
|
||||||
EXPECT_EQ(4, var.getIntValue());
|
EXPECT_EQ(4, var.getIntValue());
|
||||||
EXPECT_FLOAT_EQ(2.0f, var.getFloatArrayValue(0));
|
EXPECT_FLOAT_EQ(2.0f, var.getFloatArrayValue(0));
|
||||||
EXPECT_FLOAT_EQ(1.0f, var.getFloatArrayValue(1));
|
EXPECT_FLOAT_EQ(1.0f, var.getFloatArrayValue(1));
|
||||||
EXPECT_FLOAT_EQ(1.0f / 3.0f, var.getFloatArrayValue(2));
|
EXPECT_FLOAT_EQ(2.0f, var.getFloatArrayValue(2));
|
||||||
EXPECT_FLOAT_EQ(1.2f, var.getFloatArrayValue(3));
|
EXPECT_FLOAT_EQ(0.2f, var.getFloatArrayValue(3));
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,39 +2,51 @@
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include "Maths.h"
|
#include "Maths.h"
|
||||||
#include "NoiseGenerator.h"
|
#include "NoiseNode.h"
|
||||||
|
#include "TestToolNoise.h"
|
||||||
#include "TerrainDefinition.h"
|
#include "TerrainDefinition.h"
|
||||||
#include "TerrainHeightMap.h"
|
#include "TerrainHeightMap.h"
|
||||||
#include "PaintedGridBrush.h"
|
#include "PaintedGridBrush.h"
|
||||||
#include "FloatNode.h"
|
#include "FloatNode.h"
|
||||||
|
|
||||||
/* Noise sin period is defined at 20.0 */
|
// Noise sin period is defined at 20.0
|
||||||
#define X_FACTOR (Maths::PI / 10.0)
|
static constexpr double X_FACTOR = Maths::PI / 10.0;
|
||||||
|
|
||||||
static double _noise1dMock(double x) {
|
namespace {
|
||||||
return sin(x * X_FACTOR) * 0.5 + 0.5;
|
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) {
|
SinFractalNoise::~SinFractalNoise() {
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class TerrainPainting_Test : public BaseTestCase {
|
class TerrainPainting_Test : public BaseTestCase {
|
||||||
|
public:
|
||||||
|
virtual ~TerrainPainting_Test();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void SetUp() {
|
virtual void SetUp() {
|
||||||
terrain = new TerrainDefinition(NULL);
|
terrain = new TerrainDefinition(NULL);
|
||||||
terrain->height = 3.0;
|
terrain->propHeightNoise()->forceSetGenerator(new SinFractalNoise);
|
||||||
terrain->_height_noise->clearLevels();
|
|
||||||
terrain->propWaterHeight()->setValue(0.0);
|
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() {
|
virtual void TearDown() {
|
||||||
|
@ -44,6 +56,9 @@ class TerrainPainting_Test : public BaseTestCase {
|
||||||
TerrainDefinition *terrain;
|
TerrainDefinition *terrain;
|
||||||
NoiseState noise_state;
|
NoiseState noise_state;
|
||||||
};
|
};
|
||||||
|
TerrainPainting_Test::~TerrainPainting_Test() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(TerrainPainting_Test, grid) {
|
TEST_F(TerrainPainting_Test, grid) {
|
||||||
/* Test base grid */
|
/* Test base grid */
|
||||||
|
@ -63,12 +78,9 @@ TEST_F(TerrainPainting_Test, grid) {
|
||||||
EXPECT_DOUBLE_EQ(-1.0, terrain->getGridHeight(-5, 0, 0));
|
EXPECT_DOUBLE_EQ(-1.0, terrain->getGridHeight(-5, 0, 0));
|
||||||
|
|
||||||
/* Test interpolated result */
|
/* Test interpolated result */
|
||||||
EXPECT_DOUBLE_EQ(terrain->getInterpolatedHeight(0.0, 0.0, 0, 0), 0.0);
|
EXPECT_DOUBLE_EQ(terrain->getInterpolatedHeight(0.0, 0.0, false, false), 0.0);
|
||||||
EXPECT_DOUBLE_IN_RANGE(terrain->getInterpolatedHeight(0.5, 0.0, 0, 0), 0.1564, 0.1566);
|
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, 0, 0), sin(1.0 * X_FACTOR));
|
EXPECT_DOUBLE_EQ(terrain->getInterpolatedHeight(1.0, 0.0, false, false), sin(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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _checkBrushResultSides(TerrainDefinition *terrain, PaintedGridBrush *, double center, double midhard,
|
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) {
|
TEST_F(TerrainPainting_Test, brush_flatten) {
|
||||||
/* Set up */
|
/* Set up */
|
||||||
PaintedGridBrush brush(2.0, 2.0, 4.0);
|
PaintedGridBrush brush(2.0, 2.0, 4.0);
|
||||||
terrain->height = 1.0;
|
terrain->propHeightNoise()->forceSetGenerator(new ConstantFractalNoise(0.0));
|
||||||
terrain->_height_noise->forceValue(0.0);
|
|
||||||
|
|
||||||
/* Test flattening center at 0.5 */
|
/* Test flattening center at 0.5 */
|
||||||
_checkBrushResult(terrain, &brush, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0);
|
_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 */
|
/* Test cumulative effect */
|
||||||
terrain->height_map->brushFlatten(brush, 0.0, 0.0, 0.5, 0.01, true);
|
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);
|
_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) {
|
TEST_F(TerrainPainting_Test, brush_reset) {
|
||||||
/* Set up */
|
/* Set up */
|
||||||
PaintedGridBrush brush(2.0, 2.0, 4.0);
|
PaintedGridBrush brush(2.0, 2.0, 4.0);
|
||||||
PaintedGridBrush brush_full(4.0, 0.0, 4.0);
|
PaintedGridBrush brush_full(4.0, 0.0, 4.0);
|
||||||
terrain->height = 1.0;
|
terrain->propHeightNoise()->forceSetGenerator(new ConstantFractalNoise(1.0));
|
||||||
terrain->_height_noise->forceValue(1.0);
|
|
||||||
|
|
||||||
/* Test resetting at center */
|
/* Test resetting at center */
|
||||||
_checkBrushResult(terrain, &brush, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0);
|
_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 */
|
/* Test cumulative effect */
|
||||||
terrain->height_map->brushReset(brush, 0.0, 0.0, 0.1, true);
|
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);
|
_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);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,10 @@ namespace {
|
||||||
class ConstantFractalNoise : public FractalNoise {
|
class ConstantFractalNoise : public FractalNoise {
|
||||||
public:
|
public:
|
||||||
ConstantFractalNoise(double value) : value(value) {
|
ConstantFractalNoise(double value) : value(value) {
|
||||||
// The noise will yield its value at first iteration, then its height will collapse to 0
|
// The noise will yield its value at first iteration, then will collapse to 0
|
||||||
setScaling(1.0, 0.0);
|
setStep(0.0);
|
||||||
}
|
}
|
||||||
virtual double getBase3d(double, double, double) const {
|
virtual double getBase3d(double, double, double) const override {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue