Refactored vegetation presence

This commit is contained in:
Michaël Lemaire 2015-10-18 22:15:19 +02:00
parent cd7f30ecae
commit 48dc1a8f25
19 changed files with 134 additions and 88 deletions

View file

@ -54,7 +54,7 @@ void DefinitionNode::setName(const std::string &name)
this->name = name; this->name = name;
} }
Scenery* DefinitionNode::getScenery() const Scenery* DefinitionNode::getScenery() const
{ {
if (parent) if (parent)
{ {

View file

@ -26,7 +26,7 @@ public:
inline const std::string &getTypeName() const {return type_name;} 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 *getParent() const {return parent;}
inline const DefinitionNode *getRoot() const {return root;} inline const DefinitionNode *getRoot() const {return root;}

View file

@ -102,7 +102,7 @@ Scenery::FileOperationResult Scenery::loadGlobal(const std::string &filepath)
return FILE_OPERATION_OK; return FILE_OPERATION_OK;
} }
Scenery* Scenery::getScenery() const Scenery* Scenery::getScenery() const
{ {
return this; return this;
} }

View file

@ -33,7 +33,7 @@ public:
FileOperationResult saveGlobal(const std::string &filepath) const; FileOperationResult saveGlobal(const std::string &filepath) const;
FileOperationResult loadGlobal(const std::string &filepath); FileOperationResult loadGlobal(const std::string &filepath);
virtual Scenery* getScenery() override; virtual const Scenery* getScenery() const override;
void autoPreset(int seed=0); void autoPreset(int seed=0);

View file

@ -50,7 +50,7 @@ void TextureLayerDefinition::validate()
material->validate(); material->validate();
/* Update zone height range */ /* Update zone height range */
Scenery* scenery = getScenery(); const Scenery* scenery = getScenery();
if (scenery) if (scenery)
{ {
TerrainDefinition* terrain = scenery->getTerrain(); TerrainDefinition* terrain = scenery->getTerrain();

View file

@ -11,12 +11,6 @@ static DefinitionNode* _layer_constructor(Layers* parent)
VegetationDefinition::VegetationDefinition(DefinitionNode* parent) : VegetationDefinition::VegetationDefinition(DefinitionNode* parent) :
Layers(parent, "vegetation", _layer_constructor) Layers(parent, "vegetation", _layer_constructor)
{ {
debug_model = new VegetationModelDefinition(this);
}
VegetationDefinition::~VegetationDefinition()
{
delete debug_model;
} }
void VegetationDefinition::applyPreset(VegetationPreset preset) void VegetationDefinition::applyPreset(VegetationPreset preset)

View file

@ -15,7 +15,6 @@ class DEFINITIONSHARED_EXPORT VegetationDefinition : public Layers
{ {
public: public:
VegetationDefinition(DefinitionNode* parent); VegetationDefinition(DefinitionNode* parent);
virtual ~VegetationDefinition();
/** /**
* Get a vegetation layer by its position. * Get a vegetation layer by its position.
@ -27,9 +26,6 @@ public:
VEGETATION_PRESET_TEMPERATE VEGETATION_PRESET_TEMPERATE
} VegetationPreset; } VegetationPreset;
void applyPreset(VegetationPreset preset); void applyPreset(VegetationPreset preset);
// TEMP
VegetationModelDefinition *debug_model;
}; };
} }

View file

@ -4,3 +4,8 @@ VegetationInstance::VegetationInstance(const VegetationModelDefinition &model, c
model(model), base(base), size(size), angle(angle) model(model), base(base), size(size), angle(angle)
{ {
} }
VegetationInstance VegetationInstance::displace(const Vector3 &location, const Vector3 &normal) const
{
return VegetationInstance(model, location, size, angle);
}

View file

@ -1,19 +1,19 @@
#ifndef VEGETATIONINSTANCE_H #ifndef VEGETATIONINSTANCE_H
#define VEGETATIONINSTANCE_H #define VEGETATIONINSTANCE_H
#include "software_global.h" #include "definition_global.h"
#include "Vector3.h" #include "Vector3.h"
namespace paysages { namespace paysages {
namespace software { namespace definition {
/** /**
* Single instance of a vegetation layer (e.g. a single tree). * Single instance of a vegetation layer (e.g. a single tree).
* *
* This is used as potential hit on vegetation lookup. * This is used as potential hit on vegetation lookup.
*/ */
class SOFTWARESHARED_EXPORT VegetationInstance class DEFINITIONSHARED_EXPORT VegetationInstance
{ {
public: public:
VegetationInstance(const VegetationModelDefinition &model, const Vector3 &base, double size=1.0, double angle=0.0); 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 const Vector3 &getBase() const {return base;}
inline double getSize() const {return size;} 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: private:
const VegetationModelDefinition &model; const VegetationModelDefinition &model;
Vector3 base; Vector3 base;

View file

@ -1,49 +1,16 @@
#include "VegetationLayerDefinition.h" #include "VegetationLayerDefinition.h"
#include "TerrainHeightMap.h"
#include "VegetationModelDefinition.h" #include "VegetationModelDefinition.h"
#include "VegetationPresenceDefinition.h"
VegetationLayerDefinition::VegetationLayerDefinition(DefinitionNode* parent) : VegetationLayerDefinition::VegetationLayerDefinition(DefinitionNode* parent) :
DefinitionNode(parent, "layer") DefinitionNode(parent, "layer")
{ {
//area = new TerrainHeightMap();
model = new VegetationModelDefinition(this); model = new VegetationModelDefinition(this);
} presence = new VegetationPresenceDefinition(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();
} }
void VegetationLayerDefinition::applyPreset(VegetationLayerPreset preset) void VegetationLayerDefinition::applyPreset(VegetationLayerPreset preset)
{ {
// TODO
model->randomize(); model->randomize();
} }

View file

@ -15,12 +15,9 @@ class DEFINITIONSHARED_EXPORT VegetationLayerDefinition : public DefinitionNode
{ {
public: public:
VegetationLayerDefinition(DefinitionNode *parent); VegetationLayerDefinition(DefinitionNode *parent);
virtual ~VegetationLayerDefinition();
virtual void save(PackStream *stream) const override; inline const VegetationPresenceDefinition *getPresence() const {return presence;}
virtual void load(PackStream *stream) override; inline const VegetationModelDefinition *getModel() const {return model;}
virtual void copy(DefinitionNode *destination) const override;
virtual void validate() override;
typedef enum typedef enum
{ {
@ -32,7 +29,7 @@ private:
/** /**
* Geographic area of presence of this layer. * Geographic area of presence of this layer.
*/ */
TerrainHeightMap *area; VegetationPresenceDefinition *presence;
/** /**
* Base vegetation model to use for this layer. * Base vegetation model to use for this layer.

View file

@ -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<VegetationInstance> *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;
}

View file

@ -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<VegetationInstance> *result, const VegetationModelDefinition &model, double xmin, double zmin, double xmax, double zmax, bool outcomers=true) const;
};
}
}
#endif // VEGETATIONPRESENCEDEFINITION_H

View file

@ -30,6 +30,7 @@ SOURCES += \
VegetationLayerDefinition.cpp \ VegetationLayerDefinition.cpp \
VegetationDefinition.cpp \ VegetationDefinition.cpp \
VegetationModelDefinition.cpp \ VegetationModelDefinition.cpp \
VegetationInstance.cpp \
PaintedGrid.cpp \ PaintedGrid.cpp \
PaintedGridBrush.cpp \ PaintedGridBrush.cpp \
PaintedGridData.cpp \ PaintedGridData.cpp \
@ -42,7 +43,8 @@ SOURCES += \
IntNode.cpp \ IntNode.cpp \
IntDiff.cpp \ IntDiff.cpp \
GodRaysDefinition.cpp \ GodRaysDefinition.cpp \
TimeManager.cpp TimeManager.cpp \
VegetationPresenceDefinition.cpp
HEADERS +=\ HEADERS +=\
definition_global.h \ definition_global.h \
@ -62,6 +64,7 @@ HEADERS +=\
VegetationLayerDefinition.h \ VegetationLayerDefinition.h \
VegetationDefinition.h \ VegetationDefinition.h \
VegetationModelDefinition.h \ VegetationModelDefinition.h \
VegetationInstance.h \
PaintedGrid.h \ PaintedGrid.h \
PaintedGridBrush.h \ PaintedGridBrush.h \
PaintedGridData.h \ PaintedGridData.h \
@ -74,7 +77,8 @@ HEADERS +=\
IntNode.h \ IntNode.h \
IntDiff.h \ IntDiff.h \
GodRaysDefinition.h \ GodRaysDefinition.h \
TimeManager.h TimeManager.h \
VegetationPresenceDefinition.h
unix:!symbian { unix:!symbian {
maemo5 { maemo5 {

View file

@ -38,6 +38,8 @@ namespace definition {
class VegetationDefinition; class VegetationDefinition;
class VegetationLayerDefinition; class VegetationLayerDefinition;
class VegetationModelDefinition; class VegetationModelDefinition;
class VegetationPresenceDefinition;
class VegetationInstance;
class PaintedGrid; class PaintedGrid;
class PaintedGridData; class PaintedGridData;
class PaintedGridBrush; class PaintedGridBrush;

View file

@ -9,17 +9,20 @@
#include "Scenery.h" #include "Scenery.h"
#include "TerrainRenderer.h" #include "TerrainRenderer.h"
#include "VegetationDefinition.h" #include "VegetationDefinition.h"
#include "VegetationLayerDefinition.h"
#include "VegetationPresenceDefinition.h"
#include "VegetationInstance.h"
#include "VegetationResult.h" #include "VegetationResult.h"
#include "LightComponent.h" #include "LightComponent.h"
const double DEBUG_DENSITY_FACTOR = 0.5; /**
* Grid iterator to collect instances of a layer, in small squares.
// TEMP */
class VegetationGridIterator: public SpaceGridIterator class VegetationGridIterator: public SpaceGridIterator
{ {
public: public:
VegetationGridIterator(const SpaceSegment &segment, VegetationRenderer *renderer, VegetationModelDefinition *model, bool only_hit): VegetationGridIterator(const SpaceSegment &segment, VegetationRenderer *renderer, VegetationLayerDefinition *layer, bool only_hit):
segment(segment), renderer(renderer), model(model), only_hit(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 virtual bool onCell(int x, int, int z) override
{ {
double dx = ((double)x + 0.5) * DEBUG_DENSITY_FACTOR; std::vector<VegetationInstance> instances;
double dz = ((double)z + 0.5) * DEBUG_DENSITY_FACTOR;
Vector3 base = renderer->getParent()->getTerrainRenderer()->getResult(dx, dz, 1, 1).location; layer->getPresence()->collectInstances(&instances, *layer->getModel(), x - 0.5, z - 0.5, x + 0.5, z + 0.5);
VegetationInstance instance(*model, base, 0.2);
result = renderer->renderInstance(segment, instance, only_hit); for (auto &instance: instances)
return not result.hit; {
result = renderer->renderInstance(segment, instance, only_hit);
if (result.hit)
{
return false;
}
}
return true;
} }
private: private:
const SpaceSegment &segment; const SpaceSegment &segment;
VegetationRenderer *renderer; VegetationRenderer *renderer;
VegetationModelDefinition *model; VegetationLayerDefinition *layer;
RayCastingResult result; RayCastingResult result;
bool only_hit; bool only_hit;
}; };
@ -52,10 +62,18 @@ void VegetationRenderer::setEnabled(bool enabled)
this->enabled = 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()); VegetationModelRenderer model_renderer(parent, &instance.getModel());
SpaceSegment scaled_segment(segment.getStart().sub(instance.getBase()).scale(1.0 / instance.getSize()), SpaceSegment scaled_segment(segment.getStart().sub(instance.getBase()).scale(1.0 / instance.getSize()),
segment.getEnd().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) if (enabled)
{ {
// Find instances potentially crossing the segment VegetationDefinition *vegetation = parent->getScenery()->getVegetation();
// TODO Collect the nearest hit, don't stop at the first one int n = vegetation->count();
VegetationGridIterator it(segment, this, parent->getScenery()->getVegetation()->debug_model, only_hit); // TODO Don't stop at first layer, find the nearest hit
if (not segment.projectedOnYPlane().scaled(1.0 / DEBUG_DENSITY_FACTOR).iterateOnGrid(it)) for (int i = 0; i < n; i++)
{ {
return it.getResult(); // Find instances potentially crossing the segment
} VegetationGridIterator it(segment, this, vegetation->getVegetationLayer(i), only_hit);
else if (not segment.projectedOnYPlane().iterateOnGrid(it))
{ {
return RayCastingResult(); return it.getResult();
}
} }
return RayCastingResult();
} }
else else
{ {

View file

@ -22,8 +22,12 @@ public:
/** /**
* Perform ray casting on a single instance. * 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. * Perform ray casting on a given segment.

View file

@ -59,7 +59,6 @@ SOURCES += SoftwareRenderer.cpp \
GodRaysResult.cpp \ GodRaysResult.cpp \
VegetationRasterizer.cpp \ VegetationRasterizer.cpp \
VegetationRenderer.cpp \ VegetationRenderer.cpp \
VegetationInstance.cpp \
VegetationResult.cpp VegetationResult.cpp
HEADERS += SoftwareRenderer.h\ HEADERS += SoftwareRenderer.h\
@ -109,7 +108,6 @@ HEADERS += SoftwareRenderer.h\
GodRaysResult.h \ GodRaysResult.h \
VegetationRasterizer.h \ VegetationRasterizer.h \
VegetationRenderer.h \ VegetationRenderer.h \
VegetationInstance.h \
VegetationResult.h VegetationResult.h
unix:!symbian { unix:!symbian {

View file

@ -55,7 +55,6 @@ namespace software {
class GodRaysSampler; class GodRaysSampler;
class GodRaysResult; class GodRaysResult;
class VegetationResult; class VegetationResult;
class VegetationInstance;
class VegetationRenderer; class VegetationRenderer;
class VegetationModelRenderer; class VegetationModelRenderer;