WIP on textures refactoring
This commit is contained in:
parent
b3787ed7ea
commit
24b73b1504
22 changed files with 266 additions and 590 deletions
|
@ -7,7 +7,6 @@
|
|||
#include "CameraDefinition.h"
|
||||
#include "CloudsDefinition.h"
|
||||
#include "TerrainDefinition.h"
|
||||
#include "TexturesDefinition.h"
|
||||
#include "VegetationDefinition.h"
|
||||
#include "WaterDefinition.h"
|
||||
#include "DiffManager.h"
|
||||
|
@ -24,7 +23,6 @@ Scenery::Scenery() : DefinitionNode(NULL, "scenery", "scenery") {
|
|||
camera = new CameraDefinition(this);
|
||||
clouds = new CloudsDefinition(this);
|
||||
terrain = new TerrainDefinition(this);
|
||||
textures = new TexturesDefinition(this);
|
||||
water = new WaterDefinition(this);
|
||||
vegetation = new VegetationDefinition(this);
|
||||
}
|
||||
|
@ -135,7 +133,6 @@ const Scenery *Scenery::getScenery() const {
|
|||
|
||||
void Scenery::autoPreset(RandomGenerator &random) {
|
||||
terrain->applyPreset(TerrainDefinition::TERRAIN_PRESET_STANDARD, random);
|
||||
textures->applyPreset(TexturesDefinition::TEXTURES_PRESET_FULL, random);
|
||||
atmosphere->applyPreset(AtmosphereDefinition::ATMOSPHERE_PRESET_CLEAR_DAY, random);
|
||||
water->applyPreset(WaterDefinition::WATER_PRESET_LAKE, random);
|
||||
clouds->applyPreset(CloudsDefinition::CLOUDS_PRESET_PARTLY_CLOUDY, random);
|
||||
|
@ -187,14 +184,6 @@ void Scenery::getTerrain(TerrainDefinition *terrain) {
|
|||
this->terrain->copy(terrain);
|
||||
}
|
||||
|
||||
void Scenery::setTextures(TexturesDefinition *textures) {
|
||||
textures->copy(this->textures);
|
||||
}
|
||||
|
||||
void Scenery::getTextures(TexturesDefinition *textures) {
|
||||
this->textures->copy(textures);
|
||||
}
|
||||
|
||||
void Scenery::setVegetation(VegetationDefinition *vegetation) {
|
||||
vegetation->copy(this->vegetation);
|
||||
}
|
||||
|
@ -213,7 +202,7 @@ void Scenery::getWater(WaterDefinition *water) {
|
|||
|
||||
void Scenery::keepCameraAboveGround(CameraDefinition *camera) {
|
||||
Vector3 camera_location = camera->getLocation();
|
||||
double terrain_height = terrain->getInterpolatedHeight(camera_location.x, camera_location.z, true, true) + 1.0;
|
||||
double terrain_height = terrain->getInterpolatedHeight(camera_location.x, camera_location.z, true, true) + terrain->getMaximalDisplacement() + 0.5;
|
||||
double water_height = 0.5;
|
||||
if (camera_location.y < water_height || camera_location.y < terrain_height) {
|
||||
double diff = ((water_height > terrain_height) ? water_height : terrain_height) - camera_location.y;
|
||||
|
|
|
@ -95,12 +95,6 @@ class DEFINITIONSHARED_EXPORT Scenery : public DefinitionNode {
|
|||
}
|
||||
void getTerrain(TerrainDefinition *terrain);
|
||||
|
||||
void setTextures(TexturesDefinition *textures);
|
||||
inline TexturesDefinition *getTextures() const {
|
||||
return textures;
|
||||
}
|
||||
void getTextures(TexturesDefinition *textures);
|
||||
|
||||
void setVegetation(VegetationDefinition *Vegetation);
|
||||
inline VegetationDefinition *getVegetation() const {
|
||||
return vegetation;
|
||||
|
@ -120,7 +114,6 @@ class DEFINITIONSHARED_EXPORT Scenery : public DefinitionNode {
|
|||
CameraDefinition *camera;
|
||||
CloudsDefinition *clouds;
|
||||
TerrainDefinition *terrain;
|
||||
TexturesDefinition *textures;
|
||||
VegetationDefinition *vegetation;
|
||||
WaterDefinition *water;
|
||||
};
|
||||
|
|
|
@ -1,12 +1,26 @@
|
|||
#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;
|
||||
|
@ -15,8 +29,13 @@ TerrainDefinition::TerrainDefinition(DefinitionNode *parent) : DefinitionNode(pa
|
|||
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() {
|
||||
|
@ -27,7 +46,11 @@ void TerrainDefinition::validate() {
|
|||
|
||||
// Get base noise range
|
||||
height_noise->getGenerator()->estimateRange(&_min_height, &_max_height, 0.1);
|
||||
// TODO Alter limits with heightmap min/max, and displacement textures
|
||||
// TODO Alter limits with heightmap min/max
|
||||
|
||||
double max_displacement = getMaximalDisplacement();
|
||||
_min_height -= max_displacement;
|
||||
_max_height += max_displacement;
|
||||
|
||||
has_painting = height_map->hasPainting();
|
||||
}
|
||||
|
@ -60,7 +83,7 @@ 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(0.1, to_double(x), to_double(z));
|
||||
h = height_noise->getGenerator()->get2d(1.0, to_double(x), to_double(z));
|
||||
}
|
||||
|
||||
return h;
|
||||
|
@ -70,7 +93,7 @@ double TerrainDefinition::getInterpolatedHeight(double x, double z, bool with_pa
|
|||
double h;
|
||||
|
||||
if (!with_painting || !has_painting || !height_map->getInterpolatedValue(x, z, &h)) {
|
||||
h = height_noise->getGenerator()->get2d(0.1, x, z);
|
||||
h = height_noise->getGenerator()->get2d(1.0, x, z);
|
||||
}
|
||||
|
||||
return (water_offset ? (h + getWaterOffset()) : h);
|
||||
|
@ -81,6 +104,17 @@ double TerrainDefinition::getWaterOffset() const {
|
|||
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;
|
||||
|
||||
|
@ -96,11 +130,55 @@ unsigned long TerrainDefinition::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;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,16 +25,26 @@ class DEFINITIONSHARED_EXPORT TerrainDefinition : public DefinitionNode {
|
|||
virtual void copy(DefinitionNode *destination) const override;
|
||||
virtual void validate() override;
|
||||
|
||||
inline MaterialNode *propDefaultMaterial() const {
|
||||
return default_material;
|
||||
}
|
||||
inline FloatNode *propWaterHeight() const {
|
||||
return water_height;
|
||||
}
|
||||
inline NoiseNode *propHeightNoise() const {
|
||||
return height_noise;
|
||||
}
|
||||
inline Layers *propDisplacements() const {
|
||||
return displacements;
|
||||
}
|
||||
inline Layers *propMaterials() const {
|
||||
return materials;
|
||||
}
|
||||
|
||||
double getGridHeight(int x, int z, bool with_painting);
|
||||
double getInterpolatedHeight(double x, double z, bool with_painting, bool water_offset = true);
|
||||
double getWaterOffset() const;
|
||||
double getMaximalDisplacement();
|
||||
unsigned long getMemoryStats();
|
||||
HeightInfo getHeightInfo();
|
||||
|
||||
|
@ -52,8 +62,11 @@ class DEFINITIONSHARED_EXPORT TerrainDefinition : public DefinitionNode {
|
|||
double _max_height;
|
||||
|
||||
private:
|
||||
MaterialNode *default_material;
|
||||
FloatNode *water_height;
|
||||
NoiseNode *height_noise;
|
||||
Layers *displacements;
|
||||
Layers *materials;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,29 +9,24 @@
|
|||
#include "Color.h"
|
||||
#include "FractalNoise.h"
|
||||
#include "NoiseNode.h"
|
||||
#include "MaterialNode.h"
|
||||
|
||||
TextureLayerDefinition::TextureLayerDefinition(DefinitionNode *parent, const string &name)
|
||||
: DefinitionNode(parent, name, "texturelayer") {
|
||||
terrain_zone = new Zone;
|
||||
material = new SurfaceMaterial;
|
||||
material = new MaterialNode(this, "material");
|
||||
|
||||
displacement_noise = new NoiseNode(this, "displacement");
|
||||
displacement_noise->setConfig(0.0);
|
||||
|
||||
detail_noise = new NoiseNode(this, "detail");
|
||||
detail_noise->setConfig(0.01);
|
||||
}
|
||||
|
||||
TextureLayerDefinition::~TextureLayerDefinition() {
|
||||
delete terrain_zone;
|
||||
delete material;
|
||||
}
|
||||
|
||||
void TextureLayerDefinition::validate() {
|
||||
DefinitionNode::validate();
|
||||
|
||||
material->validate();
|
||||
|
||||
// Update zone height range
|
||||
if (auto scenery = getScenery()) {
|
||||
TerrainDefinition *terrain = scenery->getTerrain();
|
||||
|
@ -45,8 +40,6 @@ void TextureLayerDefinition::copy(DefinitionNode *destination) const {
|
|||
|
||||
if (auto tex_destination = dynamic_cast<TextureLayerDefinition *>(destination)) {
|
||||
terrain_zone->copy(tex_destination->terrain_zone);
|
||||
|
||||
*tex_destination->material = *material;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,68 +47,12 @@ void TextureLayerDefinition::save(PackStream *stream) const {
|
|||
DefinitionNode::save(stream);
|
||||
|
||||
terrain_zone->save(stream);
|
||||
material->save(stream);
|
||||
}
|
||||
|
||||
void TextureLayerDefinition::load(PackStream *stream) {
|
||||
DefinitionNode::load(stream);
|
||||
|
||||
terrain_zone->load(stream);
|
||||
material->load(stream);
|
||||
}
|
||||
|
||||
void TextureLayerDefinition::applyPreset(TextureLayerPreset preset, RandomGenerator &random) {
|
||||
displacement_noise->randomize(random);
|
||||
detail_noise->randomize(random);
|
||||
|
||||
terrain_zone->clear();
|
||||
|
||||
switch (preset) {
|
||||
case TEXTURES_LAYER_PRESET_MUD:
|
||||
displacement_noise->setConfig(0.05, 0.1, 0.3);
|
||||
detail_noise->setConfig(0.01, 0.03);
|
||||
material->setColor(0.015, 0.014, 0.014, 1.0);
|
||||
material->reflection = 0.003;
|
||||
material->shininess = 4.0;
|
||||
break;
|
||||
case TEXTURES_LAYER_PRESET_ROCK:
|
||||
terrain_zone->addHeightRangeQuick(1.0, 0.6, 0.7, 0.87, 0.95);
|
||||
displacement_noise->setConfig(4.0, 0.15, 0.5, 0.8);
|
||||
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.7, 0.9);
|
||||
terrain_zone->addSlopeRangeQuick(1.0, 0.0, 0.0, 0.05, 0.4);
|
||||
displacement_noise->setConfig(2.0, 0.05);
|
||||
detail_noise->setConfig(0.01, 0.1);
|
||||
material->setColor(0.12, 0.19, 0.035, 1.0);
|
||||
material->reflection = 0.001;
|
||||
material->shininess = 4.0;
|
||||
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.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);
|
||||
material->reflection = 0.008;
|
||||
material->shininess = 1.0;
|
||||
break;
|
||||
case TEXTURES_LAYER_PRESET_SNOW:
|
||||
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);
|
||||
material->reflection = 0.02;
|
||||
material->shininess = 0.6;
|
||||
break;
|
||||
}
|
||||
|
||||
validate();
|
||||
}
|
||||
|
||||
bool TextureLayerDefinition::hasDisplacement() const {
|
||||
|
|
|
@ -9,16 +9,6 @@ namespace paysages {
|
|||
namespace definition {
|
||||
|
||||
class DEFINITIONSHARED_EXPORT TextureLayerDefinition : public DefinitionNode {
|
||||
public:
|
||||
typedef enum { TEXTURES_MERGE_FADE, TEXTURES_MERGE_DISSOLVE, TEXTURES_MERGE_DISPLACEMENT_VALUE } TextureMergeMode;
|
||||
typedef enum {
|
||||
TEXTURES_LAYER_PRESET_MUD,
|
||||
TEXTURES_LAYER_PRESET_ROCK,
|
||||
TEXTURES_LAYER_PRESET_GRASS,
|
||||
TEXTURES_LAYER_PRESET_SAND,
|
||||
TEXTURES_LAYER_PRESET_SNOW
|
||||
} TextureLayerPreset;
|
||||
|
||||
public:
|
||||
TextureLayerDefinition(DefinitionNode *parent, const string &name);
|
||||
virtual ~TextureLayerDefinition();
|
||||
|
@ -29,13 +19,14 @@ class DEFINITIONSHARED_EXPORT TextureLayerDefinition : public DefinitionNode {
|
|||
virtual void copy(DefinitionNode *destination) const override;
|
||||
virtual void validate() override;
|
||||
|
||||
void applyPreset(TextureLayerPreset preset, RandomGenerator &random = RandomGeneratorDefault);
|
||||
|
||||
inline Zone *propTerrainZone() const {
|
||||
return terrain_zone;
|
||||
}
|
||||
inline NoiseNode *propDisplacementNoise() const {
|
||||
return displacement_noise;
|
||||
}
|
||||
inline NoiseNode *propDetailNoise() const {
|
||||
return detail_noise;
|
||||
inline MaterialNode *propMaterial() const {
|
||||
return material;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,13 +39,10 @@ class DEFINITIONSHARED_EXPORT TextureLayerDefinition : public DefinitionNode {
|
|||
*/
|
||||
double getMaximalDisplacement() const;
|
||||
|
||||
public:
|
||||
Zone *terrain_zone;
|
||||
SurfaceMaterial *material;
|
||||
|
||||
private:
|
||||
Zone *terrain_zone;
|
||||
NoiseNode *displacement_noise;
|
||||
NoiseNode *detail_noise;
|
||||
MaterialNode *material;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
#include "TexturesDefinition.h"
|
||||
|
||||
#include "TextureLayerDefinition.h"
|
||||
|
||||
static DefinitionNode *_layer_constructor(Layers *parent, const string &name) {
|
||||
return new TextureLayerDefinition(parent, name);
|
||||
}
|
||||
|
||||
TexturesDefinition::TexturesDefinition(DefinitionNode *parent) : Layers(parent, "textures", _layer_constructor) {
|
||||
}
|
||||
|
||||
void TexturesDefinition::applyPreset(TexturesPreset preset, RandomGenerator &random) {
|
||||
TextureLayerDefinition layer(NULL, "temp");
|
||||
clear();
|
||||
|
||||
layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_MUD, random);
|
||||
layer.setName("Mud");
|
||||
addLayer(layer);
|
||||
|
||||
if (preset == TEXTURES_PRESET_FULL) {
|
||||
layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK, random);
|
||||
layer.setName("Ground");
|
||||
addLayer(layer);
|
||||
|
||||
layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_GRASS, random);
|
||||
layer.setName("Grass");
|
||||
addLayer(layer);
|
||||
|
||||
layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SAND, random);
|
||||
layer.setName("Sand");
|
||||
addLayer(layer);
|
||||
|
||||
layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SNOW, random);
|
||||
layer.setName("Snow");
|
||||
addLayer(layer);
|
||||
} else if (preset == TEXTURES_PRESET_IRELAND) {
|
||||
layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK, random);
|
||||
layer.setName("Ground");
|
||||
addLayer(layer);
|
||||
|
||||
layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_GRASS, random);
|
||||
layer.setName("Grass");
|
||||
addLayer(layer);
|
||||
} else if (preset == TEXTURES_PRESET_ALPS) {
|
||||
layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK, random);
|
||||
layer.setName("Ground");
|
||||
addLayer(layer);
|
||||
|
||||
layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SNOW, random);
|
||||
layer.setName("Snow");
|
||||
addLayer(layer);
|
||||
}
|
||||
}
|
||||
|
||||
double TexturesDefinition::getMaximalDisplacement() {
|
||||
double result = 0.0;
|
||||
int n = getLayerCount();
|
||||
for (int i = 0; i < n; i++) {
|
||||
result += getTextureLayer(i)->getMaximalDisplacement();
|
||||
}
|
||||
return result;
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
#ifndef TEXTURESDEFINITION_H
|
||||
#define TEXTURESDEFINITION_H
|
||||
|
||||
#include "definition_global.h"
|
||||
|
||||
#include "Layers.h"
|
||||
|
||||
namespace paysages {
|
||||
namespace definition {
|
||||
|
||||
class DEFINITIONSHARED_EXPORT TexturesDefinition : public Layers {
|
||||
public:
|
||||
TexturesDefinition(DefinitionNode *parent);
|
||||
|
||||
inline TextureLayerDefinition *getTextureLayer(int position) const {
|
||||
return (TextureLayerDefinition *)getLayer(position);
|
||||
}
|
||||
|
||||
typedef enum { TEXTURES_PRESET_FULL, TEXTURES_PRESET_IRELAND, TEXTURES_PRESET_ALPS } TexturesPreset;
|
||||
void applyPreset(TexturesPreset preset, RandomGenerator &random = RandomGeneratorDefault);
|
||||
|
||||
double getMaximalDisplacement();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TEXTURESDEFINITION_H
|
|
@ -35,7 +35,6 @@ class CloudLayerDefinition;
|
|||
class AtmosphereDefinition;
|
||||
class CelestialBodyDefinition;
|
||||
class GodRaysDefinition;
|
||||
class TexturesDefinition;
|
||||
class TextureLayerDefinition;
|
||||
class TerrainDefinition;
|
||||
class TerrainHeightMap;
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include "AtmosphereDefinition.h"
|
||||
#include "AtmosphereRenderer.h"
|
||||
#include "AtmosphereResult.h"
|
||||
#include "TexturesDefinition.h"
|
||||
#include "GodRaysDefinition.h"
|
||||
#include "TextureLayerDefinition.h"
|
||||
#include "WaterDefinition.h"
|
||||
|
@ -37,6 +36,7 @@
|
|||
#include "RandomGenerator.h"
|
||||
#include "NoiseFunctionSimplex.h"
|
||||
#include "Zone.h"
|
||||
#include "MaterialNode.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
|
@ -111,11 +111,11 @@ static void testGroundShadowQuality() {
|
|||
scenery.getWater()->transparency = 0.0;
|
||||
scenery.getAtmosphere()->applyPreset(AtmosphereDefinition::ATMOSPHERE_PRESET_CLEAR_SUNSET, random);
|
||||
scenery.getAtmosphere()->setDayTime(16, 45);
|
||||
scenery.getTextures()->clear();
|
||||
/*scenery.getTextures()->clear();
|
||||
TextureLayerDefinition texture(NULL, "test");
|
||||
texture.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK);
|
||||
texture.terrain_zone->clear();
|
||||
scenery.getTextures()->addLayer(texture);
|
||||
texture.propTerrainZone()->clear();
|
||||
scenery.getTextures()->addLayer(texture);*/
|
||||
scenery.getCamera()->setLocation(Vector3(10.0, 10.0, -10.0));
|
||||
scenery.getCamera()->setTarget(VECTOR_ZERO);
|
||||
|
||||
|
@ -398,22 +398,22 @@ static void testTextures() {
|
|||
|
||||
// TODO Customize terrain function
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
/*for (int i = 0; i < 5; i++) {
|
||||
TextureLayerDefinition layer(NULL, "test");
|
||||
layer.applyPreset(static_cast<TextureLayerDefinition::TextureLayerPreset>(i));
|
||||
layer.terrain_zone->clear();
|
||||
layer.propTerrainZone()->clear();
|
||||
scenery.getTextures()->clear();
|
||||
scenery.getTextures()->addLayer(layer);
|
||||
startTestRender(&renderer, "texture", i * 2);
|
||||
|
||||
layer.propDetailNoise()->setConfig(0.0);
|
||||
layer.propMaterial()->propBump()->setConfig(0.0);
|
||||
scenery.getTextures()->clear();
|
||||
scenery.getTextures()->addLayer(layer);
|
||||
startTestRender(&renderer, "texture", i * 2 + 1);
|
||||
}
|
||||
}*/
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
scenery.getTextures()->applyPreset(static_cast<TexturesDefinition::TexturesPreset>(i));
|
||||
/*scenery.getTextures()->applyPreset(static_cast<TexturesDefinition::TexturesPreset>(i));*/
|
||||
startTestRender(&renderer, "texture_comp", i);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include "LightComponent.h"
|
||||
#include "Color.h"
|
||||
#include "SurfaceMaterial.h"
|
||||
#include "MaterialNode.h"
|
||||
#include "FractalNoise.h"
|
||||
|
||||
LightStatus::LightStatus(LightingManager *manager, const Vector3 &location, const Vector3 &eye, bool filtered) {
|
||||
this->safety_offset = -0.0000001;
|
||||
|
@ -33,7 +35,7 @@ void LightStatus::pushComponent(LightComponent component) {
|
|||
}
|
||||
}
|
||||
|
||||
Color LightStatus::apply(const Vector3 &normal, const SurfaceMaterial &material) {
|
||||
Color LightStatus::apply(const Vector3 &normal, const SurfaceMaterial &material) const {
|
||||
Color final(0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
for (auto component : components) {
|
||||
|
@ -44,6 +46,44 @@ Color LightStatus::apply(const Vector3 &normal, const SurfaceMaterial &material)
|
|||
return final;
|
||||
}
|
||||
|
||||
Color LightStatus::apply(const Vector3 &normal, const MaterialNode *material, double precision) const {
|
||||
Vector3 final_normal = normal;
|
||||
|
||||
if (material->hasBump()) {
|
||||
// Alter normal vector using bump noise
|
||||
Vector3 dx, dy;
|
||||
Vector3 pivot;
|
||||
if (normal.y > 0.95) {
|
||||
pivot = VECTOR_NORTH;
|
||||
} else {
|
||||
pivot = VECTOR_UP;
|
||||
}
|
||||
dx = normal.crossProduct(pivot).normalize();
|
||||
dy = normal.crossProduct(dx).normalize();
|
||||
|
||||
Vector3 center, east, south;
|
||||
auto detail_noise = material->getBumpGenerator();
|
||||
double detail = precision;
|
||||
double offset = precision * 0.1;
|
||||
|
||||
center = location.add(normal.scale(detail_noise->getTriplanar(detail, location, normal)));
|
||||
|
||||
east = location.add(dx.scale(offset));
|
||||
east = east.add(normal.scale(detail_noise->getTriplanar(detail, east, normal)));
|
||||
|
||||
south = location.add(dy.scale(offset));
|
||||
south = south.add(normal.scale(detail_noise->getTriplanar(detail, south, normal)));
|
||||
|
||||
final_normal = center.getNormal3(south, east);
|
||||
|
||||
if (final_normal.dotProduct(normal) < 0.0) {
|
||||
final_normal = final_normal.scale(-1.0);
|
||||
}
|
||||
}
|
||||
|
||||
return apply(final_normal, material->getSurfaceMaterial());
|
||||
}
|
||||
|
||||
Color LightStatus::getSum() const {
|
||||
Color final = COLOR_BLACK;
|
||||
|
||||
|
|
|
@ -25,7 +25,15 @@ class SOFTWARESHARED_EXPORT LightStatus {
|
|||
|
||||
void pushComponent(LightComponent component);
|
||||
|
||||
Color apply(const Vector3 &normal, const SurfaceMaterial &material);
|
||||
/**
|
||||
* Apply the lighting to a flat surface.
|
||||
*/
|
||||
Color apply(const Vector3 &normal, const SurfaceMaterial &material) const;
|
||||
|
||||
/**
|
||||
* Apply the lighting to a bumpy surface.
|
||||
*/
|
||||
Color apply(const Vector3 &normal, const MaterialNode *material, double precision) const;
|
||||
|
||||
/**
|
||||
* Return the sum of all received lights.
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "CloudsRenderer.h"
|
||||
#include "CloudsDefinition.h"
|
||||
#include "TerrainRenderer.h"
|
||||
#include "TexturesRenderer.h"
|
||||
#include "VegetationRenderer.h"
|
||||
#include "WaterRenderer.h"
|
||||
#include "SkyRasterizer.h"
|
||||
|
@ -33,7 +32,6 @@ SoftwareRenderer::SoftwareRenderer(Scenery *scenery) : scenery(scenery) {
|
|||
atmosphere_renderer = new BaseAtmosphereRenderer(this);
|
||||
clouds_renderer = new CloudsRenderer(this);
|
||||
terrain_renderer = new TerrainRenderer(this);
|
||||
textures_renderer = new TexturesRenderer();
|
||||
vegetation_renderer = new VegetationRenderer(this);
|
||||
water_renderer = new WaterRenderer(this);
|
||||
|
||||
|
@ -71,7 +69,6 @@ SoftwareRenderer::~SoftwareRenderer() {
|
|||
delete atmosphere_renderer;
|
||||
delete clouds_renderer;
|
||||
delete terrain_renderer;
|
||||
delete textures_renderer;
|
||||
delete vegetation_renderer;
|
||||
delete water_renderer;
|
||||
}
|
||||
|
@ -105,7 +102,6 @@ void SoftwareRenderer::prepare() {
|
|||
|
||||
void SoftwareRenderer::setQuality(double quality) {
|
||||
terrain_renderer->setQuality(quality);
|
||||
textures_renderer->setQuality(quality);
|
||||
clouds_renderer->setQuality(quality);
|
||||
godrays->setQuality(quality);
|
||||
|
||||
|
|
|
@ -55,9 +55,6 @@ class SOFTWARESHARED_EXPORT SoftwareRenderer {
|
|||
inline TerrainRenderer *getTerrainRenderer() const {
|
||||
return terrain_renderer;
|
||||
}
|
||||
inline TexturesRenderer *getTexturesRenderer() const {
|
||||
return textures_renderer;
|
||||
}
|
||||
inline WaterRenderer *getWaterRenderer() const {
|
||||
return water_renderer;
|
||||
}
|
||||
|
@ -102,7 +99,6 @@ class SOFTWARESHARED_EXPORT SoftwareRenderer {
|
|||
BaseAtmosphereRenderer *atmosphere_renderer;
|
||||
CloudsRenderer *clouds_renderer;
|
||||
TerrainRenderer *terrain_renderer;
|
||||
TexturesRenderer *textures_renderer;
|
||||
WaterRenderer *water_renderer;
|
||||
NightSky *nightsky_renderer;
|
||||
MoonRenderer *moon_renderer;
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include "CameraDefinition.h"
|
||||
#include "TerrainRenderer.h"
|
||||
#include "WaterRenderer.h"
|
||||
#include "TexturesRenderer.h"
|
||||
#include "Scenery.h"
|
||||
#include "CanvasPortion.h"
|
||||
#include "CanvasFragment.h"
|
||||
|
@ -100,8 +99,7 @@ void TerrainRasterizer::getChunk(SoftwareRenderer *renderer, TerrainRasterizer::
|
|||
chunk->point_ne.y += yoffset;
|
||||
}
|
||||
|
||||
double displacement_power =
|
||||
renderer->getTexturesRenderer()->getMaximalDisplacement(renderer->getScenery()->getTextures());
|
||||
double displacement_power = renderer->getScenery()->getTerrain()->getMaximalDisplacement();
|
||||
|
||||
BoundingBox box;
|
||||
if (displacement_power > 0.0) {
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
#include "TerrainRayWalker.h"
|
||||
|
||||
#include <cmath>
|
||||
#include "Logs.h"
|
||||
#include "SoftwareRenderer.h"
|
||||
#include "Scenery.h"
|
||||
#include "TerrainDefinition.h"
|
||||
#include "TexturesDefinition.h"
|
||||
#include "TerrainRenderer.h"
|
||||
#include "TexturesRenderer.h"
|
||||
#include "Matrix4.h"
|
||||
|
||||
TerrainRayWalker::TerrainRayWalker(SoftwareRenderer *renderer) : renderer(renderer) {
|
||||
|
@ -24,19 +23,18 @@ void TerrainRayWalker::setQuality(double displacement_safety, double minimal_ste
|
|||
}
|
||||
|
||||
void TerrainRayWalker::setQuality(double factor) {
|
||||
setQuality(0.2 + 0.8 * factor, 1.0 / (factor * factor * 30.0 + 1.0), 50.0 / (factor * 10.0 + 1.0),
|
||||
setQuality(0.2 + 1.8 * factor, 1.0 / (factor * factor * 30.0 + 1.0), 50.0 / (factor * 10.0 + 1.0),
|
||||
1.0 / (factor * 10.0 + 1.0), 10.0 + factor * 200.0, factor * factor * 100.0);
|
||||
}
|
||||
|
||||
void TerrainRayWalker::update() {
|
||||
TerrainDefinition *terrain = renderer->getScenery()->getTerrain();
|
||||
HeightInfo info = terrain->getHeightInfo();
|
||||
auto definition = renderer->getScenery()->getTerrain();
|
||||
|
||||
TexturesDefinition *textures = renderer->getScenery()->getTextures();
|
||||
displacement_base = textures->getMaximalDisplacement();
|
||||
HeightInfo info = definition->getHeightInfo();
|
||||
ymin = info.min_height;
|
||||
ymax = info.max_height;
|
||||
|
||||
ymin = info.min_height - displacement_base;
|
||||
ymax = info.max_height + displacement_base;
|
||||
displacement_base = definition->getMaximalDisplacement();
|
||||
}
|
||||
|
||||
static inline Vector3 _getShiftAxis(const Vector3 &direction) {
|
||||
|
@ -51,8 +49,6 @@ static inline Vector3 _getShiftAxis(const Vector3 &direction) {
|
|||
bool TerrainRayWalker::startWalking(const Vector3 &start, Vector3 direction, double escape_angle,
|
||||
TerrainHitResult &result) {
|
||||
auto terrain_renderer = renderer->getTerrainRenderer();
|
||||
auto textures_renderer = renderer->getTexturesRenderer();
|
||||
auto textures_definition = renderer->getScenery()->getTextures();
|
||||
TerrainRenderer::TerrainResult terrain_result;
|
||||
Vector3 cursor, displaced;
|
||||
double diff;
|
||||
|
@ -86,8 +82,7 @@ bool TerrainRayWalker::startWalking(const Vector3 &start, Vector3 direction, dou
|
|||
|
||||
// If we are close enough to the terrain, apply displacement
|
||||
else if (diff < displacement_base * displacement_safety) {
|
||||
displaced =
|
||||
textures_renderer->displaceTerrain(textures_definition, terrain_result.location, terrain_result.normal);
|
||||
displaced = terrain_renderer->displaceResult(terrain_result);
|
||||
diff = cursor.y - displaced.y;
|
||||
hit = diff < 0.0;
|
||||
}
|
||||
|
|
|
@ -3,12 +3,18 @@
|
|||
#include <algorithm>
|
||||
#include "SoftwareRenderer.h"
|
||||
#include "Scenery.h"
|
||||
#include "MaterialNode.h"
|
||||
#include "TerrainDefinition.h"
|
||||
#include "TexturesRenderer.h"
|
||||
#include "TexturesDefinition.h"
|
||||
#include "TextureLayerDefinition.h"
|
||||
#include "LightComponent.h"
|
||||
#include "TerrainRayWalker.h"
|
||||
#include "RayCastingResult.h"
|
||||
#include "Layers.h"
|
||||
#include "NoiseNode.h"
|
||||
#include "FractalNoise.h"
|
||||
#include "LightingManager.h"
|
||||
#include "LightStatus.h"
|
||||
#include "Zone.h"
|
||||
|
||||
TerrainRenderer::TerrainRenderer(SoftwareRenderer *parent) : parent(parent) {
|
||||
walker_ray = new TerrainRayWalker(parent);
|
||||
|
@ -37,11 +43,11 @@ void TerrainRenderer::setQuality(double factor) {
|
|||
setQuality(factor > 0.6, factor, factor * 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) const {
|
||||
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) const {
|
||||
TerrainResult result;
|
||||
double offset = 0.001;
|
||||
|
||||
|
@ -80,57 +86,84 @@ TerrainRenderer::TerrainResult TerrainRenderer::getResult(double x, double z, bo
|
|||
return result;
|
||||
}
|
||||
|
||||
Vector3 TerrainRenderer::getDisplaced(double x, double z, bool with_painting) {
|
||||
auto terrain = getResult(x, z, with_painting);
|
||||
auto textures = parent->getScenery()->getTextures();
|
||||
return parent->getTexturesRenderer()->displaceTerrain(textures, terrain.location, terrain.normal);
|
||||
}
|
||||
Vector3 TerrainRenderer::displaceResult(const TerrainRenderer::TerrainResult &result) const {
|
||||
const Vector3 &location = result.location;
|
||||
const Vector3 &normal = result.normal;
|
||||
auto displacements = parent->getScenery()->getTerrain()->propDisplacements();
|
||||
double offset = 0.0;
|
||||
|
||||
static inline pair<vector<double>, vector<Vector3>> _getTexturesInfo(TerrainRenderer *terrain_renderer,
|
||||
TexturesRenderer *textures_renderer, double x,
|
||||
double z,
|
||||
TexturesDefinition *textures_definition) {
|
||||
auto terrain = terrain_renderer->getResult(x, z, true);
|
||||
auto presence = textures_renderer->getLayersPresence(textures_definition, terrain.location, terrain.normal);
|
||||
auto displaced =
|
||||
textures_renderer->getLayersDisplacement(textures_definition, terrain.location, terrain.normal, presence);
|
||||
return pair<vector<double>, vector<Vector3>>(presence, displaced);
|
||||
}
|
||||
|
||||
Color TerrainRenderer::getFinalColor(double x, double z, double precision) {
|
||||
auto textures_renderer = parent->getTexturesRenderer();
|
||||
auto textures_definition = parent->getScenery()->getTextures();
|
||||
|
||||
if (textures_definition->getLayerCount() == 0) {
|
||||
return COLOR_BLACK;
|
||||
} else {
|
||||
auto current = _getTexturesInfo(this, textures_renderer, x, z, textures_definition);
|
||||
auto top_location = current.second.back();
|
||||
|
||||
vector<Vector3> normal;
|
||||
int i = 0;
|
||||
// TODO Use getNormal5 on high-quality renders
|
||||
double offset = 0.0001;
|
||||
auto east = _getTexturesInfo(this, textures_renderer, x + offset, z, textures_definition);
|
||||
auto south = _getTexturesInfo(this, textures_renderer, x, z + offset, textures_definition);
|
||||
for (auto layer_presence : current.first) {
|
||||
if (layer_presence > 0.0) {
|
||||
normal.push_back(current.second[i].getNormal3(south.second[i], east.second[i]));
|
||||
} else {
|
||||
normal.push_back(VECTOR_ZERO);
|
||||
int n = displacements->getLayerCount();
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (auto displacement = dynamic_cast<TextureLayerDefinition *>(displacements->getLayer(i))) {
|
||||
double presence = displacement->propTerrainZone()->getValue(location, normal);
|
||||
if (presence > 0.0) {
|
||||
auto noise = displacement->propDisplacementNoise()->getGenerator();
|
||||
offset += noise->getTriplanar(0.01, location, normal) * presence;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
auto color =
|
||||
textures_renderer->getFinalComposition(textures_definition, parent->getLightingManager(), current.first,
|
||||
current.second, normal, precision, parent->getCameraLocation());
|
||||
|
||||
return parent->applyMediumTraversal(top_location, color);
|
||||
}
|
||||
|
||||
return location.add(normal.scale(offset));
|
||||
}
|
||||
|
||||
RayCastingResult TerrainRenderer::castRay(const Vector3 &start, const Vector3 &direction) {
|
||||
Vector3 TerrainRenderer::getDisplaced(double x, double z, bool with_painting) const {
|
||||
return displaceResult(getResult(x, z, with_painting));
|
||||
}
|
||||
|
||||
Color TerrainRenderer::getFinalColor(double x, double z, double precision) const {
|
||||
auto definition = parent->getScenery()->getTerrain();
|
||||
|
||||
// Get displaced location and normal
|
||||
double offset = 0.0001;
|
||||
Vector3 normal;
|
||||
TerrainResult locresult = getResult(x, z, true);
|
||||
Vector3 location = displaceResult(locresult);
|
||||
Vector3 east = getDisplaced(x + offset, z, true);
|
||||
Vector3 south = getDisplaced(x, z + offset, true);
|
||||
if (quad_normals) {
|
||||
Vector3 west = getDisplaced(x - offset, z, true);
|
||||
Vector3 north = getDisplaced(x, z - offset, true);
|
||||
normal = location.getNormal5(south, north, east, west);
|
||||
} else {
|
||||
normal = location.getNormal3(south, east);
|
||||
}
|
||||
if (normal.dotProduct(locresult.normal) < 0.0) {
|
||||
normal = normal.scale(-1.0);
|
||||
}
|
||||
|
||||
// Prepare the lighting status
|
||||
auto lighting = parent->getLightingManager();
|
||||
LightStatus status(lighting, location, parent->getCameraLocation());
|
||||
lighting->fillStatus(status, location);
|
||||
|
||||
// Apply materials
|
||||
auto materials = definition->propMaterials();
|
||||
unsigned int n = materials->getLayerCount();
|
||||
Color result = COLOR_BLACK;
|
||||
if (n == 0) {
|
||||
addMaterial(&result, definition->propDefaultMaterial(), 1.0, normal, precision, status);
|
||||
} else {
|
||||
for (unsigned int i = 0; i < n; i++) {
|
||||
if (auto material = dynamic_cast<TextureLayerDefinition *>(definition->propMaterials()->getLayer(i))) {
|
||||
double presence = material->propTerrainZone()->getValue(location, normal);
|
||||
if (presence > 0.0) {
|
||||
addMaterial(&result, material->propMaterial(), presence, normal, precision, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return parent->applyMediumTraversal(location, result);
|
||||
}
|
||||
|
||||
void TerrainRenderer::addMaterial(Color *base, const MaterialNode *node, double presence, const Vector3 &normal,
|
||||
double precision, const LightStatus &lighting) const {
|
||||
Color col = lighting.apply(normal, node, precision);
|
||||
col.a = presence;
|
||||
base->mask(col);
|
||||
}
|
||||
|
||||
RayCastingResult TerrainRenderer::castRay(const Vector3 &start, const Vector3 &direction) const {
|
||||
RayCastingResult result;
|
||||
TerrainRayWalker::TerrainHitResult walk_result;
|
||||
if (walker_ray->startWalking(start, direction.normalize(), 0.0, walk_result)) {
|
||||
|
|
|
@ -26,10 +26,11 @@ class SOFTWARESHARED_EXPORT TerrainRenderer : public LightFilter {
|
|||
void setQuality(bool quad_normals, double ray_precision, double shadow_precision);
|
||||
void setQuality(double factor);
|
||||
|
||||
virtual RayCastingResult castRay(const Vector3 &start, const Vector3 &direction);
|
||||
virtual double getHeight(double x, double z, bool with_painting, bool water_offset = true);
|
||||
virtual TerrainResult getResult(double x, double z, bool with_painting);
|
||||
Vector3 getDisplaced(double x, double z, bool with_painting);
|
||||
virtual RayCastingResult castRay(const Vector3 &start, const Vector3 &direction) const;
|
||||
virtual double getHeight(double x, double z, bool with_painting, bool water_offset = true) const;
|
||||
virtual TerrainResult getResult(double x, double z, bool with_painting) const;
|
||||
virtual Vector3 displaceResult(const TerrainResult &result) const;
|
||||
Vector3 getDisplaced(double x, double z, bool with_painting) const;
|
||||
virtual bool applyLightFilter(LightComponent &light, const Vector3 &at) override;
|
||||
|
||||
/**
|
||||
|
@ -42,7 +43,13 @@ class SOFTWARESHARED_EXPORT TerrainRenderer : public LightFilter {
|
|||
*
|
||||
* Textures will be applied (with displacement and detail), and medium traversal will be performed at the location.
|
||||
*/
|
||||
virtual Color getFinalColor(double x, double z, double precision);
|
||||
virtual Color getFinalColor(double x, double z, double precision) const;
|
||||
|
||||
/**
|
||||
* Add a material component to a composited result.
|
||||
*/
|
||||
void addMaterial(Color *base, const MaterialNode *node, double presence, const Vector3 &normal, double precision,
|
||||
const LightStatus &lighting) const;
|
||||
|
||||
private:
|
||||
SoftwareRenderer *parent;
|
||||
|
|
|
@ -1,192 +0,0 @@
|
|||
#include "TexturesRenderer.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include "Scenery.h"
|
||||
#include "SoftwareRenderer.h"
|
||||
#include "TextureLayerDefinition.h"
|
||||
#include "TexturesDefinition.h"
|
||||
#include "Zone.h"
|
||||
#include "LightingManager.h"
|
||||
#include "LightStatus.h"
|
||||
#include "NoiseNode.h"
|
||||
#include "FractalNoise.h"
|
||||
#include "NoiseGenerator.h"
|
||||
|
||||
TexturesRenderer::TexturesRenderer() {
|
||||
setQualityFactor(0.5);
|
||||
}
|
||||
|
||||
TexturesRenderer::~TexturesRenderer() {
|
||||
}
|
||||
|
||||
void TexturesRenderer::setQuality(bool normal5) {
|
||||
quality_normal5 = normal5;
|
||||
}
|
||||
|
||||
void TexturesRenderer::setQualityFactor(double factor) {
|
||||
setQuality(factor > 0.6);
|
||||
}
|
||||
|
||||
double TexturesRenderer::getMaximalDisplacement(TexturesDefinition *textures) const {
|
||||
int i, n;
|
||||
double disp = 0.0;
|
||||
n = textures->getLayerCount();
|
||||
for (i = 0; i < n; i++) {
|
||||
TextureLayerDefinition *layer = textures->getTextureLayer(i);
|
||||
double layer_disp = layer->getMaximalDisplacement();
|
||||
if (layer_disp > 0.0) {
|
||||
disp += layer_disp;
|
||||
}
|
||||
}
|
||||
return disp;
|
||||
}
|
||||
|
||||
static Vector3 _getDetailNormal(Vector3 base_location, Vector3 base_normal, TextureLayerDefinition *layer,
|
||||
double precision, bool normal5) {
|
||||
Vector3 result;
|
||||
|
||||
/* Find guiding vectors in the appoximated local plane */
|
||||
Vector3 dx, dy;
|
||||
Vector3 pivot;
|
||||
if (base_normal.y > 0.95) {
|
||||
pivot = VECTOR_NORTH;
|
||||
} else {
|
||||
pivot = VECTOR_UP;
|
||||
}
|
||||
dx = base_normal.crossProduct(pivot).normalize();
|
||||
dy = base_normal.crossProduct(dx).normalize();
|
||||
|
||||
/* Apply detail noise locally */
|
||||
Vector3 center, north, east, south, west;
|
||||
auto detail_noise = layer->propDetailNoise()->getGenerator();
|
||||
double detail = precision;
|
||||
double offset = precision * 0.1;
|
||||
|
||||
center = base_location.add(base_normal.scale(detail_noise->getTriplanar(detail, base_location, base_normal)));
|
||||
|
||||
east = base_location.add(dx.scale(offset));
|
||||
east = east.add(base_normal.scale(detail_noise->getTriplanar(detail, east, base_normal)));
|
||||
|
||||
south = base_location.add(dy.scale(offset));
|
||||
south = south.add(base_normal.scale(detail_noise->getTriplanar(detail, south, base_normal)));
|
||||
|
||||
if (normal5) {
|
||||
west = base_location.add(dx.scale(-offset));
|
||||
west = west.add(base_normal.scale(detail_noise->getTriplanar(detail, west, base_normal)));
|
||||
|
||||
north = base_location.add(dy.scale(-offset));
|
||||
north = north.add(base_normal.scale(detail_noise->getTriplanar(detail, north, base_normal)));
|
||||
|
||||
result = center.getNormal5(south, north, east, west);
|
||||
} else {
|
||||
result = center.getNormal3(south, east);
|
||||
}
|
||||
|
||||
if (result.dotProduct(base_normal) < 0.0) {
|
||||
result = result.scale(-1.0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline double _getLayerPresence(TextureLayerDefinition *layer, const Vector3 &location, const Vector3 &normal) {
|
||||
return layer->terrain_zone->getValue(location, normal);
|
||||
}
|
||||
|
||||
static inline double _getLayerDisplacement(TextureLayerDefinition *layer, const Vector3 &location,
|
||||
const Vector3 &normal, double presence) {
|
||||
auto noise = layer->propDisplacementNoise()->getGenerator();
|
||||
return noise->getTriplanar(0.001, location, normal) * presence;
|
||||
}
|
||||
|
||||
static inline double _getLayerDisplacement(TextureLayerDefinition *layer, const Vector3 &location,
|
||||
const Vector3 &normal) {
|
||||
double presence = _getLayerPresence(layer, location, normal);
|
||||
return _getLayerDisplacement(layer, location, normal, presence);
|
||||
}
|
||||
|
||||
Vector3 TexturesRenderer::displaceTerrain(const TexturesDefinition *textures, const Vector3 &location,
|
||||
const Vector3 &normal) const {
|
||||
double offset = 0.0;
|
||||
int i, n;
|
||||
|
||||
n = textures->getLayerCount();
|
||||
for (i = 0; i < n; i++) {
|
||||
TextureLayerDefinition *layer = textures->getTextureLayer(i);
|
||||
|
||||
if (layer->hasDisplacement()) {
|
||||
offset += _getLayerDisplacement(layer, location, normal);
|
||||
}
|
||||
}
|
||||
|
||||
return location.add(normal.scale(offset));
|
||||
}
|
||||
|
||||
vector<double> TexturesRenderer::getLayersPresence(const TexturesDefinition *textures, const Vector3 &location,
|
||||
const Vector3 &normal) const {
|
||||
int n = textures->getLayerCount();
|
||||
vector<double> result;
|
||||
for (int i = 0; i < n; i++) {
|
||||
TextureLayerDefinition *layer = textures->getTextureLayer(i);
|
||||
double presence = _getLayerPresence(layer, location, normal);
|
||||
result.push_back(presence);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
vector<Vector3> TexturesRenderer::getLayersDisplacement(const TexturesDefinition *textures, const Vector3 &location,
|
||||
const Vector3 &normal, const vector<double> &presence) const {
|
||||
int n = textures->getLayerCount();
|
||||
assert(presence.size() == to_size(n));
|
||||
vector<Vector3> result;
|
||||
Vector3 displaced = location;
|
||||
for (int i = 0; i < n; i++) {
|
||||
double layer_presence = presence[i];
|
||||
if (layer_presence > 0.0) {
|
||||
TextureLayerDefinition *layer = textures->getTextureLayer(i);
|
||||
double displacement = _getLayerDisplacement(layer, location, normal, layer_presence);
|
||||
displaced = displaced.add(normal.scale(displacement * layer_presence));
|
||||
}
|
||||
result.push_back(displaced);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Color TexturesRenderer::getFinalComposition(const TexturesDefinition *textures, LightingManager *lighting,
|
||||
const vector<double> &presence, const vector<Vector3> &location,
|
||||
const vector<Vector3> &normal, double precision, const Vector3 &eye) const {
|
||||
unsigned int n = textures->getLayerCount();
|
||||
assert(presence.size() == to_size(n));
|
||||
assert(location.size() == to_size(n));
|
||||
assert(normal.size() == to_size(n));
|
||||
Color result = COLOR_BLACK;
|
||||
|
||||
// Start at the top-most covering layer (layers underneath are only important for displacement, not color)
|
||||
unsigned int i;
|
||||
unsigned int ipos = 0;
|
||||
for (i = n - 1; i > 0; i--) {
|
||||
if (presence[i] > 0.1 and ipos == 0) {
|
||||
ipos = i;
|
||||
} else if (presence[i] > 0.99999) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare the lighing status
|
||||
LightStatus status(lighting, location[ipos], eye);
|
||||
lighting->fillStatus(status, location[ipos]);
|
||||
|
||||
// Iterate on each layer
|
||||
while (i < n) {
|
||||
double layer_presence = presence[i];
|
||||
if (layer_presence > 0.0) {
|
||||
TextureLayerDefinition *layer = textures->getTextureLayer(i);
|
||||
auto detail_normal = _getDetailNormal(location[i], normal[i], layer, precision, quality_normal5);
|
||||
Color layer_color = status.apply(detail_normal, *layer->material);
|
||||
layer_color.a *= layer_presence;
|
||||
result.mask(layer_color);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return result;
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
#ifndef TEXTURESRENDERER_H
|
||||
#define TEXTURESRENDERER_H
|
||||
|
||||
#include "software_global.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace paysages {
|
||||
namespace software {
|
||||
|
||||
class SOFTWARESHARED_EXPORT TexturesRenderer {
|
||||
public:
|
||||
TexturesRenderer();
|
||||
virtual ~TexturesRenderer();
|
||||
|
||||
/**
|
||||
* Set the quality parameters.
|
||||
*
|
||||
* "normal5" can be set to true to use balanced 5 points instead of unbalanced 3 points for normal computations.
|
||||
*/
|
||||
void setQuality(bool normal5);
|
||||
|
||||
/**
|
||||
* Set an automated quality factor.
|
||||
*/
|
||||
void setQualityFactor(double factor);
|
||||
|
||||
/**
|
||||
* Get the maximal displacement offset all combined textures can make.
|
||||
*/
|
||||
double getMaximalDisplacement(TexturesDefinition *textures) const;
|
||||
|
||||
/**
|
||||
* Get the fully displaced terrain location (applying all textures).
|
||||
*/
|
||||
Vector3 displaceTerrain(const TexturesDefinition *textures, const Vector3 &location, const Vector3 &normal) const;
|
||||
|
||||
/**
|
||||
* Get the presence of each texture layer at a given terrain location.
|
||||
*/
|
||||
vector<double> getLayersPresence(const TexturesDefinition *textures, const Vector3 &location,
|
||||
const Vector3 &normal) const;
|
||||
|
||||
/**
|
||||
* Get the displaced location of each texture layer at a given terrain location.
|
||||
*
|
||||
* 'presence' is the result of 'getLayersPresence'.
|
||||
*/
|
||||
vector<Vector3> getLayersDisplacement(const TexturesDefinition *textures, const Vector3 &location,
|
||||
const Vector3 &normal, const vector<double> &presence) const;
|
||||
|
||||
/**
|
||||
* Get the final lighted texture composition.
|
||||
*
|
||||
* 'presence' is the result of 'getLayersPresence'.
|
||||
* 'location' is the result of 'getLayersDisplacement'.
|
||||
* 'normal' is the normal vector (taking only displacement into account, not detail) at each texture's 'location'.
|
||||
* 'precision' is the level of detail needed for the composition (minimal height of the detail noise).
|
||||
*/
|
||||
Color getFinalComposition(const TexturesDefinition *textures, LightingManager *lighting,
|
||||
const vector<double> &presence, const vector<Vector3> &location,
|
||||
const vector<Vector3> &normal, double precision, const Vector3 &eye) const;
|
||||
|
||||
private:
|
||||
bool quality_normal5;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TEXTURESRENDERER_H
|
|
@ -30,7 +30,6 @@ class BaseCloudLayerRenderer;
|
|||
class BaseCloudsModel;
|
||||
|
||||
class TerrainRenderer;
|
||||
class TexturesRenderer;
|
||||
class WaterRenderer;
|
||||
|
||||
class Rasterizer;
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
#include "BaseTestCase.h"
|
||||
#include "TexturesRenderer.h"
|
||||
|
||||
#include "Vector3.h"
|
||||
#include "TexturesDefinition.h"
|
||||
#include "TextureLayerDefinition.h"
|
||||
#include "Zone.h"
|
||||
|
||||
TEST(TexturesRenderer, getLayersPresence) {
|
||||
TexturesRenderer renderer;
|
||||
TexturesDefinition textures(NULL);
|
||||
vector<double> result;
|
||||
|
||||
result = renderer.getLayersPresence(&textures, VECTOR_ZERO, VECTOR_UP);
|
||||
ASSERT_EQ(0u, result.size());
|
||||
|
||||
TextureLayerDefinition layer1(NULL, "t1");
|
||||
textures.addLayer(layer1);
|
||||
|
||||
result = renderer.getLayersPresence(&textures, VECTOR_ZERO, VECTOR_UP);
|
||||
ASSERT_EQ(1u, result.size());
|
||||
EXPECT_DOUBLE_EQ(1.0, result[0]);
|
||||
|
||||
TextureLayerDefinition layer2(NULL, "t2");
|
||||
layer2.terrain_zone->addHeightRangeQuick(0.8, 0.0, 1.0, 2.0, 3.0);
|
||||
textures.addLayer(layer2);
|
||||
|
||||
result = renderer.getLayersPresence(&textures, VECTOR_ZERO, VECTOR_UP);
|
||||
ASSERT_EQ(2u, result.size());
|
||||
EXPECT_DOUBLE_EQ(1.0, result[0]);
|
||||
EXPECT_DOUBLE_EQ(0.0, result[1]);
|
||||
|
||||
result = renderer.getLayersPresence(&textures, VECTOR_UP.scale(0.5), VECTOR_UP);
|
||||
ASSERT_EQ(2u, result.size());
|
||||
EXPECT_DOUBLE_EQ(1.0, result[0]);
|
||||
EXPECT_DOUBLE_EQ(0.4, result[1]);
|
||||
|
||||
result = renderer.getLayersPresence(&textures, VECTOR_UP, VECTOR_UP);
|
||||
ASSERT_EQ(2u, result.size());
|
||||
EXPECT_DOUBLE_EQ(1.0, result[0]);
|
||||
EXPECT_DOUBLE_EQ(0.8, result[1]);
|
||||
}
|
Loading…
Reference in a new issue