#include "TerrainDefinition.h" #include #include "Layers.h" #include "TextureLayerDefinition.h" #include "TerrainHeightMap.h" #include "NoiseGenerator.h" #include "PackStream.h" #include "FloatNode.h" #include "NoiseNode.h" #include "MaterialNode.h" #include "FractalNoise.h" #include "SurfaceMaterial.h" #include "Color.h" #include "Zone.h" static DefinitionNode *_newTerrainDisplacement(Layers *parent, const string &name) { return new TextureLayerDefinition(parent, name); } static DefinitionNode *_newTerrainColor(Layers *parent, const string &name) { return new TextureLayerDefinition(parent, name); } TerrainDefinition::TerrainDefinition(DefinitionNode *parent) : DefinitionNode(parent, "terrain", "terrain") { shadow_smoothing = 0.0; height_map = new TerrainHeightMap(this); has_painting = false; addChild(height_map); default_material = new MaterialNode(this, "default_material"); water_height = new FloatNode(this, "water_height"); height_noise = new NoiseNode(this, "height_noise"); displacements = new Layers(this, "displacements", _newTerrainDisplacement); materials = new Layers(this, "materials", _newTerrainColor); } TerrainDefinition::~TerrainDefinition() { } void TerrainDefinition::validate() { DefinitionNode::validate(); // Get base noise range height_noise->getGenerator()->estimateRange(&_min_height, &_max_height, 0.1); // TODO Alter limits with heightmap min/max double max_displacement = getMaximalDisplacement(); _min_height -= max_displacement; _max_height += max_displacement; has_painting = height_map->hasPainting(); } void TerrainDefinition::copy(DefinitionNode *_destination) const { if (auto destination = dynamic_cast(_destination)) { destination->shadow_smoothing = shadow_smoothing; height_map->copy(destination->height_map); destination->validate(); } } void TerrainDefinition::save(PackStream *stream) const { DefinitionNode::save(stream); stream->write(&shadow_smoothing); } void TerrainDefinition::load(PackStream *stream) { DefinitionNode::load(stream); stream->read(&shadow_smoothing); validate(); } 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->getGenerator()->get2d(1.0, to_double(x), to_double(z)); } return h; } 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->getGenerator()->get2d(1.0, x, z); } return (water_offset ? (h + getWaterOffset()) : h); } double TerrainDefinition::getWaterOffset() const { double height_power = (_max_height - _min_height) * 0.5; return -water_height->getValue() * height_power; } double TerrainDefinition::getMaximalDisplacement() { double result = 0.0; int n = displacements->getLayerCount(); for (int i = 0; i < n; i++) { if (auto layer = dynamic_cast(displacements->getLayer(i))) { result += layer->getMaximalDisplacement(); } } return result; } HeightInfo TerrainDefinition::getHeightInfo() { HeightInfo result; result.min_height = _min_height; result.max_height = _max_height; result.base_height = -getWaterOffset(); return result; } unsigned long TerrainDefinition::getMemoryStats() { return height_map->getMemoryStats(); } void TerrainDefinition::applyPreset(TerrainPreset preset, RandomGenerator &random) { default_material->setSurfaceMaterial(SurfaceMaterial(Color(0.6, 0.55, 0.57, 1.0))); displacements->clear(); materials->clear(); switch (preset) { case TERRAIN_PRESET_STANDARD: height_noise->randomize(random); height_noise->setConfig(400.0, 0.1, 0.5, 1.02); shadow_smoothing = 0.03; TextureLayerDefinition mountain(NULL, "mountain"); mountain.propTerrainZone()->addHeightRangeQuick(1.0, 0.4, 0.7, 0.87, 0.95); mountain.propDisplacementNoise()->setConfig(4.0, 0.15, 0.5, 0.8); displacements->addLayer(mountain); TextureLayerDefinition mud(NULL, "mud"); mud.propTerrainZone()->addHeightRangeQuick(1.0, 0.4, 0.7, 0.87, 0.95); mud.propMaterial()->propBump()->setConfig(0.05, 0.1, 0.3); mud.propMaterial()->setSurfaceMaterial(Color(0.015, 0.014, 0.014), 0.001, 4.0); materials->addLayer(mud); TextureLayerDefinition rock(NULL, "rock"); rock.propTerrainZone()->addHeightRangeQuick(1.0, 0.6, 0.7, 0.87, 0.95); rock.propMaterial()->propBump()->setConfig(0.02, 0.04); rock.propMaterial()->setSurfaceMaterial(Color(0.6, 0.55, 0.57), 0.002, 6.0); materials->addLayer(rock); TextureLayerDefinition grass(NULL, "grass"); grass.propTerrainZone()->addHeightRangeQuick(1.0, 0.45, 0.5, 0.7, 0.9); grass.propTerrainZone()->addSlopeRangeQuick(1.0, 0.0, 0.0, 0.05, 0.4); grass.propMaterial()->propBump()->setConfig(2.0, 0.05); grass.propMaterial()->setSurfaceMaterial(Color(0.12, 0.19, 0.035), 0.001, 4.0); materials->addLayer(grass); TextureLayerDefinition sand(NULL, "sand"); sand.propTerrainZone()->addHeightRangeQuick(1.0, 0.495, 0.505, 0.56, 0.63); sand.propTerrainZone()->addSlopeRangeQuick(1.0, 0.0, 0.0, 0.05, 0.3); sand.propMaterial()->propBump()->setConfig(0.004, 0.08); sand.propMaterial()->setSurfaceMaterial(Color(1.2, 1.1, 0.9), 0.003, 1.0); materials->addLayer(sand); TextureLayerDefinition snow(NULL, "snow"); snow.propTerrainZone()->addHeightRangeQuick(1.0, 0.87, 0.95, 10.0, 100.0); snow.propTerrainZone()->addSlopeRangeQuick(1.0, 0.0, 0.0, 0.1, 1.0); snow.propMaterial()->propBump()->setConfig(0.01, 0.03); snow.propMaterial()->setSurfaceMaterial(Color(5.0, 5.0, 5.0), 0.01, 0.6); materials->addLayer(snow); break; } water_height->setValue(-0.3); height_map->clearPainting(); validate(); }