190 lines
6.1 KiB
C++
190 lines
6.1 KiB
C++
#include "TerrainDefinition.h"
|
|
|
|
#include <cmath>
|
|
#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<TerrainDefinition *>(_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<TextureLayerDefinition *>(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();
|
|
}
|