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;
}
Scenery* DefinitionNode::getScenery()
const Scenery* DefinitionNode::getScenery() const
{
if (parent)
{

View file

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

View file

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

View file

@ -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);

View file

@ -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();

View file

@ -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)

View file

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

View file

@ -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);
}

View file

@ -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;

View file

@ -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();
}

View file

@ -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.

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 \
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 {

View file

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

View file

@ -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<VegetationInstance> 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
{

View file

@ -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.

View file

@ -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 {

View file

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