First draft of vegetation layers (WIP)
This commit is contained in:
parent
52bad18d26
commit
b430f6037e
31 changed files with 949 additions and 12 deletions
|
@ -9,6 +9,7 @@
|
|||
#include "CloudsDefinition.h"
|
||||
#include "TerrainDefinition.h"
|
||||
#include "TexturesDefinition.h"
|
||||
#include "VegetationDefinition.h"
|
||||
#include "WaterDefinition.h"
|
||||
#include "Logs.h"
|
||||
|
||||
|
@ -24,6 +25,7 @@ Scenery::Scenery():
|
|||
terrain = new TerrainDefinition(this);
|
||||
textures = new TexturesDefinition(this);
|
||||
water = new WaterDefinition(this);
|
||||
vegetation = new VegetationDefinition(this);
|
||||
}
|
||||
|
||||
void Scenery::validate()
|
||||
|
@ -118,6 +120,7 @@ void Scenery::autoPreset(int seed)
|
|||
atmosphere->applyPreset(AtmosphereDefinition::ATMOSPHERE_PRESET_CLEAR_DAY);
|
||||
water->applyPreset(WaterDefinition::WATER_PRESET_LAKE);
|
||||
clouds->applyPreset(CloudsDefinition::CLOUDS_PRESET_PARTLY_CLOUDY);
|
||||
vegetation->applyPreset(VegetationDefinition::VEGETATION_PRESET_TEMPERATE);
|
||||
|
||||
camera->setLocation(VECTOR_ZERO);
|
||||
camera->setTarget(VECTOR_NORTH);
|
||||
|
@ -178,6 +181,16 @@ void Scenery::getTextures(TexturesDefinition* textures)
|
|||
this->textures->copy(textures);
|
||||
}
|
||||
|
||||
void Scenery::setVegetation(VegetationDefinition* vegetation)
|
||||
{
|
||||
vegetation->copy(this->vegetation);
|
||||
}
|
||||
|
||||
void Scenery::getVegetation(VegetationDefinition* vegetation)
|
||||
{
|
||||
this->vegetation->copy(vegetation);
|
||||
}
|
||||
|
||||
void Scenery::setWater(WaterDefinition* water)
|
||||
{
|
||||
water->copy(this->water);
|
||||
|
|
|
@ -57,6 +57,10 @@ public:
|
|||
inline TexturesDefinition* getTextures() const {return textures;}
|
||||
void getTextures(TexturesDefinition* textures);
|
||||
|
||||
void setVegetation(VegetationDefinition* Vegetation);
|
||||
inline VegetationDefinition* getVegetation() const {return vegetation;}
|
||||
void getVegetation(VegetationDefinition* Vegetation);
|
||||
|
||||
void setWater(WaterDefinition* water);
|
||||
inline WaterDefinition* getWater() const {return water;}
|
||||
void getWater(WaterDefinition* water);
|
||||
|
@ -69,6 +73,7 @@ private:
|
|||
CloudsDefinition* clouds;
|
||||
TerrainDefinition* terrain;
|
||||
TexturesDefinition* textures;
|
||||
VegetationDefinition* vegetation;
|
||||
WaterDefinition* water;
|
||||
};
|
||||
|
||||
|
|
|
@ -17,6 +17,12 @@ SurfaceMaterial::SurfaceMaterial(const Color &color)
|
|||
receive_shadows = 1.0;
|
||||
}
|
||||
|
||||
SurfaceMaterial::SurfaceMaterial(const SurfaceMaterial &other):
|
||||
SurfaceMaterial(COLOR_BLACK)
|
||||
{
|
||||
other.copy(this);
|
||||
}
|
||||
|
||||
SurfaceMaterial::~SurfaceMaterial()
|
||||
{
|
||||
delete base;
|
||||
|
|
|
@ -11,6 +11,7 @@ class DEFINITIONSHARED_EXPORT SurfaceMaterial
|
|||
public:
|
||||
SurfaceMaterial();
|
||||
SurfaceMaterial(const Color &color);
|
||||
SurfaceMaterial(const SurfaceMaterial &other);
|
||||
~SurfaceMaterial();
|
||||
|
||||
void setColor(double r, double g, double b, double a);
|
||||
|
|
34
src/definition/VegetationDefinition.cpp
Normal file
34
src/definition/VegetationDefinition.cpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
#include "VegetationDefinition.h"
|
||||
|
||||
#include "VegetationLayerDefinition.h"
|
||||
#include "VegetationModelDefinition.h"
|
||||
|
||||
static DefinitionNode* _layer_constructor(Layers* parent)
|
||||
{
|
||||
return new VegetationLayerDefinition(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)
|
||||
{
|
||||
VegetationLayerDefinition *layer;
|
||||
|
||||
clear();
|
||||
|
||||
if (preset == VEGETATION_PRESET_TEMPERATE)
|
||||
{
|
||||
layer = getVegetationLayer(addLayer());
|
||||
layer->applyPreset(VegetationLayerDefinition::VEGETATION_BASIC_TREES);
|
||||
layer->setName("Basic tree");
|
||||
}
|
||||
}
|
38
src/definition/VegetationDefinition.h
Normal file
38
src/definition/VegetationDefinition.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
#ifndef VEGETATIONDEFINITION_H
|
||||
#define VEGETATIONDEFINITION_H
|
||||
|
||||
#include "definition_global.h"
|
||||
|
||||
#include "Layers.h"
|
||||
|
||||
namespace paysages {
|
||||
namespace definition {
|
||||
|
||||
/**
|
||||
* Definition of all vegetation layers in the scenery.
|
||||
*/
|
||||
class DEFINITIONSHARED_EXPORT VegetationDefinition : public Layers
|
||||
{
|
||||
public:
|
||||
VegetationDefinition(DefinitionNode* parent);
|
||||
virtual ~VegetationDefinition();
|
||||
|
||||
/**
|
||||
* Get a vegetation layer by its position.
|
||||
*/
|
||||
inline VegetationLayerDefinition* getVegetationLayer(int position) const {return (VegetationLayerDefinition*)getLayer(position);}
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VEGETATION_PRESET_TEMPERATE
|
||||
} VegetationPreset;
|
||||
void applyPreset(VegetationPreset preset);
|
||||
|
||||
// TEMP
|
||||
VegetationModelDefinition *debug_model;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // VEGETATIONDEFINITION_H
|
49
src/definition/VegetationLayerDefinition.cpp
Normal file
49
src/definition/VegetationLayerDefinition.cpp
Normal file
|
@ -0,0 +1,49 @@
|
|||
#include "VegetationLayerDefinition.h"
|
||||
|
||||
#include "TerrainHeightMap.h"
|
||||
#include "VegetationModelDefinition.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();
|
||||
}
|
||||
|
||||
void VegetationLayerDefinition::applyPreset(VegetationLayerPreset preset)
|
||||
{
|
||||
// TODO
|
||||
model->randomize();
|
||||
}
|
46
src/definition/VegetationLayerDefinition.h
Normal file
46
src/definition/VegetationLayerDefinition.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
#ifndef VEGETATIONLAYERDEFINITION_H
|
||||
#define VEGETATIONLAYERDEFINITION_H
|
||||
|
||||
#include "definition_global.h"
|
||||
|
||||
#include "DefinitionNode.h"
|
||||
|
||||
namespace paysages {
|
||||
namespace definition {
|
||||
|
||||
/**
|
||||
* Definition of one vegetation layer.
|
||||
*/
|
||||
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;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VEGETATION_BASIC_TREES
|
||||
} VegetationLayerPreset;
|
||||
void applyPreset(VegetationLayerPreset preset);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Geographic area of presence of this layer.
|
||||
*/
|
||||
TerrainHeightMap *area;
|
||||
|
||||
/**
|
||||
* Base vegetation model to use for this layer.
|
||||
*/
|
||||
VegetationModelDefinition *model;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // VEGETATIONLAYERDEFINITION_H
|
166
src/definition/VegetationModelDefinition.cpp
Normal file
166
src/definition/VegetationModelDefinition.cpp
Normal file
|
@ -0,0 +1,166 @@
|
|||
#include "VegetationModelDefinition.h"
|
||||
|
||||
#include "VegetationDefinition.h"
|
||||
#include "RandomGenerator.h"
|
||||
#include "Matrix4.h"
|
||||
#include "SurfaceMaterial.h"
|
||||
#include "PackStream.h"
|
||||
|
||||
VegetationModelDefinition::VegetationModelDefinition(DefinitionNode *parent):
|
||||
DefinitionNode(parent, "model")
|
||||
{
|
||||
solid_material = new SurfaceMaterial();
|
||||
foliage_material = new SurfaceMaterial();
|
||||
|
||||
randomize();
|
||||
}
|
||||
|
||||
VegetationModelDefinition::~VegetationModelDefinition()
|
||||
{
|
||||
delete solid_material;
|
||||
delete foliage_material;
|
||||
}
|
||||
|
||||
void VegetationModelDefinition::save(PackStream *stream) const
|
||||
{
|
||||
int n;
|
||||
solid_material->save(stream);
|
||||
foliage_material->save(stream);
|
||||
|
||||
n = solid_volumes.size();
|
||||
stream->write(&n);
|
||||
for (const auto &solid_volume: solid_volumes)
|
||||
{
|
||||
solid_volume.save(stream);
|
||||
}
|
||||
n = foliage_groups.size();
|
||||
stream->write(&n);
|
||||
for (const auto &foliage_group: foliage_groups)
|
||||
{
|
||||
foliage_group.save(stream);
|
||||
}
|
||||
n = foliage_items.size();
|
||||
stream->write(&n);
|
||||
for (const auto &foliage_item: foliage_items)
|
||||
{
|
||||
foliage_item.save(stream);
|
||||
}
|
||||
}
|
||||
|
||||
void VegetationModelDefinition::load(PackStream *stream)
|
||||
{
|
||||
int i, n;
|
||||
solid_material->load(stream);
|
||||
foliage_material->load(stream);
|
||||
|
||||
stream->read(&n);
|
||||
solid_volumes.clear();
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
CappedCylinder solid_volume;
|
||||
solid_volume.load(stream);
|
||||
solid_volumes.push_back(solid_volume);
|
||||
}
|
||||
stream->read(&n);
|
||||
foliage_groups.clear();
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
Sphere foliage_group;
|
||||
foliage_group.load(stream);
|
||||
foliage_groups.push_back(foliage_group);
|
||||
}
|
||||
stream->read(&n);
|
||||
foliage_items.clear();
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
Disk foliage_item;
|
||||
foliage_item.load(stream);
|
||||
foliage_items.push_back(foliage_item);
|
||||
}
|
||||
}
|
||||
|
||||
void VegetationModelDefinition::copy(DefinitionNode *destination_) const
|
||||
{
|
||||
VegetationModelDefinition *destination = (VegetationModelDefinition *)destination_;
|
||||
|
||||
solid_material->copy(destination->solid_material);
|
||||
foliage_material->copy(destination->foliage_material);
|
||||
|
||||
destination->solid_volumes.clear();
|
||||
for (const auto &solid_volume: solid_volumes)
|
||||
{
|
||||
destination->solid_volumes.push_back(CappedCylinder(solid_volume));
|
||||
}
|
||||
destination->foliage_groups.clear();
|
||||
for (const auto &foliage_group: foliage_groups)
|
||||
{
|
||||
destination->foliage_groups.push_back(Sphere(foliage_group));
|
||||
}
|
||||
destination->foliage_items.clear();
|
||||
for (const auto &foliage_item: foliage_items)
|
||||
{
|
||||
destination->foliage_items.push_back(Disk(foliage_item));
|
||||
}
|
||||
}
|
||||
|
||||
void VegetationModelDefinition::validate()
|
||||
{
|
||||
}
|
||||
|
||||
static inline double randomizeValue(double base, double min_factor, double max_factor)
|
||||
{
|
||||
return base * (min_factor + RandomGenerator::random() * (max_factor - min_factor));
|
||||
}
|
||||
|
||||
static void addBranchRecurse(std::vector<CappedCylinder> &branches, const Vector3 &base, const Vector3 &direction, double radius, double length)
|
||||
{
|
||||
branches.push_back(CappedCylinder(base, direction, radius, length));
|
||||
|
||||
if (length > 0.1)
|
||||
{
|
||||
int split_count = 3;
|
||||
Vector3 new_base = base.add(direction.scale(length));
|
||||
Matrix4 pivot1 = Matrix4::newRotateAxis(randomizeValue(1.0 - 0.6 * length, 0.9, 1.1), VECTOR_EAST);
|
||||
Vector3 new_direction = pivot1.multPoint(direction);
|
||||
for (int i = 0; i < split_count; i++)
|
||||
{
|
||||
Matrix4 pivot2 = Matrix4::newRotateAxis(randomizeValue(M_PI * 2.0 / (double)split_count, 0.9, 1.1), direction);
|
||||
new_direction = pivot2.multPoint(new_direction);
|
||||
|
||||
addBranchRecurse(branches, new_base, new_direction, randomizeValue(radius, 0.65, 0.75), randomizeValue(length, 0.55, 0.65));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VegetationModelDefinition::randomize()
|
||||
{
|
||||
// Clear structure
|
||||
solid_volumes.clear();
|
||||
foliage_groups.clear();
|
||||
foliage_items.clear();
|
||||
|
||||
// Add trunk and branches
|
||||
addBranchRecurse(solid_volumes, VECTOR_ZERO, VECTOR_UP, 0.05, 0.5);
|
||||
|
||||
// Add foliage groups
|
||||
for (const auto &branch: solid_volumes)
|
||||
{
|
||||
double length = branch.getLength();
|
||||
if (length < 0.2)
|
||||
{
|
||||
double radius = length * 0.5;
|
||||
Vector3 center = branch.getAxis().getOrigin().add(branch.getAxis().getDirection().scale(radius));
|
||||
foliage_groups.push_back(Sphere(center, radius * 5.0));
|
||||
}
|
||||
}
|
||||
|
||||
// Add foliage items
|
||||
for (int i = 0; i < 150; i++)
|
||||
{
|
||||
double radius = 0.15;
|
||||
Vector3 dir = Vector3::randomInSphere(1.0 - radius);
|
||||
Vector3 normal = dir.add(Vector3::randomInSphere(0.4)).add(Vector3(0.0, 0.6, 0.0)).normalize();
|
||||
Disk leaf(dir, normal, randomizeValue(radius, 0.8, 1.0));
|
||||
foliage_items.push_back(leaf);
|
||||
}
|
||||
}
|
49
src/definition/VegetationModelDefinition.h
Normal file
49
src/definition/VegetationModelDefinition.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
#ifndef VEGETATIONMODELDEFINITION_H
|
||||
#define VEGETATIONMODELDEFINITION_H
|
||||
|
||||
#include "definition_global.h"
|
||||
|
||||
#include <vector>
|
||||
#include "DefinitionNode.h"
|
||||
#include "Sphere.h"
|
||||
#include "CappedCylinder.h"
|
||||
#include "Disk.h"
|
||||
|
||||
namespace paysages {
|
||||
namespace definition {
|
||||
|
||||
/**
|
||||
* Model of vegetation.
|
||||
*/
|
||||
class DEFINITIONSHARED_EXPORT VegetationModelDefinition: public DefinitionNode
|
||||
{
|
||||
public:
|
||||
VegetationModelDefinition(DefinitionNode *parent);
|
||||
virtual ~VegetationModelDefinition();
|
||||
|
||||
inline const std::vector<CappedCylinder> &getSolidVolumes() const {return solid_volumes;}
|
||||
inline const std::vector<Sphere> &getFoliageGroups() const {return foliage_groups;}
|
||||
inline const std::vector<Disk> &getFoliageItems() const {return foliage_items;}
|
||||
|
||||
virtual void save(PackStream *stream) const override;
|
||||
virtual void load(PackStream *stream) override;
|
||||
virtual void copy(DefinitionNode *destination) const override;
|
||||
virtual void validate() override;
|
||||
|
||||
/**
|
||||
* Randomize the model geometry.
|
||||
*/
|
||||
void randomize();
|
||||
|
||||
private:
|
||||
SurfaceMaterial *solid_material;
|
||||
SurfaceMaterial *foliage_material;
|
||||
std::vector<CappedCylinder> solid_volumes;
|
||||
std::vector<Sphere> foliage_groups;
|
||||
std::vector<Disk> foliage_items;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // VEGETATIONMODELDEFINITION_H
|
|
@ -27,6 +27,9 @@ SOURCES += \
|
|||
TerrainDefinition.cpp \
|
||||
TerrainHeightMap.cpp \
|
||||
Scenery.cpp \
|
||||
VegetationLayerDefinition.cpp \
|
||||
VegetationDefinition.cpp \
|
||||
VegetationModelDefinition.cpp \
|
||||
PaintedGrid.cpp \
|
||||
PaintedGridBrush.cpp \
|
||||
PaintedGridData.cpp \
|
||||
|
@ -56,6 +59,9 @@ HEADERS +=\
|
|||
TerrainDefinition.h \
|
||||
TerrainHeightMap.h \
|
||||
Scenery.h \
|
||||
VegetationLayerDefinition.h \
|
||||
VegetationDefinition.h \
|
||||
VegetationModelDefinition.h \
|
||||
PaintedGrid.h \
|
||||
PaintedGridBrush.h \
|
||||
PaintedGridData.h \
|
||||
|
|
|
@ -35,6 +35,9 @@ namespace definition {
|
|||
class TextureLayerDefinition;
|
||||
class TerrainDefinition;
|
||||
class TerrainHeightMap;
|
||||
class VegetationDefinition;
|
||||
class VegetationLayerDefinition;
|
||||
class VegetationModelDefinition;
|
||||
class PaintedGrid;
|
||||
class PaintedGridData;
|
||||
class PaintedGridBrush;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#include "CanvasFragment.h"
|
||||
|
||||
const int MAX_FRAGMENTS_PER_PIXEL = 2;
|
||||
const int MAX_FRAGMENTS_PER_PIXEL = 5;
|
||||
|
||||
namespace paysages {
|
||||
namespace software {
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace software {
|
|||
const int RASTERIZER_CLIENT_SKY = 0;
|
||||
const int RASTERIZER_CLIENT_WATER = 1;
|
||||
const int RASTERIZER_CLIENT_TERRAIN = 2;
|
||||
const int RASTERIZER_CLIENT_VEGETATION = 3;
|
||||
|
||||
typedef struct ScanPoint ScanPoint;
|
||||
typedef struct RenderScanlines RenderScanlines;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "TerrainRasterizer.h"
|
||||
#include "WaterRasterizer.h"
|
||||
#include "SkyRasterizer.h"
|
||||
#include "VegetationRasterizer.h"
|
||||
#include "CameraDefinition.h"
|
||||
#include "ParallelWork.h"
|
||||
#include "CanvasPortion.h"
|
||||
|
@ -30,6 +31,7 @@ SoftwareCanvasRenderer::SoftwareCanvasRenderer(Scenery *scenery):
|
|||
rasterizers.push_back(new SkyRasterizer(this, progress, RASTERIZER_CLIENT_SKY));
|
||||
rasterizers.push_back(new WaterRasterizer(this, progress, RASTERIZER_CLIENT_WATER));
|
||||
rasterizers.push_back(new TerrainRasterizer(this, progress, RASTERIZER_CLIENT_TERRAIN));
|
||||
rasterizers.push_back(new VegetationRasterizer(this, progress, RASTERIZER_CLIENT_VEGETATION));
|
||||
|
||||
current_work = NULL;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "CloudsDefinition.h"
|
||||
#include "TerrainRenderer.h"
|
||||
#include "TexturesRenderer.h"
|
||||
#include "VegetationRenderer.h"
|
||||
#include "WaterRenderer.h"
|
||||
#include "SkyRasterizer.h"
|
||||
#include "TerrainRasterizer.h"
|
||||
|
@ -34,6 +35,7 @@ SoftwareRenderer::SoftwareRenderer(Scenery* scenery):
|
|||
clouds_renderer = new CloudsRenderer(this);
|
||||
terrain_renderer = new TerrainRenderer(this);
|
||||
textures_renderer = new TexturesRenderer(this);
|
||||
vegetation_renderer = new VegetationRenderer(this);
|
||||
water_renderer = new WaterRenderer(this);
|
||||
|
||||
nightsky_renderer = new NightSky(this);
|
||||
|
@ -44,6 +46,7 @@ SoftwareRenderer::SoftwareRenderer(Scenery* scenery):
|
|||
|
||||
lighting->registerFilter(water_renderer);
|
||||
lighting->registerFilter(terrain_renderer);
|
||||
lighting->registerFilter(vegetation_renderer);
|
||||
lighting->registerFilter(clouds_renderer);
|
||||
lighting->registerSource(atmosphere_renderer);
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ public:
|
|||
inline TerrainRenderer* getTerrainRenderer() const {return terrain_renderer;}
|
||||
inline TexturesRenderer* getTexturesRenderer() const {return textures_renderer;}
|
||||
inline WaterRenderer* getWaterRenderer() const {return water_renderer;}
|
||||
inline VegetationRenderer* getVegetationRenderer() const {return vegetation_renderer;}
|
||||
|
||||
inline NightSky* getNightSky() const {return nightsky_renderer;}
|
||||
|
||||
|
@ -74,6 +75,7 @@ private:
|
|||
TexturesRenderer* textures_renderer;
|
||||
WaterRenderer* water_renderer;
|
||||
NightSky* nightsky_renderer;
|
||||
VegetationRenderer *vegetation_renderer;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
TerrainRasterizer::TerrainRasterizer(SoftwareRenderer* renderer, RenderProgress *progress, int client_id):
|
||||
Rasterizer(renderer, progress, client_id, Color(1.0, 0.9, 0.9))
|
||||
{
|
||||
setBackFaceCulling(true);
|
||||
yoffset = 0.0;
|
||||
}
|
||||
|
||||
void TerrainRasterizer::setQuality(double base_chunk_size, double detail_factor, int max_chunk_detail)
|
||||
|
@ -77,19 +79,40 @@ void TerrainRasterizer::renderQuad(CanvasPortion *canvas, double x, double z, do
|
|||
ov4.z = z;
|
||||
dv4 = renderer->getTerrainRenderer()->getResult(x + size, z, true, true).location;
|
||||
|
||||
if (yoffset != 0.0)
|
||||
{
|
||||
dv1.y += yoffset;
|
||||
dv2.y += yoffset;
|
||||
dv3.y += yoffset;
|
||||
dv4.y += yoffset;
|
||||
}
|
||||
|
||||
if (dv1.y > water_height || dv2.y > water_height || dv3.y > water_height || dv4.y > water_height)
|
||||
{
|
||||
pushDisplacedQuad(canvas, dv1, dv2, dv3, dv4, ov1, ov2, ov3, ov4);
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainRasterizer::getChunk(TerrainRasterizer::TerrainChunkInfo* chunk, double x, double z, double size, bool displaced)
|
||||
void TerrainRasterizer::setYOffset(double offset)
|
||||
{
|
||||
this->yoffset = offset;
|
||||
}
|
||||
|
||||
void TerrainRasterizer::getChunk(SoftwareRenderer* renderer, TerrainRasterizer::TerrainChunkInfo* chunk, double x, double z, double size, int displaced)
|
||||
{
|
||||
chunk->point_nw = renderer->getTerrainRenderer()->getResult(x, z, true, displaced).location;
|
||||
chunk->point_sw = renderer->getTerrainRenderer()->getResult(x, z + size, true, displaced).location;
|
||||
chunk->point_se = renderer->getTerrainRenderer()->getResult(x + size, z + size, true, displaced).location;
|
||||
chunk->point_ne = renderer->getTerrainRenderer()->getResult(x + size, z, true, displaced).location;
|
||||
|
||||
if (yoffset != 0.0)
|
||||
{
|
||||
chunk->point_nw.y += yoffset;
|
||||
chunk->point_sw.y += yoffset;
|
||||
chunk->point_se.y += yoffset;
|
||||
chunk->point_ne.y += yoffset;
|
||||
}
|
||||
|
||||
double displacement_power;
|
||||
if (displaced)
|
||||
{
|
||||
|
@ -158,7 +181,7 @@ int TerrainRasterizer::performTessellation(CanvasPortion* canvas, bool displaced
|
|||
{
|
||||
for (i = 0; i < chunk_count - 1; i++)
|
||||
{
|
||||
getChunk(&chunk, cx - radius_ext + chunk_size * i, cz - radius_ext, chunk_size, displaced);
|
||||
getChunk(renderer, &chunk, cx - radius_ext + chunk_size * i, cz - radius_ext, chunk_size, displaced);
|
||||
if (chunk.detail_hint > 0)
|
||||
{
|
||||
result += chunk.detail_hint * chunk.detail_hint;
|
||||
|
@ -172,7 +195,7 @@ int TerrainRasterizer::performTessellation(CanvasPortion* canvas, bool displaced
|
|||
return result;
|
||||
}
|
||||
|
||||
getChunk(&chunk, cx + radius_int, cz - radius_ext + chunk_size * i, chunk_size, displaced);
|
||||
getChunk(renderer, &chunk, cx + radius_int, cz - radius_ext + chunk_size * i, chunk_size, displaced);
|
||||
if (chunk.detail_hint > 0)
|
||||
{
|
||||
result += chunk.detail_hint * chunk.detail_hint;
|
||||
|
@ -186,7 +209,7 @@ int TerrainRasterizer::performTessellation(CanvasPortion* canvas, bool displaced
|
|||
return result;
|
||||
}
|
||||
|
||||
getChunk(&chunk, cx + radius_int - chunk_size * i, cz + radius_int, chunk_size, displaced);
|
||||
getChunk(renderer, &chunk, cx + radius_int - chunk_size * i, cz + radius_int, chunk_size, displaced);
|
||||
if (chunk.detail_hint > 0)
|
||||
{
|
||||
result += chunk.detail_hint * chunk.detail_hint;
|
||||
|
@ -200,7 +223,7 @@ int TerrainRasterizer::performTessellation(CanvasPortion* canvas, bool displaced
|
|||
return result;
|
||||
}
|
||||
|
||||
getChunk(&chunk, cx - radius_ext, cz + radius_int - chunk_size * i, chunk_size, displaced);
|
||||
getChunk(renderer, &chunk, cx - radius_ext, cz + radius_int - chunk_size * i, chunk_size, displaced);
|
||||
if (chunk.detail_hint > 0)
|
||||
{
|
||||
result += chunk.detail_hint * chunk.detail_hint;
|
||||
|
|
|
@ -38,6 +38,14 @@ public:
|
|||
virtual void rasterizeToCanvas(CanvasPortion* canvas) override;
|
||||
virtual Color shadeFragment(const CanvasFragment &fragment, const CanvasFragment *previous) const override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Add a vertical offset to rasterized polygons.
|
||||
*
|
||||
* This may be used to rasterize a covering layer on top of ground.
|
||||
*/
|
||||
void setYOffset(double offset);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Method called for each chunk tessellated by performTessellation.
|
||||
|
@ -62,9 +70,11 @@ private:
|
|||
|
||||
void renderQuad(CanvasPortion* canvas, double x, double z, double size, double water_height);
|
||||
|
||||
void getChunk(TerrainRasterizer::TerrainChunkInfo* chunk, double x, double z, double size, bool displaced);
|
||||
void getChunk(SoftwareRenderer* renderer, TerrainRasterizer::TerrainChunkInfo* chunk, double x, double z, double size, int displaced);
|
||||
|
||||
private:
|
||||
double yoffset;
|
||||
|
||||
// Quality control
|
||||
double base_chunk_size;
|
||||
double detail_factor;
|
||||
|
|
6
src/render/software/VegetationInstance.cpp
Normal file
6
src/render/software/VegetationInstance.cpp
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include "VegetationInstance.h"
|
||||
|
||||
VegetationInstance::VegetationInstance(const VegetationModelDefinition &model, const Vector3 &base, double size, double angle):
|
||||
model(model), base(base), size(size), angle(angle)
|
||||
{
|
||||
}
|
35
src/render/software/VegetationInstance.h
Normal file
35
src/render/software/VegetationInstance.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#ifndef VEGETATIONINSTANCE_H
|
||||
#define VEGETATIONINSTANCE_H
|
||||
|
||||
#include "software_global.h"
|
||||
|
||||
#include "Vector3.h"
|
||||
|
||||
namespace paysages {
|
||||
namespace software {
|
||||
|
||||
/**
|
||||
* Single instance of a vegetation layer (e.g. a single tree).
|
||||
*
|
||||
* This is used as potential hit on vegetation lookup.
|
||||
*/
|
||||
class SOFTWARESHARED_EXPORT VegetationInstance
|
||||
{
|
||||
public:
|
||||
VegetationInstance(const VegetationModelDefinition &model, const Vector3 &base, double size=1.0, double angle=0.0);
|
||||
|
||||
inline const VegetationModelDefinition &getModel() const {return model;}
|
||||
inline const Vector3 &getBase() const {return base;}
|
||||
inline double getSize() const {return size;}
|
||||
|
||||
private:
|
||||
const VegetationModelDefinition &model;
|
||||
Vector3 base;
|
||||
double size;
|
||||
double angle;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // VEGETATIONINSTANCE_H
|
128
src/render/software/VegetationModelRenderer.cpp
Normal file
128
src/render/software/VegetationModelRenderer.cpp
Normal file
|
@ -0,0 +1,128 @@
|
|||
#include "VegetationModelRenderer.h"
|
||||
|
||||
#include "Color.h"
|
||||
#include "SurfaceMaterial.h"
|
||||
#include "SpaceSegment.h"
|
||||
#include "InfiniteRay.h"
|
||||
#include "Disk.h"
|
||||
#include "SoftwareRenderer.h"
|
||||
#include "LightComponent.h"
|
||||
#include "VegetationModelDefinition.h"
|
||||
#include "VegetationResult.h"
|
||||
|
||||
VegetationModelRenderer::VegetationModelRenderer(SoftwareRenderer* parent, const VegetationModelDefinition* model):
|
||||
parent(parent), model(model)
|
||||
{
|
||||
}
|
||||
|
||||
VegetationModelRenderer::~VegetationModelRenderer()
|
||||
{
|
||||
}
|
||||
|
||||
VegetationResult VegetationModelRenderer::getResult(const SpaceSegment &segment, bool only_hit) const
|
||||
{
|
||||
InfiniteRay ray(segment.getStart(), segment.getDirection());
|
||||
int intersections;
|
||||
Color result = COLOR_TRANSPARENT;
|
||||
bool hit = false;
|
||||
Vector3 location, normal;
|
||||
double distance, nearest, maximal;
|
||||
|
||||
maximal = segment.getLength();
|
||||
nearest = maximal;
|
||||
|
||||
for (const auto &branch: model->getSolidVolumes())
|
||||
{
|
||||
Vector3 near, far;
|
||||
if (branch.checkRayIntersection(ray, &near, &far))
|
||||
{
|
||||
distance = ray.getCursor(near);
|
||||
if (distance >= 0.0 and distance <= maximal)
|
||||
{
|
||||
// Got a branch hit
|
||||
if (only_hit)
|
||||
{
|
||||
return VegetationResult(true);
|
||||
}
|
||||
|
||||
if (distance < nearest)
|
||||
{
|
||||
result = Color(0.2, 0.15, 0.15);
|
||||
nearest = distance;
|
||||
|
||||
hit = true;
|
||||
location = near;
|
||||
normal = near.sub(branch.getAxis().getOrigin()).crossProduct(branch.getAxis().getDirection()).normalize();
|
||||
normal = branch.getAxis().getDirection().crossProduct(normal).normalize();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &foliage: model->getFoliageGroups())
|
||||
{
|
||||
Vector3 near, far;
|
||||
intersections = foliage.checkRayIntersection(ray, &near, &far);
|
||||
if (intersections == 2)
|
||||
{
|
||||
InfiniteRay subray(ray.getOrigin().sub(foliage.getCenter()).scale(1.0 / foliage.getRadius()), ray.getDirection());
|
||||
|
||||
for (const auto &leaf: model->getFoliageItems())
|
||||
{
|
||||
Disk sized_leaf(leaf.getPoint(), leaf.getNormal(), leaf.getRadius() * leaf.getRadius() / foliage.getRadius());
|
||||
if (sized_leaf.checkRayIntersection(subray, &near) == 1)
|
||||
{
|
||||
near = near.scale(foliage.getRadius()).add(foliage.getCenter());
|
||||
distance = ray.getCursor(near);
|
||||
|
||||
if (distance >= 0.0 and distance <= maximal)
|
||||
{
|
||||
// Got a foliage hit
|
||||
if (only_hit)
|
||||
{
|
||||
return VegetationResult(true);
|
||||
}
|
||||
|
||||
if (distance < nearest)
|
||||
{
|
||||
result = Color(0.3, 0.5, 0.3);
|
||||
nearest = distance;
|
||||
|
||||
hit = true;
|
||||
location = near;
|
||||
normal = sized_leaf.getNormal();
|
||||
|
||||
if (normal.dotProduct(location.sub(segment.getStart())) > 0.0)
|
||||
{
|
||||
// We look at backside
|
||||
result = Color(0.3, 0.4, 0.3);
|
||||
normal = normal.scale(-1.0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hit)
|
||||
{
|
||||
SurfaceMaterial material(result);
|
||||
material.reflection = 0.003;
|
||||
material.shininess = 3.0;
|
||||
material.hardness = 0.3;
|
||||
material.validate();
|
||||
// FIXME Can't use reference to temporary material
|
||||
return VegetationResult(location, normal, material);
|
||||
}
|
||||
else
|
||||
{
|
||||
return VegetationResult();
|
||||
}
|
||||
}
|
||||
|
||||
bool VegetationModelRenderer::applyLightFilter(LightComponent &light, const Vector3 &at)
|
||||
{
|
||||
return getResult(SpaceSegment(at, light.direction.scale(-2.0)), true).isHit();
|
||||
}
|
44
src/render/software/VegetationModelRenderer.h
Normal file
44
src/render/software/VegetationModelRenderer.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
#ifndef VEGETATIONMODELRENDERER_H
|
||||
#define VEGETATIONMODELRENDERER_H
|
||||
|
||||
#include "software_global.h"
|
||||
|
||||
#include "LightFilter.h"
|
||||
|
||||
namespace paysages {
|
||||
namespace software {
|
||||
|
||||
/**
|
||||
* Renderer of a single instance of vegetation model (e.g a single tree).
|
||||
*/
|
||||
class SOFTWARESHARED_EXPORT VegetationModelRenderer: public LightFilter
|
||||
{
|
||||
public:
|
||||
VegetationModelRenderer(SoftwareRenderer* parent, const VegetationModelDefinition *model);
|
||||
virtual ~VegetationModelRenderer();
|
||||
|
||||
/**
|
||||
* Get the final color of this model on a segment.
|
||||
*
|
||||
* Coordinates should be expressed as relative to the model origin point.
|
||||
*
|
||||
* If only_hit is True, we only look whether there is a hit or not.
|
||||
*/
|
||||
VegetationResult getResult(const SpaceSegment &segment, bool only_hit=false) const;
|
||||
|
||||
/**
|
||||
* Internal (relative) light filter.
|
||||
*
|
||||
* The 'at' parameter should be expressed as relative to the model origin point.
|
||||
*/
|
||||
virtual bool applyLightFilter(LightComponent &light, const Vector3 &at);
|
||||
|
||||
private:
|
||||
SoftwareRenderer* parent;
|
||||
const VegetationModelDefinition* model;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // VEGETATIONMODELRENDERER_H
|
46
src/render/software/VegetationRasterizer.cpp
Normal file
46
src/render/software/VegetationRasterizer.cpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
#include "VegetationRasterizer.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "CanvasFragment.h"
|
||||
#include "Color.h"
|
||||
#include "SpaceSegment.h"
|
||||
#include "SoftwareRenderer.h"
|
||||
#include "VegetationRenderer.h"
|
||||
#include "RayCastingResult.h"
|
||||
|
||||
VegetationRasterizer::VegetationRasterizer(SoftwareRenderer *renderer, RenderProgress *progress, int client_id):
|
||||
TerrainRasterizer(renderer, progress, client_id)
|
||||
{
|
||||
setYOffset(0.5);
|
||||
setColor(Color(0.8, 1.0, 0.8, 0.5));
|
||||
}
|
||||
|
||||
Color VegetationRasterizer::shadeFragment(const CanvasFragment &fragment, const CanvasFragment *previous) const
|
||||
{
|
||||
assert(previous != NULL);
|
||||
|
||||
if (not fragment.isFrontFacing() or previous->getClient() == RASTERIZER_CLIENT_SKY)
|
||||
{
|
||||
// This is an exit fragment, or the last before sky
|
||||
return COLOR_TRANSPARENT;
|
||||
}
|
||||
|
||||
// Even if we assert, this may happen in rare circumstances (no opaque background fragment), so don't crash
|
||||
if (previous == NULL)
|
||||
{
|
||||
return COLOR_TRANSPARENT;
|
||||
}
|
||||
|
||||
SoftwareRenderer *renderer = getRenderer();
|
||||
SpaceSegment segment(renderer->unprojectPoint(fragment.getPixel()), renderer->unprojectPoint(previous->getPixel()));
|
||||
RayCastingResult result = renderer->getVegetationRenderer()->getResult(segment);
|
||||
if (result.hit)
|
||||
{
|
||||
return result.hit_color;
|
||||
}
|
||||
else
|
||||
{
|
||||
return COLOR_TRANSPARENT;
|
||||
}
|
||||
}
|
22
src/render/software/VegetationRasterizer.h
Normal file
22
src/render/software/VegetationRasterizer.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#ifndef VEGETATIONRASTERIZER_H
|
||||
#define VEGETATIONRASTERIZER_H
|
||||
|
||||
#include "software_global.h"
|
||||
|
||||
#include "TerrainRasterizer.h"
|
||||
|
||||
namespace paysages {
|
||||
namespace software {
|
||||
|
||||
class SOFTWARESHARED_EXPORT VegetationRasterizer: public TerrainRasterizer
|
||||
{
|
||||
public:
|
||||
VegetationRasterizer(SoftwareRenderer* renderer, RenderProgress *progress, int client_id);
|
||||
|
||||
virtual Color shadeFragment(const CanvasFragment &fragment, const CanvasFragment *previous) const override;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // VEGETATIONRASTERIZER_H
|
100
src/render/software/VegetationRenderer.cpp
Normal file
100
src/render/software/VegetationRenderer.cpp
Normal file
|
@ -0,0 +1,100 @@
|
|||
#include "VegetationRenderer.h"
|
||||
|
||||
#include "VegetationModelRenderer.h"
|
||||
#include "RayCastingResult.h"
|
||||
#include "SpaceGridIterator.h"
|
||||
#include "SpaceSegment.h"
|
||||
#include "VegetationInstance.h"
|
||||
#include "SoftwareRenderer.h"
|
||||
#include "Scenery.h"
|
||||
#include "TerrainRenderer.h"
|
||||
#include "VegetationDefinition.h"
|
||||
#include "VegetationResult.h"
|
||||
#include "LightComponent.h"
|
||||
|
||||
const double DEBUG_DENSITY_FACTOR = 0.5;
|
||||
|
||||
// TEMP
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
inline const RayCastingResult &getResult() const {return result;}
|
||||
|
||||
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;
|
||||
}
|
||||
private:
|
||||
const SpaceSegment &segment;
|
||||
VegetationRenderer *renderer;
|
||||
VegetationModelDefinition *model;
|
||||
RayCastingResult result;
|
||||
bool only_hit;
|
||||
};
|
||||
|
||||
VegetationRenderer::VegetationRenderer(SoftwareRenderer *parent):
|
||||
parent(parent)
|
||||
{
|
||||
}
|
||||
|
||||
RayCastingResult VegetationRenderer::renderInstance(const SpaceSegment &segment, const VegetationInstance &instance, bool only_hit)
|
||||
{
|
||||
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()));
|
||||
VegetationResult result = model_renderer.getResult(scaled_segment, only_hit);
|
||||
|
||||
final.hit = result.isHit();
|
||||
|
||||
if (final.hit and not only_hit)
|
||||
{
|
||||
Vector3 location = result.getLocation().scale(instance.getSize()).add(instance.getBase());
|
||||
final.hit_color = parent->applyLightingToSurface(location, result.getNormal(), result.getMaterial());
|
||||
final.hit_color = parent->applyMediumTraversal(location, final.hit_color);
|
||||
final.hit_location = result.getLocation();
|
||||
}
|
||||
|
||||
return final;
|
||||
}
|
||||
|
||||
RayCastingResult VegetationRenderer::getResult(const SpaceSegment &segment, bool only_hit)
|
||||
{
|
||||
// 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))
|
||||
{
|
||||
return it.getResult();
|
||||
}
|
||||
else
|
||||
{
|
||||
return RayCastingResult();
|
||||
}
|
||||
}
|
||||
|
||||
bool VegetationRenderer::applyLightFilter(LightComponent &light, const Vector3 &at)
|
||||
{
|
||||
// Get segment to iterate
|
||||
SpaceSegment segment(at, at.add(light.direction.scale(-1.0 * parent->render_quality)));
|
||||
if (getResult(segment, true).hit)
|
||||
{
|
||||
light.color = COLOR_BLACK;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
37
src/render/software/VegetationRenderer.h
Normal file
37
src/render/software/VegetationRenderer.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#ifndef VEGETATIONRENDERER_H
|
||||
#define VEGETATIONRENDERER_H
|
||||
|
||||
#include "software_global.h"
|
||||
|
||||
#include "LightFilter.h"
|
||||
|
||||
namespace paysages {
|
||||
namespace software {
|
||||
|
||||
class SOFTWARESHARED_EXPORT VegetationRenderer: public LightFilter
|
||||
{
|
||||
public:
|
||||
VegetationRenderer(SoftwareRenderer *parent);
|
||||
|
||||
inline SoftwareRenderer *getParent() const {return parent;}
|
||||
|
||||
/**
|
||||
* Perform ray casting on a single instance.
|
||||
*/
|
||||
RayCastingResult renderInstance(const SpaceSegment &segment, const VegetationInstance &instance, bool only_hit=false);
|
||||
|
||||
/**
|
||||
* Perform ray casting on a given segment.
|
||||
*/
|
||||
RayCastingResult getResult(const SpaceSegment &segment, bool only_hit=false);
|
||||
|
||||
virtual bool applyLightFilter(LightComponent &light, const Vector3 &at) override;
|
||||
|
||||
private:
|
||||
SoftwareRenderer *parent;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // VEGETATIONRENDERER_H
|
12
src/render/software/VegetationResult.cpp
Normal file
12
src/render/software/VegetationResult.cpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include "VegetationResult.h"
|
||||
|
||||
VegetationResult::VegetationResult(bool hit):
|
||||
hit(hit)
|
||||
{
|
||||
}
|
||||
|
||||
VegetationResult::VegetationResult(const Vector3 &location, const Vector3 &normal, const SurfaceMaterial &material):
|
||||
location(location), normal(normal), material(material)
|
||||
{
|
||||
hit = true;
|
||||
}
|
36
src/render/software/VegetationResult.h
Normal file
36
src/render/software/VegetationResult.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
#ifndef VEGETATIONRESULT_H
|
||||
#define VEGETATIONRESULT_H
|
||||
|
||||
#include "software_global.h"
|
||||
|
||||
#include "Vector3.h"
|
||||
#include "SurfaceMaterial.h"
|
||||
|
||||
namespace paysages {
|
||||
namespace software {
|
||||
|
||||
/**
|
||||
* Result of a vegetation lookup.
|
||||
*/
|
||||
class SOFTWARESHARED_EXPORT VegetationResult
|
||||
{
|
||||
public:
|
||||
VegetationResult(bool hit=false);
|
||||
VegetationResult(const Vector3 &location, const Vector3 &normal, const SurfaceMaterial &material);
|
||||
|
||||
inline bool isHit() const {return hit;}
|
||||
inline const Vector3 &getLocation() const {return location;}
|
||||
inline const Vector3 &getNormal() const {return normal;}
|
||||
inline const SurfaceMaterial &getMaterial() const {return material;}
|
||||
|
||||
private:
|
||||
bool hit;
|
||||
Vector3 location;
|
||||
Vector3 normal;
|
||||
SurfaceMaterial material;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // VEGETATIONRESULT_H
|
|
@ -37,6 +37,7 @@ SOURCES += SoftwareRenderer.cpp \
|
|||
RayCastingManager.cpp \
|
||||
NightSky.cpp \
|
||||
TerrainRayWalker.cpp \
|
||||
VegetationModelRenderer.cpp \
|
||||
Canvas.cpp \
|
||||
CanvasPortion.cpp \
|
||||
CanvasPixel.cpp \
|
||||
|
@ -55,7 +56,11 @@ SOURCES += SoftwareRenderer.cpp \
|
|||
LightSource.cpp \
|
||||
RayCastingResult.cpp \
|
||||
GodRaysSampler.cpp \
|
||||
GodRaysResult.cpp
|
||||
GodRaysResult.cpp \
|
||||
VegetationRasterizer.cpp \
|
||||
VegetationRenderer.cpp \
|
||||
VegetationInstance.cpp \
|
||||
VegetationResult.cpp
|
||||
|
||||
HEADERS += SoftwareRenderer.h\
|
||||
software_global.h \
|
||||
|
@ -82,6 +87,7 @@ HEADERS += SoftwareRenderer.h\
|
|||
RayCastingManager.h \
|
||||
NightSky.h \
|
||||
TerrainRayWalker.h \
|
||||
VegetationModelRenderer.h \
|
||||
Canvas.h \
|
||||
CanvasPortion.h \
|
||||
CanvasPixel.h \
|
||||
|
@ -100,7 +106,11 @@ HEADERS += SoftwareRenderer.h\
|
|||
LightSource.h \
|
||||
RayCastingResult.h \
|
||||
GodRaysSampler.h \
|
||||
GodRaysResult.h
|
||||
GodRaysResult.h \
|
||||
VegetationRasterizer.h \
|
||||
VegetationRenderer.h \
|
||||
VegetationInstance.h \
|
||||
VegetationResult.h
|
||||
|
||||
unix:!symbian {
|
||||
maemo5 {
|
||||
|
|
|
@ -54,6 +54,10 @@ namespace software {
|
|||
|
||||
class GodRaysSampler;
|
||||
class GodRaysResult;
|
||||
class VegetationResult;
|
||||
class VegetationInstance;
|
||||
class VegetationRenderer;
|
||||
class VegetationModelRenderer;
|
||||
|
||||
class Canvas;
|
||||
class CanvasPortion;
|
||||
|
|
Loading…
Reference in a new issue