diff --git a/src/definition/DefinitionNode.cpp b/src/definition/DefinitionNode.cpp index e994903..e5580e8 100644 --- a/src/definition/DefinitionNode.cpp +++ b/src/definition/DefinitionNode.cpp @@ -54,7 +54,7 @@ void DefinitionNode::setName(const std::string &name) this->name = name; } -Scenery* DefinitionNode::getScenery() +const Scenery* DefinitionNode::getScenery() const { if (parent) { diff --git a/src/definition/DefinitionNode.h b/src/definition/DefinitionNode.h index 514631f..b24edec 100644 --- a/src/definition/DefinitionNode.h +++ b/src/definition/DefinitionNode.h @@ -26,7 +26,7 @@ public: inline const std::string &getTypeName() const {return type_name;} - virtual Scenery* getScenery(); + virtual const Scenery* getScenery() const; inline const DefinitionNode *getParent() const {return parent;} inline const DefinitionNode *getRoot() const {return root;} diff --git a/src/definition/Scenery.cpp b/src/definition/Scenery.cpp index 0ee7409..b60a5ed 100644 --- a/src/definition/Scenery.cpp +++ b/src/definition/Scenery.cpp @@ -102,7 +102,7 @@ Scenery::FileOperationResult Scenery::loadGlobal(const std::string &filepath) return FILE_OPERATION_OK; } -Scenery* Scenery::getScenery() +const Scenery* Scenery::getScenery() const { return this; } diff --git a/src/definition/Scenery.h b/src/definition/Scenery.h index 5513490..cf9ebe4 100644 --- a/src/definition/Scenery.h +++ b/src/definition/Scenery.h @@ -33,7 +33,7 @@ public: FileOperationResult saveGlobal(const std::string &filepath) const; FileOperationResult loadGlobal(const std::string &filepath); - virtual Scenery* getScenery() override; + virtual const Scenery* getScenery() const override; void autoPreset(int seed=0); diff --git a/src/definition/TextureLayerDefinition.cpp b/src/definition/TextureLayerDefinition.cpp index fce5217..3ae17b3 100644 --- a/src/definition/TextureLayerDefinition.cpp +++ b/src/definition/TextureLayerDefinition.cpp @@ -50,7 +50,7 @@ void TextureLayerDefinition::validate() material->validate(); /* Update zone height range */ - Scenery* scenery = getScenery(); + const Scenery* scenery = getScenery(); if (scenery) { TerrainDefinition* terrain = scenery->getTerrain(); diff --git a/src/definition/VegetationDefinition.cpp b/src/definition/VegetationDefinition.cpp index 8f4a121..9437560 100644 --- a/src/definition/VegetationDefinition.cpp +++ b/src/definition/VegetationDefinition.cpp @@ -11,12 +11,6 @@ static DefinitionNode* _layer_constructor(Layers* parent) VegetationDefinition::VegetationDefinition(DefinitionNode* parent) : Layers(parent, "vegetation", _layer_constructor) { - debug_model = new VegetationModelDefinition(this); -} - -VegetationDefinition::~VegetationDefinition() -{ - delete debug_model; } void VegetationDefinition::applyPreset(VegetationPreset preset) diff --git a/src/definition/VegetationDefinition.h b/src/definition/VegetationDefinition.h index e8c8ece..aea9e11 100644 --- a/src/definition/VegetationDefinition.h +++ b/src/definition/VegetationDefinition.h @@ -15,7 +15,6 @@ class DEFINITIONSHARED_EXPORT VegetationDefinition : public Layers { public: VegetationDefinition(DefinitionNode* parent); - virtual ~VegetationDefinition(); /** * Get a vegetation layer by its position. @@ -27,9 +26,6 @@ public: VEGETATION_PRESET_TEMPERATE } VegetationPreset; void applyPreset(VegetationPreset preset); - - // TEMP - VegetationModelDefinition *debug_model; }; } diff --git a/src/render/software/VegetationInstance.cpp b/src/definition/VegetationInstance.cpp similarity index 56% rename from src/render/software/VegetationInstance.cpp rename to src/definition/VegetationInstance.cpp index 77edb69..8b95811 100644 --- a/src/render/software/VegetationInstance.cpp +++ b/src/definition/VegetationInstance.cpp @@ -4,3 +4,8 @@ VegetationInstance::VegetationInstance(const VegetationModelDefinition &model, c model(model), base(base), size(size), angle(angle) { } + +VegetationInstance VegetationInstance::displace(const Vector3 &location, const Vector3 &normal) const +{ + return VegetationInstance(model, location, size, angle); +} diff --git a/src/render/software/VegetationInstance.h b/src/definition/VegetationInstance.h similarity index 71% rename from src/render/software/VegetationInstance.h rename to src/definition/VegetationInstance.h index 2b2d1eb..fd54a21 100644 --- a/src/render/software/VegetationInstance.h +++ b/src/definition/VegetationInstance.h @@ -1,19 +1,19 @@ #ifndef VEGETATIONINSTANCE_H #define VEGETATIONINSTANCE_H -#include "software_global.h" +#include "definition_global.h" #include "Vector3.h" namespace paysages { -namespace software { +namespace definition { /** * Single instance of a vegetation layer (e.g. a single tree). * * This is used as potential hit on vegetation lookup. */ -class SOFTWARESHARED_EXPORT VegetationInstance +class DEFINITIONSHARED_EXPORT VegetationInstance { public: VegetationInstance(const VegetationModelDefinition &model, const Vector3 &base, double size=1.0, double angle=0.0); @@ -22,6 +22,11 @@ public: inline const Vector3 &getBase() const {return base;} inline double getSize() const {return size;} + /** + * Return a copy of this instance, with terrain displacement applied. + */ + VegetationInstance displace(const Vector3 &location, const Vector3 &normal) const; + private: const VegetationModelDefinition &model; Vector3 base; diff --git a/src/definition/VegetationLayerDefinition.cpp b/src/definition/VegetationLayerDefinition.cpp index 0480dea..79e53fa 100644 --- a/src/definition/VegetationLayerDefinition.cpp +++ b/src/definition/VegetationLayerDefinition.cpp @@ -1,49 +1,16 @@ #include "VegetationLayerDefinition.h" -#include "TerrainHeightMap.h" #include "VegetationModelDefinition.h" +#include "VegetationPresenceDefinition.h" VegetationLayerDefinition::VegetationLayerDefinition(DefinitionNode* parent) : DefinitionNode(parent, "layer") { - //area = new TerrainHeightMap(); model = new VegetationModelDefinition(this); -} - -VegetationLayerDefinition::~VegetationLayerDefinition() -{ - //delete area; - delete model; -} - -void VegetationLayerDefinition::save(PackStream *stream) const -{ - //area->save(stream); - model->save(stream); -} - -void VegetationLayerDefinition::load(PackStream *stream) -{ - //area->load(stream); - model->load(stream); -} - -void VegetationLayerDefinition::copy(DefinitionNode *destination_) const -{ - VegetationLayerDefinition *destination = (VegetationLayerDefinition *)destination_; - - //area->copy(destination->area); - model->copy(destination->model); -} - -void VegetationLayerDefinition::validate() -{ - //area->validate(); - model->validate(); + presence = new VegetationPresenceDefinition(this); } void VegetationLayerDefinition::applyPreset(VegetationLayerPreset preset) { - // TODO model->randomize(); } diff --git a/src/definition/VegetationLayerDefinition.h b/src/definition/VegetationLayerDefinition.h index e3fbf08..8fe775b 100644 --- a/src/definition/VegetationLayerDefinition.h +++ b/src/definition/VegetationLayerDefinition.h @@ -15,12 +15,9 @@ class DEFINITIONSHARED_EXPORT VegetationLayerDefinition : public DefinitionNode { public: VegetationLayerDefinition(DefinitionNode *parent); - virtual ~VegetationLayerDefinition(); - virtual void save(PackStream *stream) const override; - virtual void load(PackStream *stream) override; - virtual void copy(DefinitionNode *destination) const override; - virtual void validate() override; + inline const VegetationPresenceDefinition *getPresence() const {return presence;} + inline const VegetationModelDefinition *getModel() const {return model;} typedef enum { @@ -32,7 +29,7 @@ private: /** * Geographic area of presence of this layer. */ - TerrainHeightMap *area; + VegetationPresenceDefinition *presence; /** * Base vegetation model to use for this layer. diff --git a/src/definition/VegetationPresenceDefinition.cpp b/src/definition/VegetationPresenceDefinition.cpp new file mode 100644 index 0000000..e8c0e5d --- /dev/null +++ b/src/definition/VegetationPresenceDefinition.cpp @@ -0,0 +1,21 @@ +#include "VegetationPresenceDefinition.h" + +#include "Scenery.h" +#include "TerrainDefinition.h" +#include "VegetationLayerDefinition.h" +#include "VegetationInstance.h" + +VegetationPresenceDefinition::VegetationPresenceDefinition(VegetationLayerDefinition *parent): + DefinitionNode(parent, "presence") +{ +} + +bool VegetationPresenceDefinition::collectInstances(std::vector *result, const VegetationModelDefinition &model, double xmin, double zmin, double xmax, double zmax, bool outcomers) const +{ + // TEMP debug implementation + double x = (xmin + xmax) / 2.0; + double z = (zmax + zmin) / 2.0; + double y = getScenery()->getTerrain()->getInterpolatedHeight(x, z, true, true); + result->push_back(VegetationInstance(model, Vector3(x, y, z), 0.2)); + return true; +} diff --git a/src/definition/VegetationPresenceDefinition.h b/src/definition/VegetationPresenceDefinition.h new file mode 100644 index 0000000..1a51f99 --- /dev/null +++ b/src/definition/VegetationPresenceDefinition.h @@ -0,0 +1,34 @@ +#ifndef VEGETATIONPRESENCEDEFINITION_H +#define VEGETATIONPRESENCEDEFINITION_H + +#include "definition_global.h" + +#include "DefinitionNode.h" + +namespace paysages { +namespace definition { + +/** + * Definition of the presence of vegetation at locations. + */ +class DEFINITIONSHARED_EXPORT VegetationPresenceDefinition: public DefinitionNode +{ +public: + VegetationPresenceDefinition(VegetationLayerDefinition *parent); + + /** + * Collect instances in a rectangle area. + * + * If *outcomers* is true, the rectangle area will be expanded to included potential instances that does not originate + * in the area, but may have leaves in it. + * + * The location vector set in collected instances is based on raw terrain height, without displacement. + * It's the renderer role to apply the correct displacement. + */ + bool collectInstances(std::vector *result, const VegetationModelDefinition &model, double xmin, double zmin, double xmax, double zmax, bool outcomers=true) const; +}; + +} +} + +#endif // VEGETATIONPRESENCEDEFINITION_H diff --git a/src/definition/definition.pro b/src/definition/definition.pro index d328baa..559d586 100644 --- a/src/definition/definition.pro +++ b/src/definition/definition.pro @@ -30,6 +30,7 @@ SOURCES += \ VegetationLayerDefinition.cpp \ VegetationDefinition.cpp \ VegetationModelDefinition.cpp \ + VegetationInstance.cpp \ PaintedGrid.cpp \ PaintedGridBrush.cpp \ PaintedGridData.cpp \ @@ -42,7 +43,8 @@ SOURCES += \ IntNode.cpp \ IntDiff.cpp \ GodRaysDefinition.cpp \ - TimeManager.cpp + TimeManager.cpp \ + VegetationPresenceDefinition.cpp HEADERS +=\ definition_global.h \ @@ -62,6 +64,7 @@ HEADERS +=\ VegetationLayerDefinition.h \ VegetationDefinition.h \ VegetationModelDefinition.h \ + VegetationInstance.h \ PaintedGrid.h \ PaintedGridBrush.h \ PaintedGridData.h \ @@ -74,7 +77,8 @@ HEADERS +=\ IntNode.h \ IntDiff.h \ GodRaysDefinition.h \ - TimeManager.h + TimeManager.h \ + VegetationPresenceDefinition.h unix:!symbian { maemo5 { diff --git a/src/definition/definition_global.h b/src/definition/definition_global.h index fffaa08..4565eee 100644 --- a/src/definition/definition_global.h +++ b/src/definition/definition_global.h @@ -38,6 +38,8 @@ namespace definition { class VegetationDefinition; class VegetationLayerDefinition; class VegetationModelDefinition; + class VegetationPresenceDefinition; + class VegetationInstance; class PaintedGrid; class PaintedGridData; class PaintedGridBrush; diff --git a/src/render/software/VegetationRenderer.cpp b/src/render/software/VegetationRenderer.cpp index e89230e..ee87693 100644 --- a/src/render/software/VegetationRenderer.cpp +++ b/src/render/software/VegetationRenderer.cpp @@ -9,17 +9,20 @@ #include "Scenery.h" #include "TerrainRenderer.h" #include "VegetationDefinition.h" +#include "VegetationLayerDefinition.h" +#include "VegetationPresenceDefinition.h" +#include "VegetationInstance.h" #include "VegetationResult.h" #include "LightComponent.h" -const double DEBUG_DENSITY_FACTOR = 0.5; - -// TEMP +/** + * Grid iterator to collect instances of a layer, in small squares. + */ class VegetationGridIterator: public SpaceGridIterator { public: - VegetationGridIterator(const SpaceSegment &segment, VegetationRenderer *renderer, VegetationModelDefinition *model, bool only_hit): - segment(segment), renderer(renderer), model(model), only_hit(only_hit) + VegetationGridIterator(const SpaceSegment &segment, VegetationRenderer *renderer, VegetationLayerDefinition *layer, bool only_hit): + segment(segment), renderer(renderer), layer(layer), only_hit(only_hit) { } @@ -27,17 +30,24 @@ public: virtual bool onCell(int x, int, int z) override { - double dx = ((double)x + 0.5) * DEBUG_DENSITY_FACTOR; - double dz = ((double)z + 0.5) * DEBUG_DENSITY_FACTOR; - Vector3 base = renderer->getParent()->getTerrainRenderer()->getResult(dx, dz, 1, 1).location; - VegetationInstance instance(*model, base, 0.2); - result = renderer->renderInstance(segment, instance, only_hit); - return not result.hit; + std::vector instances; + + layer->getPresence()->collectInstances(&instances, *layer->getModel(), x - 0.5, z - 0.5, x + 0.5, z + 0.5); + + for (auto &instance: instances) + { + result = renderer->renderInstance(segment, instance, only_hit); + if (result.hit) + { + return false; + } + } + return true; } private: const SpaceSegment &segment; VegetationRenderer *renderer; - VegetationModelDefinition *model; + VegetationLayerDefinition *layer; RayCastingResult result; bool only_hit; }; @@ -52,10 +62,18 @@ void VegetationRenderer::setEnabled(bool enabled) this->enabled = enabled; } -RayCastingResult VegetationRenderer::renderInstance(const SpaceSegment &segment, const VegetationInstance &instance, bool only_hit) +RayCastingResult VegetationRenderer::renderInstance(const SpaceSegment &segment, const VegetationInstance &instance, bool only_hit, bool displaced) { - RayCastingResult final; + if (!displaced) + { + // Recursive call on displaced instance + const Vector3 &base = instance.getBase(); + TerrainRenderer::TerrainResult terrain = parent->getTerrainRenderer()->getResult(base.x, base.z, true, true); + VegetationInstance displaced_instance = instance.displace(terrain.location, terrain.normal); + return renderInstance(segment, displaced_instance, only_hit, true); + } + RayCastingResult final; VegetationModelRenderer model_renderer(parent, &instance.getModel()); SpaceSegment scaled_segment(segment.getStart().sub(instance.getBase()).scale(1.0 / instance.getSize()), segment.getEnd().sub(instance.getBase()).scale(1.0 / instance.getSize())); @@ -78,17 +96,19 @@ RayCastingResult VegetationRenderer::getResult(const SpaceSegment &segment, bool { if (enabled) { - // Find instances potentially crossing the segment - // TODO Collect the nearest hit, don't stop at the first one - VegetationGridIterator it(segment, this, parent->getScenery()->getVegetation()->debug_model, only_hit); - if (not segment.projectedOnYPlane().scaled(1.0 / DEBUG_DENSITY_FACTOR).iterateOnGrid(it)) + VegetationDefinition *vegetation = parent->getScenery()->getVegetation(); + int n = vegetation->count(); + // TODO Don't stop at first layer, find the nearest hit + for (int i = 0; i < n; i++) { - return it.getResult(); - } - else - { - return RayCastingResult(); + // Find instances potentially crossing the segment + VegetationGridIterator it(segment, this, vegetation->getVegetationLayer(i), only_hit); + if (not segment.projectedOnYPlane().iterateOnGrid(it)) + { + return it.getResult(); + } } + return RayCastingResult(); } else { diff --git a/src/render/software/VegetationRenderer.h b/src/render/software/VegetationRenderer.h index 42cab58..c7fd1b4 100644 --- a/src/render/software/VegetationRenderer.h +++ b/src/render/software/VegetationRenderer.h @@ -22,8 +22,12 @@ public: /** * Perform ray casting on a single instance. + * + * If *only_hit* is true, only care about hitting or not, do not compute the color. + * + * If *displaced* is true, *instance* is considered on already displaced terrain, else, terrain displacement is applied. */ - RayCastingResult renderInstance(const SpaceSegment &segment, const VegetationInstance &instance, bool only_hit=false); + RayCastingResult renderInstance(const SpaceSegment &segment, const VegetationInstance &instance, bool only_hit=false, bool displaced=false); /** * Perform ray casting on a given segment. diff --git a/src/render/software/software.pro b/src/render/software/software.pro index 583ec81..a9cf031 100644 --- a/src/render/software/software.pro +++ b/src/render/software/software.pro @@ -59,7 +59,6 @@ SOURCES += SoftwareRenderer.cpp \ GodRaysResult.cpp \ VegetationRasterizer.cpp \ VegetationRenderer.cpp \ - VegetationInstance.cpp \ VegetationResult.cpp HEADERS += SoftwareRenderer.h\ @@ -109,7 +108,6 @@ HEADERS += SoftwareRenderer.h\ GodRaysResult.h \ VegetationRasterizer.h \ VegetationRenderer.h \ - VegetationInstance.h \ VegetationResult.h unix:!symbian { diff --git a/src/render/software/software_global.h b/src/render/software/software_global.h index 4996a99..e0f5855 100644 --- a/src/render/software/software_global.h +++ b/src/render/software/software_global.h @@ -55,7 +55,6 @@ namespace software { class GodRaysSampler; class GodRaysResult; class VegetationResult; - class VegetationInstance; class VegetationRenderer; class VegetationModelRenderer;