TerrainDefinition and Scenery refactoring

This commit is contained in:
Michaël Lemaire 2013-11-17 22:36:18 +01:00
parent fa5c0041af
commit 9e6838f733
57 changed files with 1545 additions and 1341 deletions

View file

@ -1,5 +1,13 @@
#include "Interpolation.h"
Interpolation::Interpolation()
double Interpolation::bicubic(double stencil[16], double x, double y)
{
double buf_cubic_y[4];
buf_cubic_y[0] = Interpolation::cubic(stencil, x);
buf_cubic_y[1] = Interpolation::cubic(stencil + 4, x);
buf_cubic_y[2] = Interpolation::cubic(stencil + 8, x);
buf_cubic_y[3] = Interpolation::cubic(stencil + 12, x);
return Interpolation::cubic(buf_cubic_y, y);
}

View file

@ -6,15 +6,14 @@
namespace paysages {
namespace basics {
class Interpolation
class BASICSSHARED_EXPORT Interpolation
{
public:
Interpolation();
static inline double cubic(double p[4], double x)
{
return p[1] + 0.5 * x * (p[2] - p[0] + x * (2.0 * p[0] - 5.0 * p[1] + 4.0 * p[2] - p[3] + x * (3.0 * (p[1] - p[2]) + p[3] - p[0])));
}
static double bicubic(double stencil[16], double x, double y);
};
}

View file

@ -29,6 +29,18 @@ void BaseDefinition::setName(QString name)
this->name = name;
}
Scenery* BaseDefinition::getScenery()
{
if (parent)
{
return parent->getScenery();
}
else
{
return NULL;
}
}
void BaseDefinition::save(PackStream* stream) const
{
stream->write(name);

View file

@ -28,6 +28,8 @@ public:
inline const QString& getName() const {return name;}
virtual void setName(QString name);
virtual Scenery* getScenery();
inline const BaseDefinition* getParent() const {return parent;}
inline const BaseDefinition* getRoot() const {return root;}

144
src/definition/Scenery.cpp Normal file
View file

@ -0,0 +1,144 @@
#include "Scenery.h"
#include <ctime>
#include "NoiseGenerator.h"
#include "PackStream.h"
#include "AtmosphereDefinition.h"
#include "CameraDefinition.h"
#include "CloudsDefinition.h"
#include "TerrainDefinition.h"
#include "TexturesDefinition.h"
#include "WaterDefinition.h"
Scenery::Scenery():
BaseDefinition(NULL)
{
addChild(atmosphere = new AtmosphereDefinition(this));
addChild(camera = new CameraDefinition);
addChild(clouds = new CloudsDefinition(this));
addChild(terrain = new TerrainDefinition(this));
addChild(textures = new TexturesDefinition(this));
addChild(water = new WaterDefinition(this));
}
void Scenery::save(PackStream* stream) const
{
BaseDefinition::save(stream);
noiseSave(stream);
}
void Scenery::load(PackStream* stream)
{
BaseDefinition::load(stream);
noiseLoad(stream);
validate();
}
void Scenery::validate()
{
BaseDefinition::validate();
checkCameraAboveGround();
}
Scenery* Scenery::getScenery()
{
return this;
}
void Scenery::autoPreset(int seed)
{
if (!seed)
{
seed = time(NULL);
}
srand(seed);
terrain->applyPreset(TerrainDefinition::TERRAIN_PRESET_STANDARD);
textures->applyPreset(TexturesDefinition::TEXTURES_PRESET_FULL);
atmosphere->applyPreset(AtmosphereDefinition::ATMOSPHERE_PRESET_CLEAR_DAY);
water->applyPreset(WaterDefinition::WATER_PRESET_LAKE);
clouds->applyPreset(CloudsDefinition::CLOUDS_PRESET_PARTLY_CLOUDY);
camera->setLocation(VECTOR_ZERO);
camera->setTarget(VECTOR_NORTH);
validate();
}
void Scenery::setAtmosphere(AtmosphereDefinition* atmosphere)
{
atmosphere->copy(this->atmosphere);
}
void Scenery::getAtmosphere(AtmosphereDefinition* atmosphere)
{
this->atmosphere->copy(atmosphere);
}
void Scenery::setCamera(CameraDefinition* camera)
{
camera->copy(this->camera);
checkCameraAboveGround();
}
void Scenery::getCamera(CameraDefinition* camera)
{
this->camera->copy(camera);
}
void Scenery::setClouds(CloudsDefinition* clouds)
{
clouds->copy(this->clouds);
}
void Scenery::getClouds(CloudsDefinition* clouds)
{
this->clouds->copy(clouds);
}
void Scenery::setTerrain(TerrainDefinition* terrain)
{
terrain->copy(this->terrain);
}
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::setWater(WaterDefinition* water)
{
water->copy(this->water);
}
void Scenery::getWater(WaterDefinition* water)
{
this->water->copy(water);
}
void Scenery::checkCameraAboveGround()
{
Vector3 camera_location = camera->getLocation();
double terrain_height = terrain->getInterpolatedHeight(camera_location.x, camera_location.z, 1, 1) + 0.5;
double water_height = terrain->getWaterHeight() + 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;
camera->setLocation(camera_location.add(Vector3(0.0, diff, 0.0)));
}
}

View file

@ -1,34 +1,28 @@
#ifndef SCENERY_H
#define SCENERY_H
#include "rendering_global.h"
#include "definition_global.h"
#include "BaseDefinition.h"
class TerrainDefinition;
class Renderer;
typedef void (*SceneryCustomDataCallback)(PackStream* stream, void* data);
namespace paysages {
namespace definition {
/**
* @brief Global scenery management
*
* This class contains the whole scenery definition.
*/
class RENDERINGSHARED_EXPORT Scenery: private BaseDefinition
class DEFINITIONSHARED_EXPORT Scenery: public BaseDefinition
{
public:
Scenery();
virtual ~Scenery();
static Scenery* getCurrent();
void setCustomSaveCallbacks(SceneryCustomDataCallback callback_save, SceneryCustomDataCallback callback_load, void* data);
virtual void save(PackStream* stream) const override;
virtual void load(PackStream* stream) override;
virtual void validate() override;
virtual Scenery* getScenery() override;
void autoPreset(int seed);
@ -56,8 +50,6 @@ public:
inline WaterDefinition* getWater() const {return water;}
void getWater(WaterDefinition* water);
void bindToRenderer(Renderer* renderer);
void checkCameraAboveGround();
private:
@ -67,14 +59,9 @@ private:
TerrainDefinition* terrain;
TexturesDefinition* textures;
WaterDefinition* water;
SceneryCustomDataCallback _custom_save;
SceneryCustomDataCallback _custom_load;
void* _custom_data;
};
// Transitional C-API
RENDERINGSHARED_EXPORT void sceneryRenderFirstPass(Renderer* renderer);
}
}
#endif // SCENERY_H

View file

@ -0,0 +1,162 @@
#include "TerrainDefinition.h"
#include "TerrainHeightMap.h"
#include "NoiseGenerator.h"
#include "PackStream.h"
TerrainDefinition::TerrainDefinition(BaseDefinition* parent):
BaseDefinition(parent)
{
height = 1.0;
scaling = 1.0;
shadow_smoothing = 0.0;
height_map = new TerrainHeightMap(this);
addChild(height_map);
water_height = -0.3;
_height_noise = new NoiseGenerator;
}
TerrainDefinition::~TerrainDefinition()
{
delete _height_noise;
}
void TerrainDefinition::validate()
{
_height_noise->validate();
if (height < 1.0)
{
height = 1.0;
}
/* Get minimal and maximal height */
_height_noise->getRange(&_min_height, &_max_height);
_min_height *= height * scaling;
_max_height *= height * scaling;
/* TODO Alter with heightmap min/max */
}
void TerrainDefinition::copy(BaseDefinition* _destination) const
{
TerrainDefinition* destination = (TerrainDefinition*)_destination;
destination->height = height;
destination->scaling = scaling;
destination->shadow_smoothing = shadow_smoothing;
height_map->copy(destination->height_map);
destination->water_height = water_height;
_height_noise->copy(destination->_height_noise);
destination->validate();
}
void TerrainDefinition::save(PackStream* stream) const
{
BaseDefinition::save(stream);
stream->write(&height);
stream->write(&scaling);
stream->write(&shadow_smoothing);
stream->write(&water_height);
_height_noise->save(stream);
}
void TerrainDefinition::load(PackStream* stream)
{
BaseDefinition::load(stream);
stream->read(&height);
stream->read(&scaling);
stream->read(&shadow_smoothing);
stream->read(&water_height);
_height_noise->load(stream);
validate();
}
double TerrainDefinition::getGridHeight(int x, int z, int with_painting)
{
double h;
if (!with_painting || !height_map->getGridHeight(x, z, &h))
{
h = _height_noise->get2DTotal((double)x, (double)z);
}
return h;
}
double TerrainDefinition::getInterpolatedHeight(double x, double z, int scaled, int with_painting)
{
double h;
x /= scaling;
z /= scaling;
if (!with_painting || !height_map->getInterpolatedHeight(x, z, &h))
{
h = _height_noise->get2DTotal(x, z);
}
if (scaled)
{
return h * height * scaling;
}
else
{
return h;
}
}
HeightInfo TerrainDefinition::getHeightInfo()
{
HeightInfo result;
result.min_height = _min_height;
result.max_height = _max_height;
/* TODO This is duplicated in ter_render.c (_realGetWaterHeight) */
result.base_height = water_height * height * scaling;
return result;
}
double TerrainDefinition::getWaterHeight()
{
return water_height * height * scaling;
}
unsigned long TerrainDefinition::getMemoryStats()
{
return height_map->getMemoryStats();
}
void TerrainDefinition::applyPreset(TerrainPreset preset)
{
int resolution = 8;
switch (preset)
{
case TERRAIN_PRESET_STANDARD:
_height_noise->randomizeOffsets();
_height_noise->clearLevels();
_height_noise->addLevelSimple(pow(2.0, resolution + 1), -1.0, 1.0);
_height_noise->addLevelsSimple(resolution - 2, pow(2.0, resolution - 1), -0.7, 0.7, 0.5);
_height_noise->normalizeAmplitude(-1.0, 1.0, 0);
_height_noise->setFunctionParams(NOISE_FUNCTION_SIMPLEX, 0.0, 0.0);
scaling = 1.0;
height = 30.0;
shadow_smoothing = 0.03;
break;
default:
;
}
height_map->clearPainting();
validate();
}

View file

@ -0,0 +1,61 @@
#ifndef TERRAINDEFINITION_H
#define TERRAINDEFINITION_H
#include "definition_global.h"
#include "BaseDefinition.h"
namespace paysages {
namespace definition {
typedef struct
{
double min_height;
double max_height;
double base_height;
} HeightInfo;
class DEFINITIONSHARED_EXPORT TerrainDefinition : public BaseDefinition
{
public:
TerrainDefinition(BaseDefinition* parent);
virtual ~TerrainDefinition();
virtual void save(PackStream* stream) const override;
virtual void load(PackStream* stream) override;
virtual void copy(BaseDefinition* destination) const override;
virtual void validate() override;
double getGridHeight(int x, int z, int with_painting);
double getInterpolatedHeight(double x, double z, int scaled, int with_painting);
unsigned long getMemoryStats();
HeightInfo getHeightInfo();
double getWaterHeight();
public:
typedef enum
{
TERRAIN_PRESET_STANDARD
} TerrainPreset;
void applyPreset(TerrainPreset preset);
public:
double height;
double scaling;
double shadow_smoothing;
TerrainHeightMap* height_map;
double water_height;
double _detail;
NoiseGenerator* _height_noise;
double _min_height;
double _max_height;
};
}
}
#endif // TERRAINDEFINITION_H

View file

@ -0,0 +1,484 @@
#include "TerrainHeightMap.h"
#include "PackStream.h"
#include "Memory.h"
#include "TerrainDefinition.h"
#include "TerrainHeightMapBrush.h"
#include "Interpolation.h"
#include "NoiseGenerator.h"
#include <cassert>
typedef struct
{
int xstart;
int xend;
double* height;
} HeightMapPixelGroup;
typedef struct
{
int z;
int pixel_groups_count;
HeightMapPixelGroup* pixel_groups;
} HeightMapRow;
namespace paysages {
namespace definition {
class TerrainHeightMapData
{
public:
int memsize;
int rows_count;
HeightMapRow* rows;
};
}
}
static void _initData(TerrainHeightMapData* data)
{
data->rows_count = 0;
data->rows = new HeightMapRow[1];
data->memsize = 0;
}
static void _clearData(TerrainHeightMapData* data)
{
int i, j;
for (i = 0; i < data->rows_count; i++)
{
for (j = 0; j < data->rows[i].pixel_groups_count; j++)
{
free(data->rows[i].pixel_groups[j].height);
}
free(data->rows[i].pixel_groups);
}
data->rows_count = 0;
delete[] data->rows;
data->rows = new HeightMapRow[1];
data->memsize = 0;
}
static void _deleteData(TerrainHeightMapData* data)
{
_clearData(data);
delete[] data->rows;
delete data;
}
static void _copyData(TerrainHeightMapData* source, TerrainHeightMapData* destination)
{
int i, j, n;
size_t size;
_clearData(destination);
destination->rows_count = source->rows_count;
if (destination->rows_count > 0)
{
size = sizeof(HeightMapRow) * destination->rows_count;
destination->rows = (HeightMapRow*)realloc(destination->rows, size);
destination->memsize += size;
for (i = 0; i < destination->rows_count; i++)
{
destination->rows[i].z = source->rows[i].z;
destination->rows[i].pixel_groups_count = source->rows[i].pixel_groups_count;
size = sizeof(HeightMapPixelGroup) * destination->rows[i].pixel_groups_count;
destination->rows[i].pixel_groups = (HeightMapPixelGroup*)malloc(size);
destination->memsize += size;
for (j = 0; j < destination->rows[i].pixel_groups_count; j++)
{
destination->rows[i].pixel_groups[j].xstart = source->rows[i].pixel_groups[j].xstart;
destination->rows[i].pixel_groups[j].xend = source->rows[i].pixel_groups[j].xend;
n = destination->rows[i].pixel_groups[j].xend - destination->rows[i].pixel_groups[j].xstart + 1;
size = sizeof(double) * n;
destination->rows[i].pixel_groups[j].height = (double*)malloc(size);
destination->memsize += size;
memcpy(destination->rows[i].pixel_groups[j].height, source->rows[i].pixel_groups[j].height, size);
}
}
}
}
static void _saveData(PackStream* stream, TerrainHeightMapData* data)
{
int i, j, k;
stream->write(&data->rows_count);
for (i = 0; i < data->rows_count; i++)
{
stream->write(&data->rows[i].z);
stream->write(&data->rows[i].pixel_groups_count);
for (j = 0; j < data->rows[i].pixel_groups_count; j++)
{
stream->write(&data->rows[i].pixel_groups[j].xstart);
stream->write(&data->rows[i].pixel_groups[j].xend);
for (k = 0; k < data->rows[i].pixel_groups[j].xend - data->rows[i].pixel_groups[j].xstart; k++)
{
stream->write(&data->rows[i].pixel_groups[j].height[k]);
}
}
}
}
static void _loadData(PackStream* stream, TerrainHeightMapData* data)
{
int i, j, k, n;
size_t size;
_clearData(data);
stream->read(&data->rows_count);
if (data->rows_count > 0)
{
size = sizeof(HeightMapRow) * data->rows_count;
data->rows = (HeightMapRow*)realloc(data->rows, size);
data->memsize += size;
for (i = 0; i < data->rows_count; i++)
{
stream->read(&data->rows[i].z);
stream->read(&data->rows[i].pixel_groups_count);
size = sizeof(HeightMapPixelGroup) * data->rows[i].pixel_groups_count;
data->rows[i].pixel_groups = (HeightMapPixelGroup*)malloc(size);
data->memsize += size;
for (j = 0; j < data->rows[i].pixel_groups_count; j++)
{
stream->read(&data->rows[i].pixel_groups[j].xstart);
stream->read(&data->rows[i].pixel_groups[j].xend);
n = data->rows[i].pixel_groups[j].xend - data->rows[i].pixel_groups[j].xstart;
size = sizeof(double) * n;
data->rows[i].pixel_groups[j].height = (double*)malloc(size);
data->memsize += size;
for (k = 0; k < n; k++)
{
stream->read(&data->rows[i].pixel_groups[j].height[k]);
}
}
}
}
}
/*
* Get a pointer to the data in a heightmap, to a certain location.
* If the location is not already in the heightmap, it is initialized with the terrain height.
* This method will grow the heightmap as necessary (if 'grow' is set to false, NULL will be returned on missing pixels).
*/
inline double* TerrainHeightMap::getDataPointer(TerrainHeightMapData* data, int x, int z, TerrainHeightMapData* fallback, TerrainDefinition* terrain, int grow)
{
int i;
/* Find row */
/* TODO Dichotomic search */
HeightMapRow* row;
i = 0;
while (i < data->rows_count && data->rows[i].z < z)
{
i++;
}
if (i < data->rows_count && data->rows[i].z == z)
{
row = data->rows + i;
}
else if (grow)
{
row = (HeightMapRow*)Memory::naiveArrayInsert((void**)&data->rows, sizeof(HeightMapRow), data->rows_count, i);
row->z = z;
row->pixel_groups_count = 0;
row->pixel_groups = (HeightMapPixelGroup*)malloc(1);
data->rows_count++;
data->memsize += sizeof(HeightMapRow);
}
else
{
return NULL;
}
#ifndef NDEBUG
/* Check rows */
for (i = 1; i < data->rows_count; i++)
{
assert(data->rows[i].z > data->rows[i - 1].z);
}
#endif
/* Find pixel group */
HeightMapPixelGroup* pixel_group = NULL;
for (i = 0; i < row->pixel_groups_count; i++)
{
if (x < row->pixel_groups[i].xstart - 1)
{
break;
}
else if (x <= row->pixel_groups[i].xend + 1)
{
if (x == row->pixel_groups[i].xend + 1 && i < row->pixel_groups_count - 1 && x == row->pixel_groups[i + 1].xstart)
{
/* Choose next group if it already includes the pixel */
i++;
}
pixel_group = row->pixel_groups + i;
break;
}
}
/* Alter pixel group */
double* pixel;
int added = 1;
if (!pixel_group)
{
if (!grow)
{
return NULL;
}
/* Create the pixel group with one pixel */
pixel_group = (HeightMapPixelGroup*)Memory::naiveArrayInsert((void**)&row->pixel_groups, sizeof(HeightMapPixelGroup), row->pixel_groups_count, i);
pixel_group->xstart = x;
pixel_group->xend = x;
pixel_group->height = (double*)malloc(sizeof(double));
pixel = pixel_group->height;
row->pixel_groups_count++;
data->memsize += sizeof(HeightMapPixelGroup) + sizeof(double);
}
else if (x == pixel_group->xstart - 1)
{
if (!grow)
{
return NULL;
}
/* Extend the rowgroup at start */
pixel_group->xstart--;
pixel = (double*)Memory::naiveArrayInsert((void**)&pixel_group->height, sizeof(double), pixel_group->xend - pixel_group->xstart, 0);
data->memsize += sizeof(double);
}
else if (x == pixel_group->xend + 1)
{
if (!grow)
{
return NULL;
}
/* Extend the rowgroup at end */
pixel_group->xend++;
pixel = (double*)Memory::naiveArrayInsert((void**)&pixel_group->height, sizeof(double), pixel_group->xend - pixel_group->xstart, pixel_group->xend - pixel_group->xstart);
data->memsize += sizeof(double);
}
else
{
assert(x >= pixel_group->xstart);
assert(x <= pixel_group->xend);
pixel = pixel_group->height + x - pixel_group->xstart;
added = 0;
}
#ifndef NDEBUG
/* Check pixel groups */
for (i = 0; i < row->pixel_groups_count; i++)
{
if (i > 0)
{
assert(row->pixel_groups[i].xstart > row->pixel_groups[i - 1].xend);
}
if (i < row->pixel_groups_count - 1)
{
assert(row->pixel_groups[i].xend < row->pixel_groups[i + 1].xstart);
}
assert(row->pixel_groups[i].xend >= row->pixel_groups[i].xstart);
}
#endif
/* Reset pixel if it had been added */
if (added && (terrain || fallback))
{
if (fallback)
{
double* dpointer = getDataPointer(fallback, x, z, NULL, terrain, 0);
if (dpointer)
{
*pixel = *dpointer;
}
else if (terrain)
{
*pixel = terrain->getGridHeight(x, z, 0);
}
}
else if (terrain)
{
*pixel = terrain->getGridHeight(x, z, 0);
}
}
return pixel;
}
TerrainHeightMap::TerrainHeightMap(TerrainDefinition* terrain):
BaseDefinition(terrain), terrain(terrain)
{
merged_data = new TerrainHeightMapData;
brush_data = new TerrainHeightMapData;
_initData(merged_data);
_initData(brush_data);
}
TerrainHeightMap::~TerrainHeightMap()
{
_deleteData(merged_data);
_deleteData(brush_data);
}
void TerrainHeightMap::copy(BaseDefinition* _destination) const
{
TerrainHeightMap* destination = (TerrainHeightMap*)_destination;
destination->terrain = terrain;
_copyData(merged_data, destination->merged_data);
_clearData(destination->brush_data);
}
void TerrainHeightMap::save(PackStream* stream) const
{
_saveData(stream, merged_data);
}
void TerrainHeightMap::load(PackStream* stream)
{
_loadData(stream, merged_data);
_clearData(brush_data);
}
int TerrainHeightMap::getGridHeight(int x, int z, double* result)
{
double* dpointer;
dpointer = getDataPointer(brush_data, x, z, NULL, NULL, 0);
if (dpointer)
{
*result = *dpointer;
return 1;
}
else
{
dpointer = getDataPointer(merged_data, x, z, NULL, NULL, 0);
if (dpointer)
{
*result = *dpointer;
return 1;
}
else
{
return 0;
}
}
}
int TerrainHeightMap::getInterpolatedHeight(double x, double z, double* result)
{
int ix, iz;
int xlow;
int zlow;
xlow = floor(x);
zlow = floor(z);
int hit = 0;
for (ix = xlow - 1; ix <= xlow + 2 && !hit; ix++)
{
for (iz = zlow - 1; iz <= zlow + 2 && !hit; iz++)
{
if (getDataPointer(brush_data, x, z, NULL, NULL, 0) || getDataPointer(merged_data, x, z, NULL, NULL, 0))
{
hit = 1;
}
}
}
if (hit && result)
{
double stencil[16];
double value;
for (ix = xlow - 1; ix <= xlow + 2; ix++)
{
for (iz = zlow - 1; iz <= zlow + 2; iz++)
{
if (!getGridHeight(ix, iz, &value))
{
value = terrain->getGridHeight(ix, iz, 0);
}
stencil[(iz - (zlow - 1)) * 4 + ix - (xlow - 1)] = value;
}
}
*result = Interpolation::bicubic(stencil, x - (double)xlow, z - (double)zlow);
}
return hit;
}
unsigned long TerrainHeightMap::getMemoryStats() const
{
return merged_data->memsize + brush_data->memsize;
}
bool TerrainHeightMap::isPainted(int x, int z)
{
return getDataPointer(brush_data, x, z, NULL, NULL, 0) || getDataPointer(merged_data, x, z, NULL, NULL, 0);
}
void TerrainHeightMap::clearPainting()
{
_clearData(merged_data);
_clearData(brush_data);
}
void TerrainHeightMap::brushElevation(const TerrainHeightMapBrush &brush, double value)
{
TerrainHeightMapBrushElevation sbrush(brush);
sbrush.apply(this, value);
}
void TerrainHeightMap::brushFlatten(const TerrainHeightMapBrush &brush, double height, double force)
{
TerrainHeightMapBrushFlatten sbrush(brush, height);
sbrush.apply(this, force);
}
void TerrainHeightMap::brushSmooth(const TerrainHeightMapBrush &brush, double value)
{
TerrainHeightMapBrushSmooth sbrush(brush);
sbrush.apply(this, value);
}
void TerrainHeightMap::brushAddNoise(const TerrainHeightMapBrush &brush, NoiseGenerator* generator, double value)
{
TerrainHeightMapBrushAddNoise sbrush(brush, generator);
sbrush.apply(this, value);
}
void TerrainHeightMap::brushReset(const TerrainHeightMapBrush &brush, double value)
{
TerrainHeightMapBrushReset sbrush(brush);
sbrush.apply(this, value);
}
void TerrainHeightMap::endBrushStroke()
{
int i, j, k;
TerrainHeightMapData* data = brush_data;
for (i = 0; i < data->rows_count; i++)
{
for (j = 0; j < data->rows[i].pixel_groups_count; j++)
{
for (k = 0; k < data->rows[i].pixel_groups[j].xend - data->rows[i].pixel_groups[j].xstart + 1; k++)
{
double* dpointer = getDataPointer(merged_data, data->rows[i].pixel_groups[j].xstart + k, data->rows[i].z, NULL, NULL, 1);
*dpointer = data->rows[i].pixel_groups[j].height[k];
}
}
}
_clearData(brush_data);
}

View file

@ -0,0 +1,54 @@
#ifndef TERRAINHEIGHTMAP_H
#define TERRAINHEIGHTMAP_H
#include "definition_global.h"
#include "BaseDefinition.h"
namespace paysages {
namespace definition {
class TerrainHeightMapData;
class DEFINITIONSHARED_EXPORT TerrainHeightMap : public BaseDefinition
{
public:
TerrainHeightMap(TerrainDefinition* terrain);
virtual ~TerrainHeightMap();
virtual void copy(BaseDefinition* destination) const override;
virtual void save(PackStream* stream) const override;
virtual void load(PackStream* stream) override;
inline TerrainDefinition* getTerrain() const {return terrain;}
int getInterpolatedHeight(double x, double z, double* result);
int getGridHeight(int x, int z, double* result);
bool isPainted(int x, int z);
unsigned long getMemoryStats() const;
void clearPainting();
void brushElevation(const TerrainHeightMapBrush &brush, double value);
void brushSmooth(const TerrainHeightMapBrush &brush, double value);
void brushAddNoise(const TerrainHeightMapBrush &brush, NoiseGenerator* generator, double value);
void brushReset(const TerrainHeightMapBrush &brush, double value);
void brushFlatten(const TerrainHeightMapBrush &brush, double height, double force);
void endBrushStroke();
friend class TerrainHeightMapBrush;
friend class TerrainHeightMapBrushSmooth;
friend class TerrainHeightMapBrushReset;
protected:
double* getDataPointer(TerrainHeightMapData* data, int x, int z, TerrainHeightMapData* fallback, TerrainDefinition* terrain, int grow);
private:
TerrainDefinition* terrain;
TerrainHeightMapData* merged_data;
TerrainHeightMapData* brush_data;
};
}
}
#endif // TERRAINHEIGHTMAP_H

View file

@ -0,0 +1,119 @@
#include "TerrainHeightMapBrush.h"
#include "TerrainDefinition.h"
#include "TerrainHeightMap.h"
#include "NoiseGenerator.h"
typedef struct
{
int xstart;
int xend;
int xsize;
int zstart;
int zend;
int zsize;
} IntegerRect;
static inline IntegerRect _getBrushRect(TerrainHeightMapBrush* brush)
{
IntegerRect result;
double s = brush->smoothed_size + brush->hard_radius;
result.xstart = (int)floor(brush->relative_x - s);
result.xend = (int)ceil(brush->relative_x + s);
result.zstart = (int)floor(brush->relative_z - s);
result.zend = (int)ceil(brush->relative_z + s);
result.xsize = result.xend - result.xstart + 1;
result.zsize = result.zend - result.zstart + 1;
return result;
}
static inline int _isInRect(const IntegerRect &rect, int x, int z)
{
return (x >= rect.xstart && x <= rect.xend && z >= rect.zstart && z <= rect.zend);
}
void TerrainHeightMapBrush::apply(TerrainHeightMap* heightmap, double force)
{
IntegerRect brush_rect = _getBrushRect(this);
int x, z;
double dx, dz, distance, influence;
force /= heightmap->terrain->height;
for (x = brush_rect.xstart; x <= brush_rect.xend; x++)
{
dx = (double)x;
for (z = brush_rect.zstart; z <= brush_rect.zend; z++)
{
dz = (double)z;
distance = sqrt((relative_x - dx) * (relative_x - dx) + (relative_z - dz) * (relative_z - dz));
if (distance > hard_radius)
{
if (distance <= hard_radius + smoothed_size)
{
influence = (1.0 - (distance - hard_radius) / smoothed_size);
}
else
{
continue;
}
}
else
{
influence = 1.0;
}
double* dpointer = heightmap->getDataPointer(heightmap->brush_data, x, z, heightmap->merged_data, heightmap->terrain, 1);
*dpointer = getBrushValue(heightmap, dx, dz, *dpointer, influence, force);
}
}
}
double TerrainHeightMapBrush::getBrushValue(TerrainHeightMap*, double, double, double basevalue, double, double) const
{
return basevalue;
}
double TerrainHeightMapBrushElevation::getBrushValue(TerrainHeightMap*, double, double, double basevalue, double influence, double force) const
{
return basevalue + influence * force;
}
double TerrainHeightMapBrushSmooth::getBrushValue(TerrainHeightMap* heightmap, double x, double z, double basevalue, double influence, double force) const
{
TerrainDefinition* terrain = heightmap->terrain;
double ideal, factor;
ideal = terrain->getInterpolatedHeight((x + total_radius * 0.5) * terrain->scaling, z * terrain->scaling, 0, 1);
ideal += terrain->getInterpolatedHeight((x - total_radius * 0.5) * terrain->scaling, z * terrain->scaling, 0, 1);
ideal += terrain->getInterpolatedHeight(x * terrain->scaling, (z - total_radius * 0.5) * terrain->scaling, 0, 1);
ideal += terrain->getInterpolatedHeight(x * terrain->scaling, (z + total_radius * 0.5) * terrain->scaling, 0, 1);
ideal /= 4.0;
factor = influence * force;
if (factor > 1.0)
{
factor = 0.0;
}
return basevalue + (ideal - basevalue) * factor;
}
double TerrainHeightMapBrushAddNoise::getBrushValue(TerrainHeightMap*, double x, double z, double basevalue, double influence, double force) const
{
return basevalue + generator->get2DTotal(x / total_radius, z / total_radius) * influence * force * total_radius;
}
double TerrainHeightMapBrushReset::getBrushValue(TerrainHeightMap* heightmap, double x, double z, double basevalue, double influence, double force) const
{
TerrainDefinition* terrain = heightmap->terrain;
double ideal = terrain->getInterpolatedHeight(x * terrain->scaling, z * terrain->scaling, 0, 0);
return basevalue + (ideal - basevalue) * influence * force;
}
double TerrainHeightMapBrushFlatten::getBrushValue(TerrainHeightMap*, double, double, double basevalue, double influence, double force) const
{
double ideal = height;
return basevalue + (ideal - basevalue) * influence * force;
}

View file

@ -0,0 +1,78 @@
#ifndef TERRAINHEIGHTMAPBRUSH_H
#define TERRAINHEIGHTMAPBRUSH_H
#include "definition_global.h"
namespace paysages {
namespace definition {
class DEFINITIONSHARED_EXPORT TerrainHeightMapBrush
{
public:
TerrainHeightMapBrush() {}
TerrainHeightMapBrush(double relative_x, double relative_z, double hard_radius, double smoothed_size, double total_radius):
relative_x(relative_x), relative_z(relative_z), hard_radius(hard_radius), smoothed_size(smoothed_size), total_radius(total_radius) {}
void apply(TerrainHeightMap* heightmap, double force);
protected:
virtual double getBrushValue(TerrainHeightMap* heightmap, double x, double z, double basevalue, double influence, double force) const;
public:
double relative_x;
double relative_z;
double hard_radius;
double smoothed_size;
double total_radius;
};
class DEFINITIONSHARED_EXPORT TerrainHeightMapBrushElevation: public TerrainHeightMapBrush
{
public:
TerrainHeightMapBrushElevation(const TerrainHeightMapBrush& brush) : TerrainHeightMapBrush(brush) {}
protected:
double getBrushValue(TerrainHeightMap* heightmap, double x, double z, double basevalue, double influence, double force) const override;
};
class DEFINITIONSHARED_EXPORT TerrainHeightMapBrushSmooth: public TerrainHeightMapBrush
{
public:
TerrainHeightMapBrushSmooth(const TerrainHeightMapBrush& brush) : TerrainHeightMapBrush(brush) {}
protected:
double getBrushValue(TerrainHeightMap* heightmap, double x, double z, double basevalue, double influence, double force) const override;
};
class DEFINITIONSHARED_EXPORT TerrainHeightMapBrushAddNoise: public TerrainHeightMapBrush
{
public:
TerrainHeightMapBrushAddNoise(NoiseGenerator* generator) : generator(generator) {}
TerrainHeightMapBrushAddNoise(const TerrainHeightMapBrush& brush, NoiseGenerator* generator) : TerrainHeightMapBrush(brush), generator(generator) {}
protected:
double getBrushValue(TerrainHeightMap* heightmap, double x, double z, double basevalue, double influence, double force) const override;
private:
NoiseGenerator* generator;
};
class DEFINITIONSHARED_EXPORT TerrainHeightMapBrushReset: public TerrainHeightMapBrush
{
public:
TerrainHeightMapBrushReset(const TerrainHeightMapBrush& brush) : TerrainHeightMapBrush(brush) {}
protected:
double getBrushValue(TerrainHeightMap* heightmap, double x, double z, double basevalue, double influence, double force) const override;
};
class DEFINITIONSHARED_EXPORT TerrainHeightMapBrushFlatten: public TerrainHeightMapBrush
{
public:
TerrainHeightMapBrushFlatten(double height) : height(height) {}
TerrainHeightMapBrushFlatten(const TerrainHeightMapBrush& brush, double height) : TerrainHeightMapBrush(brush), height(height) {}
protected:
double getBrushValue(TerrainHeightMap* heightmap, double x, double z, double basevalue, double influence, double force) const override;
private:
double height;
};
}
}
#endif // TERRAINHEIGHTMAPBRUSH_H

View file

@ -4,6 +4,8 @@
#include "NoiseGenerator.h"
#include "SurfaceMaterial.h"
#include "PackStream.h"
#include "Scenery.h"
#include "TerrainDefinition.h"
TextureLayerDefinition::TextureLayerDefinition(BaseDefinition* parent):
BaseDefinition(parent)
@ -42,13 +44,13 @@ void TextureLayerDefinition::validate()
materialValidate(material);
/* Update zone height range */
// TODO
/*TerrainDefinition* terrain = Scenery::getCurrent()->getTerrain();
if (terrain)
Scenery* scenery = getScenery();
if (scenery)
{
HeightInfo height_info = terrainGetHeightInfo(terrain);
zoneSetRelativeHeight(terrain_zone, height_info.min_height, height_info.base_height, height_info.max_height);
}*/
TerrainDefinition* terrain = scenery->getTerrain();
HeightInfo height_info = terrain->getHeightInfo();
terrain_zone->setRelativeHeight(height_info.min_height, height_info.base_height, height_info.max_height);
}
}
void TextureLayerDefinition::copy(BaseDefinition *_destination) const

View file

@ -8,12 +8,6 @@
namespace paysages {
namespace definition {
typedef enum
{
WATER_PRESET_LAKE,
WATER_PRESET_SEA
} WaterPreset;
class WaterDefinition: public BaseDefinition
{
public:
@ -26,6 +20,12 @@ public:
virtual void copy(BaseDefinition* destination) const override;
virtual void validate() override;
public:
typedef enum
{
WATER_PRESET_LAKE,
WATER_PRESET_SEA
} WaterPreset;
void applyPreset(WaterPreset preset);
public:

View file

@ -24,7 +24,11 @@ SOURCES += \
AtmosphereDefinition.cpp \
TexturesDefinition.cpp \
TextureLayerDefinition.cpp \
Zone.cpp
Zone.cpp \
TerrainDefinition.cpp \
TerrainHeightMap.cpp \
TerrainHeightMapBrush.cpp \
Scenery.cpp
HEADERS +=\
definition_global.h \
@ -38,7 +42,11 @@ HEADERS +=\
AtmosphereDefinition.h \
TexturesDefinition.h \
TextureLayerDefinition.h \
Zone.h
Zone.h \
TerrainDefinition.h \
TerrainHeightMap.h \
TerrainHeightMapBrush.h \
Scenery.h
unix:!symbian {
maemo5 {

View file

@ -13,6 +13,7 @@
namespace paysages {
namespace definition {
class BaseDefinition;
class Scenery;
class CameraDefinition;
class SurfaceMaterial;
class Zone;
@ -23,6 +24,14 @@ namespace definition {
class AtmosphereDefinition;
class TexturesDefinition;
class TextureLayerDefinition;
class TerrainDefinition;
class TerrainHeightMap;
class TerrainHeightMapBrush;
class TerrainHeightMapBrushElevation;
class TerrainHeightMapBrushSmooth;
class TerrainHeightMapBrushAddNoise;
class TerrainHeightMapBrushReset;
class TerrainHeightMapBrushFlatten;
}
}
using namespace paysages::definition;

View file

@ -9,7 +9,7 @@
#include "CameraDefinition.h"
#include "AtmosphereDefinition.h"
#include "SoftwareRenderer.h"
#include "Scenery.h"
#include "RenderingScenery.h"
void startRender(Renderer* renderer, char* outputpath, RenderParams params)
{
@ -167,16 +167,16 @@ int main(int argc, char** argv)
for (outputcount = 0; outputcount < conf_first_picture + conf_nb_pictures; outputcount++)
{
AtmosphereDefinition* atmo = Scenery::getCurrent()->getAtmosphere();
AtmosphereDefinition* atmo = RenderingScenery::getCurrent()->getAtmosphere();
atmo->hour = (int)floor(conf_daytime_start * 24.0);
atmo->minute = (int)floor(fmod(conf_daytime_start, 1.0 / 24.0) * 24.0 * 60.0);
atmo->validate();
CameraDefinition* camera = Scenery::getCurrent()->getCamera();
CameraDefinition* camera = RenderingScenery::getCurrent()->getCamera();
Vector3 step = {conf_camera_step_x, conf_camera_step_y, conf_camera_step_z};
camera->setLocation(camera->getLocation().add(step));
renderer = new SoftwareRenderer(Scenery::getCurrent());
renderer = new SoftwareRenderer(RenderingScenery::getCurrent());
rendererSetPreviewCallbacks(renderer, NULL, NULL, _previewUpdate);
if (outputcount >= conf_first_picture)

View file

@ -12,7 +12,7 @@
#include "mainwindow.h"
#include "dialogrender.h"
#include "dialogexplorer.h"
#include "Scenery.h"
#include "RenderingScenery.h"
#include "BasePreview.h"
#include "SoftwareRenderer.h"
#include "CameraDefinition.h"
@ -232,12 +232,12 @@ void FreeFormHelper::processApplyClicked()
void FreeFormHelper::processExploreClicked()
{
SoftwareRenderer renderer(Scenery::getCurrent());
SoftwareRenderer renderer(RenderingScenery::getCurrent());
emit needAlterRenderer(&renderer);
CameraDefinition camera;
Scenery::getCurrent()->getCamera(&camera);
RenderingScenery::getCurrent()->getCamera(&camera);
DialogExplorer* dialog = new DialogExplorer(_form_widget, &camera, false, &renderer);
dialog->exec();
@ -246,7 +246,7 @@ void FreeFormHelper::processExploreClicked()
void FreeFormHelper::processRenderClicked()
{
SoftwareRenderer renderer(Scenery::getCurrent());
SoftwareRenderer renderer(RenderingScenery::getCurrent());
emit needAlterRenderer(&renderer);

View file

@ -27,7 +27,7 @@
#include "dialogexplorer.h"
#include "main.h"
#include "Scenery.h"
#include "RenderingScenery.h"
#include "PackStream.h"
#include "tools.h"
@ -127,11 +127,11 @@ MainWindow::MainWindow() :
ui->tool_panel->hide();
//ui->menuBar->hide();
Scenery::getCurrent()->setCustomSaveCallbacks(MainWindow::guiSaveCallback, MainWindow::guiLoadCallback, this);
RenderingScenery::getCurrent()->setCustomSaveCallbacks(MainWindow::guiSaveCallback, MainWindow::guiLoadCallback, this);
// FIXME AutoPreset has already been called by paysagesInit but we need to redo it here because
// the auto apply on FormRender overwrites the camera. Delete this when the render form is no longer a BaseForm.
Scenery::getCurrent()->autoPreset(0);
RenderingScenery::getCurrent()->autoPreset(0);
refreshAll();
}
@ -164,7 +164,7 @@ void MainWindow::refreshAll()
PreviewOsd* osd = PreviewOsd::getInstance(QString("geolocation"));
osd->clearItems();
PreviewOsdItem* item = osd->newItem(50, 50);
item->drawCamera(Scenery::getCurrent()->getCamera());
item->drawCamera(RenderingScenery::getCurrent()->getCamera());
item->setToolTip(QString(tr("Camera")));
emit refreshed();
@ -179,7 +179,7 @@ void MainWindow::fileNew()
{
if (QMessageBox::question(this, tr("Paysages 3D - New scenery"), tr("Do you want to start a new scenery ? Any unsaved changes will be lost."), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes)
{
Scenery::getCurrent()->autoPreset(0);
RenderingScenery::getCurrent()->autoPreset(0);
refreshAll();
}
}
@ -262,7 +262,7 @@ void MainWindow::explore3D()
CameraDefinition* camera = new CameraDefinition;
int result;
Scenery::getCurrent()->getCamera(camera);
RenderingScenery::getCurrent()->getCamera(camera);
DialogExplorer* dialog = new DialogExplorer(this, camera, true);
result = dialog->exec();
@ -271,7 +271,7 @@ void MainWindow::explore3D()
if (result == QDialog::Accepted)
{
Scenery::getCurrent()->setCamera(camera);
RenderingScenery::getCurrent()->setCamera(camera);
refreshAll();
}

View file

@ -7,7 +7,7 @@
#include <cmath>
#include "AtmosphereColorPreviewRenderer.h"
#include "Scenery.h"
#include "RenderingScenery.h"
#include "BasePreview.h"
#include "AtmosphereDefinition.h"
#include "renderer.h"
@ -78,13 +78,13 @@ FormAtmosphere::~FormAtmosphere()
void FormAtmosphere::revertConfig()
{
Scenery::getCurrent()->getAtmosphere(_definition);
RenderingScenery::getCurrent()->getAtmosphere(_definition);
BaseForm::revertConfig();
}
void FormAtmosphere::applyConfig()
{
Scenery::getCurrent()->setAtmosphere(_definition);
RenderingScenery::getCurrent()->setAtmosphere(_definition);
BaseForm::applyConfig();
}

View file

@ -3,7 +3,7 @@
#include "clouds/clo_preview.h"
#include "tools/color.h"
#include "tools/euclid.h"
#include "Scenery.h"
#include "RenderingScenery.h"
#include "BasePreview.h"
#include "renderer.h"
#include "CloudsDefinition.h"
@ -127,14 +127,14 @@ FormClouds::~FormClouds()
void FormClouds::revertConfig()
{
Scenery::getCurrent()->getClouds(_definition);
RenderingScenery::getCurrent()->getClouds(_definition);
BaseFormLayer::revertConfig();
}
void FormClouds::applyConfig()
{
BaseFormLayer::applyConfig();
Scenery::getCurrent()->setClouds(_definition);
RenderingScenery::getCurrent()->setClouds(_definition);
}
void FormClouds::layerReadCurrentFrom(void* layer_definition)

View file

@ -10,7 +10,7 @@
#include "clouds/public.h"
#include "terrain/public.h"
#include "water/public.h"
#include "Scenery.h"
#include "RenderingScenery.h"
#include "PackStream.h"
#include "SoftwareRenderer.h"
#include "BasePreview.h"
@ -64,7 +64,7 @@ protected:
void updateData()
{
Scenery::getCurrent()->bindToRenderer(_renderer);
RenderingScenery::getCurrent()->bindToRenderer(_renderer);
if (!_clouds_enabled)
{
CloudsRendererClass.bind(_renderer, _no_clouds);
@ -171,13 +171,13 @@ void FormRender::loadPack(PackStream* stream)
void FormRender::revertConfig()
{
Scenery::getCurrent()->getCamera(_camera);
RenderingScenery::getCurrent()->getCamera(_camera);
BaseForm::revertConfig();
}
void FormRender::applyConfig()
{
Scenery::getCurrent()->setCamera(_camera);
RenderingScenery::getCurrent()->setCamera(_camera);
BaseForm::applyConfig();
}
@ -193,7 +193,7 @@ void FormRender::startQuickRender()
{
rendererDelete(_renderer);
}
_renderer = new SoftwareRenderer(Scenery::getCurrent());
_renderer = new SoftwareRenderer(RenderingScenery::getCurrent());
_renderer_inited = true;
DialogRender* dialog = new DialogRender(this, _renderer);
@ -209,7 +209,7 @@ void FormRender::startRender()
{
rendererDelete(_renderer);
}
_renderer = new SoftwareRenderer(Scenery::getCurrent());
_renderer = new SoftwareRenderer(RenderingScenery::getCurrent());
_renderer_inited = true;
DialogRender* dialog = new DialogRender(this, _renderer);

View file

@ -1,6 +1,6 @@
#include "formtextures.h"
#include "Scenery.h"
#include "RenderingScenery.h"
#include "BasePreview.h"
#include "renderer.h"
#include "tools.h"
@ -47,7 +47,7 @@ protected:
void updateData()
{
TerrainRendererClass.bind(_renderer, Scenery::getCurrent()->getTerrain());
TerrainRendererClass.bind(_renderer, RenderingScenery::getCurrent()->getTerrain());
//TexturesDefinitionClass.copy(_original_layer, _preview_layer);
}
@ -140,14 +140,14 @@ FormTextures::~FormTextures()
void FormTextures::revertConfig()
{
Scenery::getCurrent()->getTextures(_definition);
RenderingScenery::getCurrent()->getTextures(_definition);
BaseFormLayer::revertConfig();
}
void FormTextures::applyConfig()
{
BaseFormLayer::applyConfig();
Scenery::getCurrent()->setTextures(_definition);
RenderingScenery::getCurrent()->setTextures(_definition);
}
void FormTextures::layerReadCurrentFrom(void* layer_definition)

View file

@ -11,7 +11,7 @@
#include "terrain/public.h"
#include "atmosphere/public.h"
#include "tools.h"
#include "Scenery.h"
#include "RenderingScenery.h"
#include "BasePreview.h"
#include "CameraDefinition.h"
#include "WaterDefinition.h"
@ -45,7 +45,7 @@ protected:
void updateData()
{
WaterRendererClass.bind(_renderer, _definition);
TerrainRendererClass.bind(_renderer, Scenery::getCurrent()->getTerrain());
TerrainRendererClass.bind(_renderer, RenderingScenery::getCurrent()->getTerrain());
}
void toggleChangeEvent(QString key, bool value)
@ -257,13 +257,13 @@ BaseForm(parent)
void FormWater::revertConfig()
{
Scenery::getCurrent()->getWater(_definition);
RenderingScenery::getCurrent()->getWater(_definition);
BaseForm::revertConfig();
}
void FormWater::applyConfig()
{
Scenery::getCurrent()->setWater(_definition);
RenderingScenery::getCurrent()->setWater(_definition);
BaseForm::applyConfig();
}
@ -275,7 +275,7 @@ void FormWater::configChangeEvent()
void FormWater::autoPresetSelected(int preset)
{
_definition->applyPreset((WaterPreset)preset);
_definition->applyPreset((WaterDefinition::WaterPreset)preset);
BaseForm::autoPresetSelected(preset);
}

View file

@ -1,10 +1,11 @@
#include "dialogterrainpainting.h"
#include "ui_dialogterrainpainting.h"
#include "tools.h"
#include <QKeyEvent>
#include <QWheelEvent>
#include <QMessageBox>
#include "tools.h"
#include "TerrainDefinition.h"
DialogTerrainPainting::DialogTerrainPainting(QWidget*parent, TerrainDefinition* terrain) :
QDialog(parent),
@ -16,7 +17,7 @@ DialogTerrainPainting::DialogTerrainPainting(QWidget*parent, TerrainDefinition*
ui->brush_preview->hide();
_terrain_original = terrain;
_terrain_modified = (TerrainDefinition*)TerrainDefinitionClass.create();
_terrain_modified = new TerrainDefinition(NULL);
ui->widget_commands->hide();
@ -80,13 +81,13 @@ void DialogTerrainPainting::wheelEvent(QWheelEvent* event)
void DialogTerrainPainting::accept()
{
TerrainDefinitionClass.copy(_terrain_modified, _terrain_original);
_terrain_modified->copy(_terrain_original);
QDialog::accept();
}
void DialogTerrainPainting::revert()
{
TerrainDefinitionClass.copy(_terrain_original, _terrain_modified);
_terrain_original->copy(_terrain_modified);
ui->widget_heightmap->setTerrain(_terrain_modified);
ui->widget_heightmap->setBrush(&_brush);
@ -112,7 +113,7 @@ void DialogTerrainPainting::brushConfigChanged()
void DialogTerrainPainting::heightmapChanged()
{
qint64 memused = terrainGetMemoryStats(_terrain_modified);
unsigned long memused = _terrain_modified->getMemoryStats();
ui->label_memory_consumption->setText(tr("Memory used: %1").arg(getHumanMemory(memused)));
ui->progress_memory_consumption->setMaximum(1024);
ui->progress_memory_consumption->setValue(memused / 1024);

View file

@ -7,14 +7,16 @@
#include "previewterrainshape.h"
#include "common/freeformhelper.h"
#include "tools.h"
#include "Scenery.h"
#include "RenderingScenery.h"
#include "TerrainDefinition.h"
#include "TerrainHeightMap.h"
#include "textures/public.h"
MainTerrainForm::MainTerrainForm(QWidget *parent) :
QWidget(parent),
ui(new Ui::MainTerrainForm)
{
_terrain = (TerrainDefinition*)TerrainDefinitionClass.create();
_terrain = new TerrainDefinition(NULL);
ui->setupUi(this);
@ -49,12 +51,12 @@ MainTerrainForm::~MainTerrainForm()
delete ui;
delete _renderer_shape;
TerrainDefinitionClass.destroy(_terrain);
delete _terrain;
}
void MainTerrainForm::refreshFromLocalData()
{
qint64 memused = terrainGetMemoryStats(_terrain);
unsigned long memused = _terrain->getMemoryStats();
if (memused > 0)
{
_form_helper->setLabelText(ui->label_painting_info, tr("Memory used by sculpted data: %1").arg(getHumanMemory(memused)));
@ -69,7 +71,7 @@ void MainTerrainForm::refreshFromLocalData()
void MainTerrainForm::refreshFromFellowData()
{
double disp = texturesGetMaximalDisplacement(Scenery::getCurrent()->getTextures());
double disp = texturesGetMaximalDisplacement(RenderingScenery::getCurrent()->getTextures());
if (disp == 0.0)
{
@ -83,12 +85,12 @@ void MainTerrainForm::refreshFromFellowData()
void MainTerrainForm::updateLocalDataFromScenery()
{
Scenery::getCurrent()->getTerrain(_terrain);
RenderingScenery::getCurrent()->getTerrain(_terrain);
}
void MainTerrainForm::commitLocalDataToScenery()
{
Scenery::getCurrent()->setTerrain(_terrain);
RenderingScenery::getCurrent()->setTerrain(_terrain);
}
void MainTerrainForm::alterRenderer(Renderer* renderer)
@ -99,7 +101,7 @@ void MainTerrainForm::alterRenderer(Renderer* renderer)
void MainTerrainForm::buttonBaseNoisePressed()
{
int erase;
if (terrainGetMemoryStats(_terrain) > 0)
if (_terrain->getMemoryStats() > 0)
{
erase = QMessageBox::question(this, tr("Paysages 3D - Base noise edition"), tr("You have manual modifications on this terrain, regenerating base noise may produce weird results."), tr("Keep my changes anyway"), tr("Erase my changes"));
}
@ -112,7 +114,7 @@ void MainTerrainForm::buttonBaseNoisePressed()
{
if (erase)
{
terrainClearPainting(_terrain->height_map);
_terrain->height_map->clearPainting();
}
}
}

View file

@ -3,6 +3,9 @@
#include <cmath>
#include <QAbstractSlider>
#include "NoiseGenerator.h"
#include "TerrainDefinition.h"
#include "TerrainHeightMap.h"
#include "TerrainHeightMapBrush.h"
PaintingBrush::PaintingBrush()
{
@ -101,7 +104,7 @@ QString PaintingBrush::getHelpText()
void PaintingBrush::applyToTerrain(TerrainDefinition* terrain, double x, double z, double duration, bool reverse)
{
double brush_strength;
TerrainBrush brush;
TerrainHeightMapBrush brush;
brush.relative_x = x;
brush.relative_z = z;
@ -118,30 +121,30 @@ void PaintingBrush::applyToTerrain(TerrainDefinition* terrain, double x, double
{
brush_strength = -brush_strength;
}
terrainBrushElevation(terrain->height_map, &brush, brush_strength * 2.0);
terrain->height_map->brushElevation(brush, brush_strength * 2.0);
break;
case PAINTING_BRUSH_SMOOTH:
if (reverse)
{
terrainBrushSmooth(terrain->height_map, &brush, brush_strength * 30.0);
terrain->height_map->brushSmooth(brush, brush_strength * 30.0);
}
else
{
terrainBrushAddNoise(terrain->height_map, &brush, _noise, brush_strength * 0.3);
terrain->height_map->brushAddNoise(brush, _noise, brush_strength * 0.3);
}
break;
case PAINTING_BRUSH_FLATTEN:
if (reverse)
{
_height = terrainGetInterpolatedHeight(terrain, x * terrain->scaling, z * terrain->scaling, 0, 1);
_height = terrain->getInterpolatedHeight(x * terrain->scaling, z * terrain->scaling, 0, 1);
}
else
{
terrainBrushFlatten(terrain->height_map, &brush, _height, brush_strength * 30.0);
terrain->height_map->brushFlatten(brush, _height, brush_strength * 30.0);
}
break;
case PAINTING_BRUSH_RESTORE:
terrainBrushReset(terrain->height_map, &brush, brush_strength * 30.0);
terrain->height_map->brushReset(brush, brush_strength * 30.0);
break;
default:
return;

View file

@ -7,6 +7,8 @@
#include <GL/glu.h>
#include "tools.h"
#include "Scenery.h"
#include "TerrainDefinition.h"
#include "TerrainHeightMap.h"
#include "WaterDefinition.h"
#define HEIGHTMAP_RESOLUTION 256
@ -174,7 +176,7 @@ void WidgetHeightMap::mouseReleaseEvent(QMouseEvent*)
_last_brush_action = 0;
if (_terrain)
{
terrainEndBrushStroke(_terrain->height_map);
_terrain->height_map->endBrushStroke();
}
if (_brush)
{
@ -214,7 +216,7 @@ void WidgetHeightMap::timerEvent(QTimerEvent*)
_last_time = new_time;
// Update top camera
Vector3 target = {_target_x, terrainGetInterpolatedHeight(_terrain, _target_x, _target_z, 1, 1), _target_z};
Vector3 target = {_target_x, _terrain->getInterpolatedHeight(_target_x, _target_z, 1, 1), _target_z};
_top_camera->setLocationCoords(target.x, target.y + 1.0, target.z + 0.1);
_top_camera->setTarget(target);
_top_camera->setZoomToTarget(_zoom);
@ -533,9 +535,9 @@ void WidgetHeightMap::updateVertexInfo()
vertex->point.x = (double) dx;
vertex->point.z = (double) dz;
vertex->point.y = terrainGetGridHeight(_terrain, dx, dz, 1) * _terrain->height;
vertex->point.y = _terrain->getGridHeight(dx, dz, 1) * _terrain->height;
vertex->painted = terrainIsPainted(_terrain->height_map, dx, dz);
vertex->painted = _terrain->height_map->isPainted(dx, dz);
}
}

View file

@ -3,7 +3,7 @@
#include "../common/freeformhelper.h"
#include "../common/freelayerhelper.h"
#include "Scenery.h"
#include "RenderingScenery.h"
#include "TexturesDefinition.h"
#include "TextureLayerDefinition.h"
#include "previewmaterial.h"
@ -133,12 +133,12 @@ void MainTexturesForm::selectPreset(int preset)
void MainTexturesForm::updateLocalDataFromScenery()
{
Scenery::getCurrent()->getTextures(textures);
RenderingScenery::getCurrent()->getTextures(textures);
}
void MainTexturesForm::commitLocalDataToScenery()
{
Scenery::getCurrent()->setTextures(textures);
RenderingScenery::getCurrent()->setTextures(textures);
}
void MainTexturesForm::refreshFromLocalData()

View file

@ -6,7 +6,7 @@
#include <cmath>
#include <GL/glu.h>
#include <QThread>
#include "Scenery.h"
#include "RenderingScenery.h"
#include "SoftwareRenderer.h"
#include "OpenGLRenderer.h"
#include "WaterDefinition.h"
@ -90,7 +90,7 @@ QGLWidget(parent)
}
else
{
_renderer = new SoftwareRenderer(Scenery::getCurrent());
_renderer = new SoftwareRenderer(RenderingScenery::getCurrent());
_renderer_created = true;
}
_opengl_renderer = new OpenGLRenderer(NULL);

View file

@ -6,8 +6,6 @@
#include "SoftwareRenderer.h"
#include "tools/color.h"
class Scenery;
namespace paysages {
namespace preview {

View file

@ -11,9 +11,6 @@
#include "software_global.h"
// TEMP
class Scenery;
namespace paysages {
namespace preview {
class PreviewOsd;

View file

@ -8,6 +8,11 @@
// Legacy compatibility
#include "renderer.h"
#include "terrain/public.h"
#include "clouds/public.h"
#include "textures/public.h"
#include "water/public.h"
static AtmosphereResult _legacyApplyAerialPerspective(Renderer* renderer, Vector3 location, Color base)
{
return ((SoftwareRenderer*)renderer)->getAtmosphereRenderer()->applyAerialPerspective(location, base);
@ -24,7 +29,33 @@ static Vector3 _legacyGetSunDirection(Renderer* renderer)
{
return ((SoftwareRenderer*)renderer)->getAtmosphereRenderer()->getSunDirection();
}
static RayCastingResult _rayWalking(Renderer* renderer, Vector3 location, Vector3 direction, int, int, int, int)
{
RayCastingResult result;
Color sky_color;
result = renderer->terrain->castRay(renderer, location, direction);
if (!result.hit)
{
sky_color = renderer->atmosphere->getSkyColor(renderer, direction).final;
result.hit = 1;
result.hit_location = v3Add(location, v3Scale(direction, 1000.0));
result.hit_color = renderer->clouds->getColor(renderer, sky_color, location, result.hit_location);
}
return result;
}
static double _getPrecision(Renderer* renderer, Vector3 location)
{
Vector3 projected;
projected = renderer->render_camera->project(location);
projected.x += 1.0;
//projected.y += 1.0;
return v3Norm(v3Sub(renderer->render_camera->unproject(projected), location)); // / (double)render_quality;
}
SoftwareRenderer::SoftwareRenderer(Scenery* scenery)
{
@ -42,7 +73,6 @@ SoftwareRenderer::SoftwareRenderer(Scenery* scenery)
this->scenery = new Scenery;
own_scenery = true;
}
this->scenery->bindToRenderer(this);
}
SoftwareRenderer::~SoftwareRenderer()
@ -57,6 +87,16 @@ SoftwareRenderer::~SoftwareRenderer()
}
}
void SoftwareRenderer::setScenery(Scenery* scenery)
{
if (!own_scenery)
{
this->scenery = new Scenery;
own_scenery = true;
}
scenery->copy(this->scenery);
}
void SoftwareRenderer::prepare()
{
// Prepare sub renderers
@ -64,12 +104,21 @@ void SoftwareRenderer::prepare()
atmosphere_renderer = new SoftwareBrunetonAtmosphereRenderer(this);
// Setup transitional renderers (for C-legacy subsystems)
rayWalking = _rayWalking;
getPrecision = _getPrecision;
scenery->getAtmosphere()->copy(atmosphere->definition);
atmosphere->applyAerialPerspective = _legacyApplyAerialPerspective;
atmosphere->getSkyColor = _legacyGetSkyColor;
atmosphere->getLightingStatus = _legacyGetLightingStatus;
atmosphere->getSunDirection = _legacyGetSunDirection;
scenery->getCamera()->copy(render_camera);
TerrainRendererClass.bind(this, scenery->getTerrain());
TexturesRendererClass.bind(this, scenery->getTextures());
CloudsRendererClass.bind(this, scenery->getClouds());
WaterRendererClass.bind(this, scenery->getWater());
// Prepare global tools
fluid_medium->clearMedia();
//fluid_medium->registerMedium(water_renderer);

View file

@ -5,8 +5,6 @@
#include "renderer.h"
class Scenery;
namespace paysages {
namespace software {
@ -20,13 +18,20 @@ public:
SoftwareRenderer(Scenery* scenery=0);
virtual ~SoftwareRenderer();
/*!
* \brief Set the scenery to render.
*
* Don't call this after rendering has already started.
*/
virtual void setScenery(Scenery* scenery) override;
/*!
* \brief Prepare the renderer sub-systems.
*
* This will clear the caches and connect elements together.
* After this call, don't update the scenery when renderer is in use.
*/
virtual void prepare();
virtual void prepare() override;
inline Scenery* getScenery() const {return scenery;}
inline BaseAtmosphereRenderer* getAtmosphereRenderer() const {return atmosphere_renderer;}

View file

@ -0,0 +1,67 @@
#include "RenderingScenery.h"
#include "renderer.h"
#include "terrain/public.h"
#include "textures/public.h"
#include "terrain/ter_raster.h"
#include "water/public.h"
#include "atmosphere/public.h"
#include "CameraDefinition.h"
static RenderingScenery _main_scenery;
RenderingScenery::RenderingScenery()
{
_custom_load = NULL;
_custom_save = NULL;
_custom_data = NULL;
}
RenderingScenery* RenderingScenery::getCurrent()
{
return &_main_scenery;
}
void RenderingScenery::setCustomSaveCallbacks(SceneryCustomDataCallback callback_save, SceneryCustomDataCallback callback_load, void* data)
{
_custom_save = callback_save;
_custom_load = callback_load;
_custom_data = data;
}
void RenderingScenery::save(PackStream* stream) const
{
if (_custom_save)
{
_custom_save(stream, _custom_data);
}
Scenery::save(stream);
}
void RenderingScenery::load(PackStream* stream)
{
if (_custom_load)
{
_custom_load(stream, _custom_data);
}
Scenery::load(stream);
}
void RenderingScenery::bindToRenderer(Renderer* renderer)
{
renderer->setScenery(this);
renderer->prepare();
}
// Transitional C-API
void sceneryRenderFirstPass(Renderer* renderer)
{
terrainRenderSurface(renderer);
waterRenderSurface(renderer);
atmosphereRenderSkydome(renderer);
}

View file

@ -0,0 +1,41 @@
#ifndef RENDERINGSCENERY_H
#define RENDERINGSCENERY_H
#include "rendering_global.h"
#include "Scenery.h"
class Renderer;
typedef void (*SceneryCustomDataCallback)(PackStream* stream, void* data);
/**
* @brief Global scenery management
*
* This class contains the whole scenery definition.
*/
class RENDERINGSHARED_EXPORT RenderingScenery: public Scenery
{
public:
RenderingScenery();
static RenderingScenery* getCurrent();
void setCustomSaveCallbacks(SceneryCustomDataCallback callback_save, SceneryCustomDataCallback callback_load, void* data);
virtual void save(PackStream* stream) const override;
virtual void load(PackStream* stream) override;
void bindToRenderer(Renderer* renderer);
private:
SceneryCustomDataCallback _custom_save;
SceneryCustomDataCallback _custom_load;
void* _custom_data;
};
// Transitional C-API
RENDERINGSHARED_EXPORT void sceneryRenderFirstPass(Renderer* renderer);
#endif // SCENERY_H

View file

@ -1,244 +0,0 @@
#include "Scenery.h"
#include <ctime>
#include "NoiseGenerator.h"
#include "PackStream.h"
#include "atmosphere/public.h"
#include "terrain/public.h"
#include "textures/public.h"
#include "renderer.h"
#include "terrain/ter_raster.h"
#include "AtmosphereDefinition.h"
#include "CameraDefinition.h"
#include "CloudsDefinition.h"
#include "TexturesDefinition.h"
#include "WaterDefinition.h"
static Scenery _main_scenery;
Scenery::Scenery():
BaseDefinition(NULL)
{
atmosphere = new AtmosphereDefinition(this);
camera = new CameraDefinition;
clouds = new CloudsDefinition(this);
terrain = (TerrainDefinition*)TerrainDefinitionClass.create();
textures = new TexturesDefinition(this);
water = new WaterDefinition(this);
addChild(atmosphere);
addChild(camera);
addChild(clouds);
addChild(textures);
addChild(water);
_custom_load = NULL;
_custom_save = NULL;
_custom_data = NULL;
}
Scenery::~Scenery()
{
TerrainDefinitionClass.destroy(terrain);
}
Scenery* Scenery::getCurrent()
{
return &_main_scenery;
}
void Scenery::setCustomSaveCallbacks(SceneryCustomDataCallback callback_save, SceneryCustomDataCallback callback_load, void* data)
{
_custom_save = callback_save;
_custom_load = callback_load;
_custom_data = data;
}
void Scenery::save(PackStream* stream) const
{
BaseDefinition::save(stream);
noiseSave(stream);
TerrainDefinitionClass.save(stream, terrain);
if (_custom_save)
{
_custom_save(stream, _custom_data);
}
}
void Scenery::load(PackStream* stream)
{
BaseDefinition::load(stream);
noiseLoad(stream);
TerrainDefinitionClass.load(stream, terrain);
if (_custom_load)
{
_custom_load(stream, _custom_data);
}
validate();
}
void Scenery::validate()
{
BaseDefinition::validate();
checkCameraAboveGround();
}
void Scenery::autoPreset(int seed)
{
if (!seed)
{
seed = time(NULL);
}
srand(seed);
terrainAutoPreset(terrain, TERRAIN_PRESET_STANDARD);
textures->applyPreset(TexturesDefinition::TEXTURES_PRESET_FULL);
atmosphere->applyPreset(AtmosphereDefinition::ATMOSPHERE_PRESET_CLEAR_DAY);
water->applyPreset(WATER_PRESET_LAKE);
clouds->applyPreset(CloudsDefinition::CLOUDS_PRESET_PARTLY_CLOUDY);
camera->setLocation(VECTOR_ZERO);
camera->setTarget(VECTOR_NORTH);
validate();
}
void Scenery::setAtmosphere(AtmosphereDefinition* atmosphere)
{
atmosphere->copy(this->atmosphere);
}
void Scenery::getAtmosphere(AtmosphereDefinition* atmosphere)
{
this->atmosphere->copy(atmosphere);
}
void Scenery::setCamera(CameraDefinition* camera)
{
camera->copy(this->camera);
checkCameraAboveGround();
}
void Scenery::getCamera(CameraDefinition* camera)
{
this->camera->copy(camera);
}
void Scenery::setClouds(CloudsDefinition* clouds)
{
clouds->copy(this->clouds);
}
void Scenery::getClouds(CloudsDefinition* clouds)
{
this->clouds->copy(clouds);
}
void Scenery::setTerrain(TerrainDefinition* terrain)
{
TerrainDefinitionClass.copy(terrain, this->terrain);
}
void Scenery::getTerrain(TerrainDefinition* terrain)
{
TerrainDefinitionClass.copy(this->terrain, terrain);
}
void Scenery::setTextures(TexturesDefinition* textures)
{
textures->copy(this->textures);
}
void Scenery::getTextures(TexturesDefinition* textures)
{
this->textures->copy(textures);
}
void Scenery::setWater(WaterDefinition* water)
{
water->copy(this->water);
}
void Scenery::getWater(WaterDefinition* water)
{
this->water->copy(water);
}
#include "clouds/public.h"
#include "water/public.h"
static RayCastingResult _rayWalking(Renderer* renderer, Vector3 location, Vector3 direction, int, int, int, int)
{
RayCastingResult result;
Color sky_color;
result = renderer->terrain->castRay(renderer, location, direction);
if (!result.hit)
{
sky_color = renderer->atmosphere->getSkyColor(renderer, direction).final;
result.hit = 1;
result.hit_location = v3Add(location, v3Scale(direction, 1000.0));
result.hit_color = renderer->clouds->getColor(renderer, sky_color, location, result.hit_location);
}
return result;
}
static double _getPrecision(Renderer* renderer, Vector3 location)
{
Vector3 projected;
projected = renderer->render_camera->project(location);
projected.x += 1.0;
//projected.y += 1.0;
return v3Norm(v3Sub(renderer->render_camera->unproject(projected), location)); // / (double)render_quality;
}
void Scenery::bindToRenderer(Renderer* renderer)
{
// TODO Get rid of this !
renderer->rayWalking = _rayWalking;
renderer->getPrecision = _getPrecision;
camera->copy(renderer->render_camera);
AtmosphereRendererClass.bind(renderer, atmosphere);
TerrainRendererClass.bind(renderer, terrain);
TexturesRendererClass.bind(renderer, textures);
CloudsRendererClass.bind(renderer, clouds);
WaterRendererClass.bind(renderer, water);
}
void Scenery::checkCameraAboveGround()
{
Vector3 camera_location = camera->getLocation();
double terrain_height = terrainGetInterpolatedHeight(terrain, camera_location.x, camera_location.z, 1, 1) + 0.5;
double water_height = terrainGetWaterHeight(terrain) + 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;
camera->setLocation(camera_location.add(Vector3(0.0, diff, 0.0)));
}
}
// Transitional C-API
void sceneryRenderFirstPass(Renderer* renderer)
{
terrainRenderSurface(renderer);
waterRenderSurface(renderer);
atmosphereRenderSkydome(renderer);
}

View file

@ -2,6 +2,7 @@
#include <cstdlib>
#include "tools/data.h"
#include "RenderingScenery.h"
#include "Scenery.h"
#include "PackStream.h"
#include "render.h"
@ -45,7 +46,7 @@ FileOperationResult paysagesSave(char* filepath)
version_header = (double)PAYSAGES_CURRENT_DATA_VERSION;
stream.write(&version_header);
Scenery::getCurrent()->save(&stream);
RenderingScenery::getCurrent()->save(&stream);
return FILE_OPERATION_OK;
}
@ -72,7 +73,7 @@ FileOperationResult paysagesLoad(char* filepath)
return FILE_OPERATION_VERSION_MISMATCH;
}
Scenery::getCurrent()->load(&stream);
RenderingScenery::getCurrent()->load(&stream);
return FILE_OPERATION_OK;
}

View file

@ -4,7 +4,7 @@
#include "System.h"
#include "Thread.h"
#include "render.h"
#include "Scenery.h"
#include "RenderingScenery.h"
#include "tools.h"
#include "CameraDefinition.h"
#include "atmosphere/public.h"

View file

@ -19,6 +19,7 @@ public:
virtual ~Renderer();
virtual void prepare() {}
virtual void setScenery(Scenery*) {}
/* Render base configuration */
int render_quality;

View file

@ -24,9 +24,7 @@ SOURCES += main.cpp \
terrain/ter_render.cpp \
terrain/ter_raster.cpp \
terrain/ter_preview.cpp \
terrain/ter_presets.cpp \
terrain/ter_painting.cpp \
terrain/ter_definition.cpp \
textures/tex_tools.cpp \
textures/tex_rendering.cpp \
textures/tex_preview.cpp \
@ -42,7 +40,7 @@ SOURCES += main.cpp \
water/wat_raster.cpp \
water/wat_preview.cpp \
water/wat_definition.cpp \
Scenery.cpp
RenderingScenery.cpp
HEADERS += \
tools.h \
@ -76,7 +74,7 @@ HEADERS += \
water/public.h \
water/private.h \
rendering_global.h \
Scenery.h
RenderingScenery.h
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../system/release/ -lpaysages_system
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../system/debug/ -lpaysages_system

View file

@ -3,22 +3,6 @@
#include "public.h"
typedef struct
{
int xstart;
int xend;
int xsize;
int zstart;
int zend;
int zsize;
} IntegerRect;
TerrainHeightMap* terrainHeightMapCreate(TerrainDefinition* definition);
void terrainHeightmapDelete(TerrainHeightMap* heightmap);
void terrainHeightmapCopy(TerrainHeightMap* source, TerrainHeightMap* destination);
void terrainHeightmapSave(PackStream* stream, TerrainHeightMap* heightmap);
void terrainHeightmapLoad(PackStream* stream, TerrainHeightMap* heightmap);
int terrainHeightmapGetInterpolatedHeight(TerrainHeightMap* heightmap, double x, double z, double* result);
int terrainHeightmapGetGridHeight(TerrainHeightMap* heightmap, int x, int z, double* result);
#endif

View file

@ -2,41 +2,10 @@
#define _PAYSAGES_TERRAIN_PUBLIC_H_
#include "../rendering_global.h"
#include <stdlib.h>
#include "../shared/types.h"
#include "../tools/color.h"
#include "../tools/euclid.h"
namespace paysages {
namespace basics {
class NoiseGenerator;
}
}
typedef enum
{
TERRAIN_PRESET_STANDARD
} TerrainPreset;
typedef struct TerrainHeightMap TerrainHeightMap;
class TerrainDefinition
{
public:
double height;
double scaling;
double shadow_smoothing;
TerrainHeightMap* height_map;
double water_height;
double _detail;
NoiseGenerator* _height_noise;
double _min_height;
double _max_height;
};
typedef struct
{
Vector3 location;
@ -62,37 +31,9 @@ public:
void* _internal_data;
};
RENDERINGSHARED_EXPORT extern StandardDefinition TerrainDefinitionClass;
RENDERINGSHARED_EXPORT extern StandardRenderer TerrainRendererClass;
RENDERINGSHARED_EXPORT void terrainAutoPreset(TerrainDefinition* definition, TerrainPreset preset);
RENDERINGSHARED_EXPORT double terrainGetGridHeight(TerrainDefinition* definition, int x, int z, int with_painting);
RENDERINGSHARED_EXPORT double terrainGetInterpolatedHeight(TerrainDefinition* definition, double x, double z, int scaled, int with_painting);
RENDERINGSHARED_EXPORT size_t terrainGetMemoryStats(TerrainDefinition* definition);
RENDERINGSHARED_EXPORT void terrainAlterPreviewRenderer(Renderer* renderer);
RENDERINGSHARED_EXPORT Color terrainGetPreviewColor(Renderer* renderer, double x, double z, double detail);
RENDERINGSHARED_EXPORT HeightInfo terrainGetHeightInfo(TerrainDefinition* definition);
RENDERINGSHARED_EXPORT double terrainGetWaterHeight(TerrainDefinition* definition);
typedef struct
{
double relative_x;
double relative_z;
double hard_radius;
double smoothed_size;
double total_radius;
} TerrainBrush;
/* Heightmap manipulation */
RENDERINGSHARED_EXPORT int terrainIsPainted(TerrainHeightMap* heightmap, int x, int z);
RENDERINGSHARED_EXPORT void terrainClearPainting(TerrainHeightMap* heightmap);
RENDERINGSHARED_EXPORT void terrainBrushElevation(TerrainHeightMap* heightmap, TerrainBrush* brush, double value);
RENDERINGSHARED_EXPORT void terrainBrushSmooth(TerrainHeightMap* heightmap, TerrainBrush* brush, double value);
RENDERINGSHARED_EXPORT void terrainBrushAddNoise(TerrainHeightMap* heightmap, TerrainBrush* brush, NoiseGenerator* generator, double value);
RENDERINGSHARED_EXPORT void terrainBrushReset(TerrainHeightMap* heightmap, TerrainBrush* brush, double value);
RENDERINGSHARED_EXPORT void terrainBrushFlatten(TerrainHeightMap* heightmap, TerrainBrush* brush, double height, double force);
RENDERINGSHARED_EXPORT void terrainEndBrushStroke(TerrainHeightMap* heightmap);
#endif

View file

@ -1,147 +0,0 @@
#include "private.h"
#include "../tools.h"
#include "../renderer.h"
#include "NoiseGenerator.h"
#include "PackStream.h"
/******************** Definition ********************/
static void _validateDefinition(TerrainDefinition* definition)
{
definition->_height_noise->validate();
if (definition->height < 1.0)
{
definition->height = 1.0;
}
/* Get minimal and maximal height */
definition->_height_noise->getRange(&definition->_min_height, &definition->_max_height);
definition->_min_height *= definition->height * definition->scaling;
definition->_max_height *= definition->height * definition->scaling;
/* TODO Alter with heightmap min/max */
}
static TerrainDefinition* _createDefinition()
{
TerrainDefinition* definition = new TerrainDefinition;
definition->height = 1.0;
definition->scaling = 1.0;
definition->shadow_smoothing = 0.0;
definition->height_map = terrainHeightMapCreate(definition);
definition->water_height = -0.3;
definition->_height_noise = new NoiseGenerator();
terrainAutoPreset(definition, TERRAIN_PRESET_STANDARD);
return definition;
}
static void _deleteDefinition(TerrainDefinition* definition)
{
terrainHeightmapDelete(definition->height_map);
delete definition->_height_noise;
delete definition;
}
static void _copyDefinition(TerrainDefinition* source, TerrainDefinition* destination)
{
destination->height = source->height;
destination->scaling = source->scaling;
destination->shadow_smoothing = source->shadow_smoothing;
terrainHeightmapCopy(source->height_map, destination->height_map);
destination->water_height = source->water_height;
source->_height_noise->copy(destination->_height_noise);
_validateDefinition(destination);
}
static void _saveDefinition(PackStream* stream, TerrainDefinition* definition)
{
stream->write(&definition->height);
stream->write(&definition->scaling);
stream->write(&definition->shadow_smoothing);
terrainHeightmapSave(stream, definition->height_map);
stream->write(&definition->water_height);
definition->_height_noise->save(stream);
}
static void _loadDefinition(PackStream* stream, TerrainDefinition* definition)
{
stream->read(&definition->height);
stream->read(&definition->scaling);
stream->read(&definition->shadow_smoothing);
terrainHeightmapLoad(stream, definition->height_map);
stream->read(&definition->water_height);
definition->_height_noise->load(stream);
_validateDefinition(definition);
}
StandardDefinition TerrainDefinitionClass = {
(FuncObjectCreate)_createDefinition,
(FuncObjectDelete)_deleteDefinition,
(FuncObjectCopy)_copyDefinition,
(FuncObjectValidate)_validateDefinition,
(FuncObjectSave)_saveDefinition,
(FuncObjectLoad)_loadDefinition
};
/******************** Public tools ********************/
double terrainGetGridHeight(TerrainDefinition* definition, int x, int z, int with_painting)
{
double height;
if (!with_painting || !terrainHeightmapGetGridHeight(definition->height_map, x, z, &height))
{
height = definition->_height_noise->get2DTotal((double)x, (double)z);
}
return height;
}
double terrainGetInterpolatedHeight(TerrainDefinition* definition, double x, double z, int scaled, int with_painting)
{
double height;
x /= definition->scaling;
z /= definition->scaling;
if (!with_painting || !terrainHeightmapGetInterpolatedHeight(definition->height_map, x, z, &height))
{
height = definition->_height_noise->get2DTotal(x, z);
}
if (scaled)
{
return height * definition->height * definition->scaling;
}
else
{
return height;
}
}
HeightInfo terrainGetHeightInfo(TerrainDefinition* definition)
{
HeightInfo result;
result.min_height = definition->_min_height;
result.max_height = definition->_max_height;
/* TODO This is duplicated in ter_render.c (_realGetWaterHeight) */
result.base_height = definition->water_height * definition->height * definition->scaling;
return result;
}
double terrainGetWaterHeight(TerrainDefinition* definition)
{
return definition->water_height * definition->height * definition->scaling;
}

View file

@ -1,603 +0,0 @@
#include "private.h"
/*
* Terrain height map painting.
*/
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "../tools/memory.h"
#include "../tools.h"
#include "PackStream.h"
#include "NoiseGenerator.h"
typedef struct
{
int xstart;
int xend;
double* height;
} HeightMapPixelGroup;
typedef struct
{
int z;
int pixel_groups_count;
HeightMapPixelGroup* pixel_groups;
} HeightMapRow;
typedef struct
{
int memsize;
int rows_count;
HeightMapRow* rows;
} HeightMapData;
struct TerrainHeightMap
{
TerrainDefinition* terrain;
HeightMapData merged_data;
HeightMapData brush_data;
};
static void _initData(HeightMapData* data)
{
data->rows_count = 0;
data->rows = new HeightMapRow[1];
data->memsize = 0;
}
static void _clearData(HeightMapData* data)
{
int i, j;
for (i = 0; i < data->rows_count; i++)
{
for (j = 0; j < data->rows[i].pixel_groups_count; j++)
{
free(data->rows[i].pixel_groups[j].height);
}
free(data->rows[i].pixel_groups);
}
data->rows_count = 0;
delete[] data->rows;
data->rows = new HeightMapRow[1];
data->memsize = 0;
}
static void _deleteData(HeightMapData* data)
{
_clearData(data);
delete[] data->rows;
}
static void _copyData(HeightMapData* source, HeightMapData* destination)
{
int i, j, n;
size_t size;
_clearData(destination);
destination->rows_count = source->rows_count;
if (destination->rows_count > 0)
{
size = sizeof(HeightMapRow) * destination->rows_count;
destination->rows = (HeightMapRow*)realloc(destination->rows, size);
destination->memsize += size;
for (i = 0; i < destination->rows_count; i++)
{
destination->rows[i].z = source->rows[i].z;
destination->rows[i].pixel_groups_count = source->rows[i].pixel_groups_count;
size = sizeof(HeightMapPixelGroup) * destination->rows[i].pixel_groups_count;
destination->rows[i].pixel_groups = (HeightMapPixelGroup*)malloc(size);
destination->memsize += size;
for (j = 0; j < destination->rows[i].pixel_groups_count; j++)
{
destination->rows[i].pixel_groups[j].xstart = source->rows[i].pixel_groups[j].xstart;
destination->rows[i].pixel_groups[j].xend = source->rows[i].pixel_groups[j].xend;
n = destination->rows[i].pixel_groups[j].xend - destination->rows[i].pixel_groups[j].xstart + 1;
size = sizeof(double) * n;
destination->rows[i].pixel_groups[j].height = (double*)malloc(size);
destination->memsize += size;
memcpy(destination->rows[i].pixel_groups[j].height, source->rows[i].pixel_groups[j].height, size);
}
}
}
}
static void _saveData(PackStream* stream, HeightMapData* data)
{
int i, j, k;
stream->write(&data->rows_count);
for (i = 0; i < data->rows_count; i++)
{
stream->write(&data->rows[i].z);
stream->write(&data->rows[i].pixel_groups_count);
for (j = 0; j < data->rows[i].pixel_groups_count; j++)
{
stream->write(&data->rows[i].pixel_groups[j].xstart);
stream->write(&data->rows[i].pixel_groups[j].xend);
for (k = 0; k < data->rows[i].pixel_groups[j].xend - data->rows[i].pixel_groups[j].xstart; k++)
{
stream->write(&data->rows[i].pixel_groups[j].height[k]);
}
}
}
}
static void _loadData(PackStream* stream, HeightMapData* data)
{
int i, j, k, n;
size_t size;
_clearData(data);
stream->read(&data->rows_count);
if (data->rows_count > 0)
{
size = sizeof(HeightMapRow) * data->rows_count;
data->rows = (HeightMapRow*)realloc(data->rows, size);
data->memsize += size;
for (i = 0; i < data->rows_count; i++)
{
stream->read(&data->rows[i].z);
stream->read(&data->rows[i].pixel_groups_count);
size = sizeof(HeightMapPixelGroup) * data->rows[i].pixel_groups_count;
data->rows[i].pixel_groups = (HeightMapPixelGroup*)malloc(size);
data->memsize += size;
for (j = 0; j < data->rows[i].pixel_groups_count; j++)
{
stream->read(&data->rows[i].pixel_groups[j].xstart);
stream->read(&data->rows[i].pixel_groups[j].xend);
n = data->rows[i].pixel_groups[j].xend - data->rows[i].pixel_groups[j].xstart;
size = sizeof(double) * n;
data->rows[i].pixel_groups[j].height = (double*)malloc(size);
data->memsize += size;
for (k = 0; k < n; k++)
{
stream->read(&data->rows[i].pixel_groups[j].height[k]);
}
}
}
}
}
/*
* Get a pointer to the data in a heightmap, to a certain location.
* If the location is not already in the heightmap, it is initialized with the terrain height.
* This method will grow the heightmap as necessary (if 'grow' is set to false, NULL will be returned on missing pixels).
*/
static double* _getDataPointer(HeightMapData* data, int x, int z, HeightMapData* fallback, TerrainDefinition* terrain, int grow)
{
int i;
/* Find row */
/* TODO Dichotomic search */
HeightMapRow* row;
i = 0;
while (i < data->rows_count && data->rows[i].z < z)
{
i++;
}
if (i < data->rows_count && data->rows[i].z == z)
{
row = data->rows + i;
}
else if (grow)
{
row = (HeightMapRow*)naiveArrayInsert((void**)&data->rows, sizeof(HeightMapRow), data->rows_count, i);
row->z = z;
row->pixel_groups_count = 0;
row->pixel_groups = (HeightMapPixelGroup*)malloc(1);
data->rows_count++;
data->memsize += sizeof(HeightMapRow);
}
else
{
return NULL;
}
#ifndef NDEBUG
/* Check rows */
for (i = 1; i < data->rows_count; i++)
{
assert(data->rows[i].z > data->rows[i - 1].z);
}
#endif
/* Find pixel group */
HeightMapPixelGroup* pixel_group = NULL;
for (i = 0; i < row->pixel_groups_count; i++)
{
if (x < row->pixel_groups[i].xstart - 1)
{
break;
}
else if (x <= row->pixel_groups[i].xend + 1)
{
if (x == row->pixel_groups[i].xend + 1 && i < row->pixel_groups_count - 1 && x == row->pixel_groups[i + 1].xstart)
{
/* Choose next group if it already includes the pixel */
i++;
}
pixel_group = row->pixel_groups + i;
break;
}
}
/* Alter pixel group */
double* pixel;
int added = 1;
if (!pixel_group)
{
if (!grow)
{
return NULL;
}
/* Create the pixel group with one pixel */
pixel_group = (HeightMapPixelGroup*)naiveArrayInsert((void**)&row->pixel_groups, sizeof(HeightMapPixelGroup), row->pixel_groups_count, i);
pixel_group->xstart = x;
pixel_group->xend = x;
pixel_group->height = (double*)malloc(sizeof(double));
pixel = pixel_group->height;
row->pixel_groups_count++;
data->memsize += sizeof(HeightMapPixelGroup) + sizeof(double);
}
else if (x == pixel_group->xstart - 1)
{
if (!grow)
{
return NULL;
}
/* Extend the rowgroup at start */
pixel_group->xstart--;
pixel = (double*)naiveArrayInsert((void**)&pixel_group->height, sizeof(double), pixel_group->xend - pixel_group->xstart, 0);
data->memsize += sizeof(double);
}
else if (x == pixel_group->xend + 1)
{
if (!grow)
{
return NULL;
}
/* Extend the rowgroup at end */
pixel_group->xend++;
pixel = (double*)naiveArrayInsert((void**)&pixel_group->height, sizeof(double), pixel_group->xend - pixel_group->xstart, pixel_group->xend - pixel_group->xstart);
data->memsize += sizeof(double);
}
else
{
assert(x >= pixel_group->xstart);
assert(x <= pixel_group->xend);
pixel = pixel_group->height + x - pixel_group->xstart;
added = 0;
}
#ifndef NDEBUG
/* Check pixel groups */
for (i = 0; i < row->pixel_groups_count; i++)
{
if (i > 0)
{
assert(row->pixel_groups[i].xstart > row->pixel_groups[i - 1].xend);
}
if (i < row->pixel_groups_count - 1)
{
assert(row->pixel_groups[i].xend < row->pixel_groups[i + 1].xstart);
}
assert(row->pixel_groups[i].xend >= row->pixel_groups[i].xstart);
}
#endif
/* Reset pixel if it had been added */
if (added && (terrain || fallback))
{
if (fallback)
{
double* dpointer = _getDataPointer(fallback, x, z, NULL, terrain, 0);
if (dpointer)
{
*pixel = *dpointer;
}
else if (terrain)
{
*pixel = terrainGetGridHeight(terrain, x, z, 0);
}
}
else if (terrain)
{
*pixel = terrainGetGridHeight(terrain, x, z, 0);
}
}
return pixel;
}
TerrainHeightMap* terrainHeightMapCreate(TerrainDefinition* terrain)
{
TerrainHeightMap* result;
result = new TerrainHeightMap;
result->terrain = terrain;
_initData(&result->merged_data);
_initData(&result->brush_data);
return result;
}
void terrainHeightmapDelete(TerrainHeightMap* heightmap)
{
_deleteData(&heightmap->merged_data);
_deleteData(&heightmap->brush_data);
delete heightmap;
}
void terrainHeightmapCopy(TerrainHeightMap* source, TerrainHeightMap* destination)
{
destination->terrain = source->terrain;
_copyData(&source->merged_data, &destination->merged_data);
_clearData(&destination->brush_data);
}
void terrainHeightmapSave(PackStream* stream, TerrainHeightMap* heightmap)
{
_saveData(stream, &heightmap->merged_data);
}
void terrainHeightmapLoad(PackStream* stream, TerrainHeightMap* heightmap)
{
_loadData(stream, &heightmap->merged_data);
_clearData(&heightmap->brush_data);
}
int terrainHeightmapGetGridHeight(TerrainHeightMap* heightmap, int x, int z, double* result)
{
double* dpointer;
dpointer = _getDataPointer(&heightmap->brush_data, x, z, NULL, NULL, 0);
if (dpointer)
{
*result = *dpointer;
return 1;
}
else
{
dpointer = _getDataPointer(&heightmap->merged_data, x, z, NULL, NULL, 0);
if (dpointer)
{
*result = *dpointer;
return 1;
}
else
{
return 0;
}
}
}
int terrainHeightmapGetInterpolatedHeight(TerrainHeightMap* heightmap, double x, double z, double* result)
{
int ix, iz;
int xlow;
int zlow;
xlow = floor(x);
zlow = floor(z);
int hit = 0;
for (ix = xlow - 1; ix <= xlow + 2 && !hit; ix++)
{
for (iz = zlow - 1; iz <= zlow + 2 && !hit; iz++)
{
if (_getDataPointer(&heightmap->brush_data, x, z, NULL, NULL, 0) || _getDataPointer(&heightmap->merged_data, x, z, NULL, NULL, 0))
{
hit = 1;
}
}
}
if (hit && result)
{
double stencil[16];
double value;
for (ix = xlow - 1; ix <= xlow + 2; ix++)
{
for (iz = zlow - 1; iz <= zlow + 2; iz++)
{
if (!terrainHeightmapGetGridHeight(heightmap, ix, iz, &value))
{
value = terrainGetGridHeight(heightmap->terrain, ix, iz, 0);
}
stencil[(iz - (zlow - 1)) * 4 + ix - (xlow - 1)] = value;
}
}
*result = toolsBicubicInterpolate(stencil, x - (double)xlow, z - (double)zlow);
}
return hit;
}
static inline IntegerRect _getBrushRect(TerrainBrush* brush)
{
IntegerRect result;
double s = brush->smoothed_size + brush->hard_radius;
result.xstart = (int)floor(brush->relative_x - s);
result.xend = (int)ceil(brush->relative_x + s);
result.zstart = (int)floor(brush->relative_z - s);
result.zend = (int)ceil(brush->relative_z + s);
result.xsize = result.xend - result.xstart + 1;
result.zsize = result.zend - result.zstart + 1;
return result;
}
static inline int _isInRect(IntegerRect rect, int x, int z)
{
return (x >= rect.xstart && x <= rect.xend && z >= rect.zstart && z <= rect.zend);
}
size_t terrainGetMemoryStats(TerrainDefinition* definition)
{
return definition->height_map->merged_data.memsize + definition->height_map->brush_data.memsize;
}
int terrainIsPainted(TerrainHeightMap* heightmap, int x, int z)
{
return _getDataPointer(&heightmap->brush_data, x, z, NULL, NULL, 0) || _getDataPointer(&heightmap->merged_data, x, z, NULL, NULL, 0);
}
void terrainClearPainting(TerrainHeightMap* heightmap)
{
_clearData(&heightmap->merged_data);
_clearData(&heightmap->brush_data);
}
typedef double (*BrushCallback)(TerrainHeightMap* heightmap, TerrainBrush* brush, double x, double z, double basevalue, double influence, double force, void* data);
static inline void _applyBrush(TerrainHeightMap* heightmap, TerrainBrush* brush, double force, void* data, BrushCallback callback)
{
IntegerRect brush_rect = _getBrushRect(brush);
int x, z;
double dx, dz, distance, influence;
force /= heightmap->terrain->height;
for (x = brush_rect.xstart; x <= brush_rect.xend; x++)
{
dx = (double)x;
for (z = brush_rect.zstart; z <= brush_rect.zend; z++)
{
dz = (double)z;
distance = sqrt((brush->relative_x - dx) * (brush->relative_x - dx) + (brush->relative_z - dz) * (brush->relative_z - dz));
if (distance > brush->hard_radius)
{
if (distance <= brush->hard_radius + brush->smoothed_size)
{
influence = (1.0 - (distance - brush->hard_radius) / brush->smoothed_size);
}
else
{
continue;
}
}
else
{
influence = 1.0;
}
double* dpointer = _getDataPointer(&heightmap->brush_data, x, z, &heightmap->merged_data, heightmap->terrain, 1);
*dpointer = callback(heightmap, brush, dx, dz, *dpointer, influence, force, data);
}
}
}
static double _applyBrushElevation(TerrainHeightMap* heightmap, TerrainBrush* brush, double x, double z, double basevalue, double influence, double force, void* data)
{
UNUSED(heightmap);
UNUSED(brush);
UNUSED(data);
UNUSED(x);
UNUSED(z);
return basevalue + influence * force;
}
void terrainBrushElevation(TerrainHeightMap* heightmap, TerrainBrush* brush, double value)
{
_applyBrush(heightmap, brush, value, NULL, _applyBrushElevation);
}
static double _applyBrushFlatten(TerrainHeightMap* heightmap, TerrainBrush* brush, double, double, double basevalue, double influence, double force, void* data)
{
UNUSED(heightmap);
UNUSED(brush);
UNUSED(data);
double ideal = *((double*)data);
return basevalue + (ideal - basevalue) * influence * force;
}
void terrainBrushFlatten(TerrainHeightMap* heightmap, TerrainBrush* brush, double height, double force)
{
_applyBrush(heightmap, brush, force, &height, _applyBrushFlatten);
}
static double _applyBrushSmooth(TerrainHeightMap* heightmap, TerrainBrush* brush, double x, double z, double basevalue, double influence, double force, void* data)
{
UNUSED(data);
double ideal, factor;
ideal = terrainGetInterpolatedHeight(heightmap->terrain, (x + brush->total_radius * 0.5) * heightmap->terrain->scaling, z * heightmap->terrain->scaling, 0, 1);
ideal += terrainGetInterpolatedHeight(heightmap->terrain, (x - brush->total_radius * 0.5) * heightmap->terrain->scaling, z * heightmap->terrain->scaling, 0, 1);
ideal += terrainGetInterpolatedHeight(heightmap->terrain, x * heightmap->terrain->scaling, (z - brush->total_radius * 0.5) * heightmap->terrain->scaling, 0, 1);
ideal += terrainGetInterpolatedHeight(heightmap->terrain, x * heightmap->terrain->scaling, (z + brush->total_radius * 0.5) * heightmap->terrain->scaling, 0, 1);
ideal /= 4.0;
factor = influence * force;
if (factor > 1.0)
{
factor = 0.0;
}
return basevalue + (ideal - basevalue) * factor;
}
void terrainBrushSmooth(TerrainHeightMap* heightmap, TerrainBrush* brush, double value)
{
_applyBrush(heightmap, brush, value, NULL, _applyBrushSmooth);
}
static double _applyBrushAddNoise(TerrainHeightMap*, TerrainBrush* brush, double x, double z, double basevalue, double influence, double force, void* data)
{
NoiseGenerator* noise = (NoiseGenerator*)data;
return basevalue + noise->get2DTotal(x / brush->total_radius, z / brush->total_radius) * influence * force * brush->total_radius;
}
void terrainBrushAddNoise(TerrainHeightMap* heightmap, TerrainBrush* brush, NoiseGenerator* generator, double value)
{
_applyBrush(heightmap, brush, value, generator, _applyBrushAddNoise);
}
static double _applyBrushReset(TerrainHeightMap* heightmap, TerrainBrush* brush, double x, double z, double basevalue, double influence, double force, void* data)
{
UNUSED(brush);
UNUSED(data);
double ideal = terrainGetInterpolatedHeight(heightmap->terrain, x * heightmap->terrain->scaling, z * heightmap->terrain->scaling, 0, 0);
return basevalue + (ideal - basevalue) * influence * force;
}
void terrainBrushReset(TerrainHeightMap* heightmap, TerrainBrush* brush, double value)
{
_applyBrush(heightmap, brush, value, NULL, _applyBrushReset);
}
void terrainEndBrushStroke(TerrainHeightMap* heightmap)
{
int i, j, k;
HeightMapData* data = &heightmap->brush_data;
for (i = 0; i < data->rows_count; i++)
{
for (j = 0; j < data->rows[i].pixel_groups_count; j++)
{
for (k = 0; k < data->rows[i].pixel_groups[j].xend - data->rows[i].pixel_groups[j].xstart + 1; k++)
{
double* dpointer = _getDataPointer(&heightmap->merged_data, data->rows[i].pixel_groups[j].xstart + k, data->rows[i].z, NULL, NULL, 1);
*dpointer = data->rows[i].pixel_groups[j].height[k];
}
}
}
_clearData(&heightmap->brush_data);
}

View file

@ -1,33 +0,0 @@
#include "private.h"
#include <math.h>
#include "NoiseGenerator.h"
/*
* Terrain presets.
*/
void terrainAutoPreset(TerrainDefinition* definition, TerrainPreset preset)
{
int resolution = 8;
switch (preset)
{
case TERRAIN_PRESET_STANDARD:
definition->_height_noise->randomizeOffsets();
definition->_height_noise->clearLevels();
definition->_height_noise->addLevelSimple(pow(2.0, resolution + 1), -1.0, 1.0);
definition->_height_noise->addLevelsSimple(resolution - 2, pow(2.0, resolution - 1), -0.7, 0.7, 0.5);
definition->_height_noise->normalizeAmplitude(-1.0, 1.0, 0);
definition->_height_noise->setFunctionParams(NOISE_FUNCTION_SIMPLEX, 0.0, 0.0);
definition->scaling = 1.0;
definition->height = 30.0;
definition->shadow_smoothing = 0.03;
break;
default:
;
}
terrainClearPainting(definition->height_map);
TerrainDefinitionClass.validate(definition);
}

View file

@ -1,10 +1,11 @@
#include "private.h"
#include <stdlib.h>
#include <math.h>
#include <cstdlib>
#include <cmath>
#include "../tools.h"
#include "../renderer.h"
#include "textures/public.h"
#include "TerrainDefinition.h"
/******************** Binding ********************/
static double _fakeGetHeight(Renderer* renderer, double x, double z, int with_painting)
@ -19,7 +20,7 @@ static double _fakeGetHeight(Renderer* renderer, double x, double z, int with_pa
static double _realGetHeight(Renderer* renderer, double x, double z, int with_painting)
{
return terrainGetInterpolatedHeight(renderer->terrain->definition, x, z, 1, with_painting);
return renderer->terrain->definition->getInterpolatedHeight(x, z, 1, with_painting);
}
static TerrainResult _fakeGetResult(Renderer* renderer, double x, double z, int with_painting, int with_textures)
@ -313,7 +314,7 @@ static TerrainRenderer* _createRenderer()
TerrainRenderer* result;
result = new TerrainRenderer;
result->definition = (TerrainDefinition*)TerrainDefinitionClass.create();
result->definition = new TerrainDefinition(NULL);
result->castRay = _fakeCastRay;
result->getHeight = _fakeGetHeight;
@ -326,13 +327,13 @@ static TerrainRenderer* _createRenderer()
static void _deleteRenderer(TerrainRenderer* renderer)
{
TerrainDefinitionClass.destroy(renderer->definition);
delete renderer->definition;
delete renderer;
}
static void _bindRenderer(Renderer* renderer, TerrainDefinition* definition)
{
TerrainDefinitionClass.copy(definition, renderer->terrain->definition);
definition->copy(renderer->terrain->definition);
renderer->terrain->castRay = _realCastRay;
renderer->terrain->getHeight = _realGetHeight;

View file

@ -1,12 +1,12 @@
#include "tex_preview.h"
#include "private.h"
#include "Scenery.h"
#include "RenderingScenery.h"
#include "TexturesDefinition.h"
void TexturesPreviewLayerCoverage_bind(Renderer* renderer, TexturesDefinition* definition)
{
TerrainRendererClass.bind(renderer, Scenery::getCurrent()->getTerrain());
TerrainRendererClass.bind(renderer, RenderingScenery::getCurrent()->getTerrain());
TexturesRendererClass.bind(renderer, definition);
}
@ -61,7 +61,7 @@ Color TexturesPreviewLayerLook_getColor(Renderer* renderer, double x, double y,
void TexturesPreviewCumul_bind(Renderer* renderer, TexturesDefinition* definition)
{
TerrainRendererClass.bind(renderer, Scenery::getCurrent()->getTerrain());
TerrainRendererClass.bind(renderer, RenderingScenery::getCurrent()->getTerrain());
TexturesRendererClass.bind(renderer, definition);
}

View file

@ -20,18 +20,6 @@ double toolsCubicInterpolate(double stencil[4], double x)
return _cubicInterpolate(stencil, x);
}
double toolsBicubicInterpolate(double stencil[16], double x, double y)
{
double buf_cubic_y[4];
buf_cubic_y[0] = _cubicInterpolate(stencil, x);
buf_cubic_y[1] = _cubicInterpolate(stencil + 4, x);
buf_cubic_y[2] = _cubicInterpolate(stencil + 8, x);
buf_cubic_y[3] = _cubicInterpolate(stencil + 12, x);
return _cubicInterpolate(buf_cubic_y, y);
}
void toolsFloat2DMapCopy(double* src, double* dest, int src_xstart, int src_ystart, int dest_xstart, int dest_ystart, int xsize, int ysize, int src_xstep, int src_ystep, int dest_xstep, int dest_ystep)
{
/* TODO Optimize with memcpy if src_xstep == dest_xstep == 1 */

View file

@ -7,8 +7,6 @@
#define UNUSED(_x_) ((void)(_x_))
RENDERINGSHARED_EXPORT double toolsRandom();
RENDERINGSHARED_EXPORT double toolsCubicInterpolate(double stencil[4], double x);
RENDERINGSHARED_EXPORT double toolsBicubicInterpolate(double stencil[16], double x, double y);
RENDERINGSHARED_EXPORT void toolsFloat2DMapCopy(double* src, double* dest, int src_xstart, int src_ystart, int dest_xstart, int dest_ystart, int xsize, int ysize, int src_xstep, int src_ystep, int dest_xstep, int dest_ystep);
#endif

View file

@ -4,22 +4,6 @@
#include <cstring>
#include <cassert>
void* naiveArrayInsert(void** array, size_t item_size, int item_count, int location)
{
char** barray = (char**)array;
assert(location >= 0);
assert(location <= item_count);
*barray = (char*)realloc(*barray, item_size * (item_count + 1));
if (location < item_count)
{
memmove(*barray + item_size * (location + 1), *barray + item_size * location, item_size * (item_count - location));
}
return *barray + item_size * location;
}
char* memory2dRealloc(char* data, int datasize, int oldxsize, int oldysize, int newxsize, int newysize, int xoffset, int yoffset)
{
int xstart, xend, xlen;

View file

@ -8,6 +8,5 @@
#include "../rendering_global.h"
RENDERINGSHARED_EXPORT char* memory2dRealloc(char* data, int datasize, int oldxsize, int oldysize, int newxsize, int newysize, int xoffset, int yoffset);
RENDERINGSHARED_EXPORT void* naiveArrayInsert(void** array, size_t item_size, int item_count, int location);
#endif

20
src/system/Memory.cpp Normal file
View file

@ -0,0 +1,20 @@
#include "Memory.h"
#include <cstring>
#include <cassert>
void* Memory::naiveArrayInsert(void** array, unsigned long item_size, int item_count, int location)
{
char** barray = (char**)array;
assert(location >= 0);
assert(location <= item_count);
*barray = (char*)realloc(*barray, item_size * (item_count + 1));
if (location < item_count)
{
memmove(*barray + item_size * (location + 1), *barray + item_size * location, item_size * (item_count - location));
}
return *barray + item_size * location;
}

18
src/system/Memory.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef MEMORY_H
#define MEMORY_H
#include "system_global.h"
namespace paysages {
namespace system {
class SYSTEMSHARED_EXPORT Memory
{
public:
static void* naiveArrayInsert(void** array, unsigned long item_size, int item_count, int location);
};
}
}
#endif // MEMORY_H

View file

@ -19,7 +19,8 @@ SOURCES += \
Mutex.cpp \
System.cpp \
PackStream.cpp \
RandomGenerator.cpp
RandomGenerator.cpp \
Memory.cpp
HEADERS += \
system_global.h \
@ -28,7 +29,8 @@ HEADERS += \
Mutex.h \
System.h \
PackStream.h \
RandomGenerator.h
RandomGenerator.h \
Memory.h
unix:!symbian {
maemo5 {

View file

@ -5,7 +5,7 @@
#include "SoftwareRenderer.h"
#include "AtmosphereDefinition.h"
#include "AtmosphereRenderer.h"
#include "Scenery.h"
#include "RenderingScenery.h"
#include "System.h"
#define OUTPUT_WIDTH 400
@ -44,7 +44,7 @@ TEST(Bruneton, AerialPerspective1)
TEST(Bruneton, AerialPerspective2)
{
AtmosphereDefinition* atmo = Scenery::getCurrent()->getAtmosphere();
AtmosphereDefinition* atmo = RenderingScenery::getCurrent()->getAtmosphere();
atmo->hour = 6;
atmo->minute = 30;
atmo->validate();

View file

@ -2,7 +2,9 @@
#include <cmath>
#include "NoiseGenerator.h"
#include "terrain/public.h"
#include "TerrainDefinition.h"
#include "TerrainHeightMap.h"
#include "TerrainHeightMapBrush.h"
/* Noise sin period is defined at 20.0 */
#define X_FACTOR (M_PI / 10.0)
@ -25,7 +27,7 @@ static double _noise3dMock(double x, double, double)
class TerrainPainting_Test : public BaseTestCase {
protected:
virtual void SetUp() {
terrain = (TerrainDefinition*)TerrainDefinitionClass.create();
terrain = new TerrainDefinition(NULL);
terrain->height = 3.0;
terrain->scaling = 1.0;
terrain->_height_noise->clearLevels();
@ -36,7 +38,7 @@ protected:
virtual void TearDown()
{
TerrainDefinitionClass.destroy(terrain);
delete terrain;
}
TerrainDefinition* terrain;
@ -45,63 +47,63 @@ protected:
TEST_F(TerrainPainting_Test, grid)
{
/* Test base grid */
EXPECT_DOUBLE_EQ(0.0, terrainGetGridHeight(terrain, 0, 0, 0));
EXPECT_DOUBLE_EQ(0.0, terrainGetGridHeight(terrain, 0, 1, 0));
EXPECT_DOUBLE_EQ(0.0, terrainGetGridHeight(terrain, 0, 0, 1));
EXPECT_DOUBLE_EQ(sin(1.0 * X_FACTOR), terrainGetGridHeight(terrain, 1, 0, 0));
EXPECT_DOUBLE_EQ(sin(2.0 * X_FACTOR), terrainGetGridHeight(terrain, 2, 0, 0));
EXPECT_DOUBLE_EQ(sin(3.0 * X_FACTOR), terrainGetGridHeight(terrain, 3, 0, 0));
EXPECT_DOUBLE_EQ(sin(4.0 * X_FACTOR), terrainGetGridHeight(terrain, 4, 0, 0));
EXPECT_DOUBLE_EQ(1.0, terrainGetGridHeight(terrain, 5, 0, 0));
EXPECT_DOUBLE_EQ(sin(4.0 * X_FACTOR), terrainGetGridHeight(terrain, 6, 0, 0));
EXPECT_DOUBLE_EQ(-sin(1.0 * X_FACTOR), terrainGetGridHeight(terrain, -1, 0, 0));
EXPECT_DOUBLE_EQ(0.0, terrainGetGridHeight(terrain, 10, 0, 0));
EXPECT_DOUBLE_EQ(-1.0, terrainGetGridHeight(terrain, 15, 0, 0));
EXPECT_DOUBLE_EQ(0.0, terrainGetGridHeight(terrain, 20, 0, 0));
EXPECT_DOUBLE_EQ(-1.0, terrainGetGridHeight(terrain, -5, 0, 0));
EXPECT_DOUBLE_EQ(0.0, terrain->getGridHeight(0, 0, 0));
EXPECT_DOUBLE_EQ(0.0, terrain->getGridHeight(0, 1, 0));
EXPECT_DOUBLE_EQ(0.0, terrain->getGridHeight(0, 0, 1));
EXPECT_DOUBLE_EQ(sin(1.0 * X_FACTOR), terrain->getGridHeight(1, 0, 0));
EXPECT_DOUBLE_EQ(sin(2.0 * X_FACTOR), terrain->getGridHeight(2, 0, 0));
EXPECT_DOUBLE_EQ(sin(3.0 * X_FACTOR), terrain->getGridHeight(3, 0, 0));
EXPECT_DOUBLE_EQ(sin(4.0 * X_FACTOR), terrain->getGridHeight(4, 0, 0));
EXPECT_DOUBLE_EQ(1.0, terrain->getGridHeight(5, 0, 0));
EXPECT_DOUBLE_EQ(sin(4.0 * X_FACTOR), terrain->getGridHeight(6, 0, 0));
EXPECT_DOUBLE_EQ(-sin(1.0 * X_FACTOR), terrain->getGridHeight(-1, 0, 0));
EXPECT_DOUBLE_EQ(0.0, terrain->getGridHeight(10, 0, 0));
EXPECT_DOUBLE_EQ(-1.0, terrain->getGridHeight(15, 0, 0));
EXPECT_DOUBLE_EQ(0.0, terrain->getGridHeight(20, 0, 0));
EXPECT_DOUBLE_EQ(-1.0, terrain->getGridHeight(-5, 0, 0));
/* Test interpolated result */
EXPECT_DOUBLE_EQ(terrainGetInterpolatedHeight(terrain, 0.0, 0.0, 0, 0), 0.0);
EXPECT_DOUBLE_IN_RANGE(terrainGetInterpolatedHeight(terrain, 0.5, 0.0, 0, 0), 0.1564, 0.1566);
EXPECT_DOUBLE_EQ(terrainGetInterpolatedHeight(terrain, 1.0, 0.0, 0, 0), sin(1.0 * X_FACTOR));
EXPECT_DOUBLE_EQ(terrainGetInterpolatedHeight(terrain, 0.0, 0.0, 1, 0), 0.0);
EXPECT_DOUBLE_IN_RANGE(terrainGetInterpolatedHeight(terrain, 0.5, 0.0, 1, 0), 3.0 * 0.1564, 3.0 * 0.1566);
EXPECT_DOUBLE_EQ(terrainGetInterpolatedHeight(terrain, 1.0, 0.0, 1, 0), 3.0 * sin(1.0 * X_FACTOR));
EXPECT_DOUBLE_EQ(terrain->getInterpolatedHeight(0.0, 0.0, 0, 0), 0.0);
EXPECT_DOUBLE_IN_RANGE(terrain->getInterpolatedHeight(0.5, 0.0, 0, 0), 0.1564, 0.1566);
EXPECT_DOUBLE_EQ(terrain->getInterpolatedHeight(1.0, 0.0, 0, 0), sin(1.0 * X_FACTOR));
EXPECT_DOUBLE_EQ(terrain->getInterpolatedHeight(0.0, 0.0, 1, 0), 0.0);
EXPECT_DOUBLE_IN_RANGE(terrain->getInterpolatedHeight(0.5, 0.0, 1, 0), 3.0 * 0.1564, 3.0 * 0.1566);
EXPECT_DOUBLE_EQ(terrain->getInterpolatedHeight(1.0, 0.0, 1, 0), 3.0 * sin(1.0 * X_FACTOR));
/* Test scaling */
terrain->scaling = 2.0;
EXPECT_DOUBLE_EQ(terrainGetGridHeight(terrain, 0, 0, 0), 0.0);
EXPECT_DOUBLE_EQ(terrainGetGridHeight(terrain, 1, 0, 0), sin(1.0 * X_FACTOR));
EXPECT_DOUBLE_EQ(terrainGetGridHeight(terrain, 2, 0, 0), sin(2.0 * X_FACTOR));
EXPECT_DOUBLE_EQ(terrainGetGridHeight(terrain, 3, 0, 0), sin(3.0 * X_FACTOR));
EXPECT_DOUBLE_EQ(terrainGetInterpolatedHeight(terrain, 0, 0, 0, 0), 0.0);
EXPECT_DOUBLE_EQ(terrainGetInterpolatedHeight(terrain, 1, 0, 0, 0), sin(0.5 * X_FACTOR));
EXPECT_DOUBLE_EQ(terrainGetInterpolatedHeight(terrain, 2, 0, 0, 0), sin(1.0 * X_FACTOR));
EXPECT_DOUBLE_EQ(terrainGetInterpolatedHeight(terrain, 3, 0, 0, 0), sin(1.5 * X_FACTOR));
EXPECT_DOUBLE_EQ(terrainGetInterpolatedHeight(terrain, 0, 0, 1, 0), 0.0);
EXPECT_DOUBLE_EQ(terrainGetInterpolatedHeight(terrain, 1, 0, 1, 0), 6.0 * sin(0.5 * X_FACTOR));
EXPECT_DOUBLE_EQ(terrainGetInterpolatedHeight(terrain, 2, 0, 1, 0), 6.0 * sin(1.0 * X_FACTOR));
EXPECT_DOUBLE_EQ(terrainGetInterpolatedHeight(terrain, 3, 0, 1, 0), 6.0 * sin(1.5 * X_FACTOR));
EXPECT_DOUBLE_EQ(terrain->getGridHeight(0, 0, 0), 0.0);
EXPECT_DOUBLE_EQ(terrain->getGridHeight(1, 0, 0), sin(1.0 * X_FACTOR));
EXPECT_DOUBLE_EQ(terrain->getGridHeight(2, 0, 0), sin(2.0 * X_FACTOR));
EXPECT_DOUBLE_EQ(terrain->getGridHeight(3, 0, 0), sin(3.0 * X_FACTOR));
EXPECT_DOUBLE_EQ(terrain->getInterpolatedHeight(0, 0, 0, 0), 0.0);
EXPECT_DOUBLE_EQ(terrain->getInterpolatedHeight(1, 0, 0, 0), sin(0.5 * X_FACTOR));
EXPECT_DOUBLE_EQ(terrain->getInterpolatedHeight(2, 0, 0, 0), sin(1.0 * X_FACTOR));
EXPECT_DOUBLE_EQ(terrain->getInterpolatedHeight(3, 0, 0, 0), sin(1.5 * X_FACTOR));
EXPECT_DOUBLE_EQ(terrain->getInterpolatedHeight(0, 0, 1, 0), 0.0);
EXPECT_DOUBLE_EQ(terrain->getInterpolatedHeight(1, 0, 1, 0), 6.0 * sin(0.5 * X_FACTOR));
EXPECT_DOUBLE_EQ(terrain->getInterpolatedHeight(2, 0, 1, 0), 6.0 * sin(1.0 * X_FACTOR));
EXPECT_DOUBLE_EQ(terrain->getInterpolatedHeight(3, 0, 1, 0), 6.0 * sin(1.5 * X_FACTOR));
}
static void _checkBrushResultSides(TerrainDefinition* terrain, TerrainBrush*, double center, double midhard, double hard, double midsoft, double soft, double exter, double neg_midhard, double neg_hard, double neg_midsoft, double neg_soft, double neg_exter)
static void _checkBrushResultSides(TerrainDefinition* terrain, TerrainHeightMapBrush*, double center, double midhard, double hard, double midsoft, double soft, double exter, double neg_midhard, double neg_hard, double neg_midsoft, double neg_soft, double neg_exter)
{
EXPECT_DOUBLE_EQ(terrainGetGridHeight(terrain, 0, 0, 1), center);
EXPECT_DOUBLE_EQ(terrain->getGridHeight(0, 0, 1), center);
EXPECT_DOUBLE_EQ(terrainGetGridHeight(terrain, 1, 0, 1), midhard);
EXPECT_DOUBLE_EQ(terrainGetGridHeight(terrain, 2, 0, 1), hard);
EXPECT_DOUBLE_EQ(terrainGetGridHeight(terrain, 3, 0, 1), midsoft);
EXPECT_DOUBLE_EQ(terrainGetGridHeight(terrain, 4, 0, 1), soft);
EXPECT_DOUBLE_EQ(terrainGetGridHeight(terrain, 5, 0, 1), exter);
EXPECT_DOUBLE_EQ(terrain->getGridHeight(1, 0, 1), midhard);
EXPECT_DOUBLE_EQ(terrain->getGridHeight(2, 0, 1), hard);
EXPECT_DOUBLE_EQ(terrain->getGridHeight(3, 0, 1), midsoft);
EXPECT_DOUBLE_EQ(terrain->getGridHeight(4, 0, 1), soft);
EXPECT_DOUBLE_EQ(terrain->getGridHeight(5, 0, 1), exter);
EXPECT_DOUBLE_EQ(terrainGetGridHeight(terrain, -1, 0, 1), neg_midhard);
EXPECT_DOUBLE_EQ(terrainGetGridHeight(terrain, -2, 0, 1), neg_hard);
EXPECT_DOUBLE_EQ(terrainGetGridHeight(terrain, -3, 0, 1), neg_midsoft);
EXPECT_DOUBLE_EQ(terrainGetGridHeight(terrain, -4, 0, 1), neg_soft);
EXPECT_DOUBLE_EQ(terrainGetGridHeight(terrain, -5, 0, 1), neg_exter);
EXPECT_DOUBLE_EQ(terrain->getGridHeight(-1, 0, 1), neg_midhard);
EXPECT_DOUBLE_EQ(terrain->getGridHeight(-2, 0, 1), neg_hard);
EXPECT_DOUBLE_EQ(terrain->getGridHeight(-3, 0, 1), neg_midsoft);
EXPECT_DOUBLE_EQ(terrain->getGridHeight(-4, 0, 1), neg_soft);
EXPECT_DOUBLE_EQ(terrain->getGridHeight(-5, 0, 1), neg_exter);
}
static void _checkBrushResult(TerrainDefinition* terrain, TerrainBrush* brush, double center, double midhard, double hard, double midsoft, double soft, double exter, int mirror)
static void _checkBrushResult(TerrainDefinition* terrain, TerrainHeightMapBrush* brush, double center, double midhard, double hard, double midsoft, double soft, double exter, int mirror)
{
if (mirror)
{
@ -116,95 +118,95 @@ static void _checkBrushResult(TerrainDefinition* terrain, TerrainBrush* brush, d
TEST_F(TerrainPainting_Test, brush_flatten)
{
/* Set up */
TerrainBrush brush = {0.0, 0.0, 2.0, 2.0, 4.0};
TerrainHeightMapBrush brush(0.0, 0.0, 2.0, 2.0, 4.0);
terrain->height = 1.0;
terrain->scaling = 1.0;
terrain->_height_noise->forceValue(0.0);
/* Test flattening center at 0.5 */
_checkBrushResult(terrain, &brush, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0);
terrainBrushFlatten(terrain->height_map, &brush, 0.5, 1.0);
terrain->height_map->brushFlatten(brush, 0.5, 1.0);
_checkBrushResult(terrain, &brush, 0.5, 0.5, 0.5, 0.25, 0.0, 0.0, 0);
/* Test brush strength */
terrainClearPainting(terrain->height_map);
terrain->height_map->clearPainting();
_checkBrushResult(terrain, &brush, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0);
terrainBrushFlatten(terrain->height_map, &brush, 0.5, 0.01);
terrain->height_map->brushFlatten(brush, 0.5, 0.01);
_checkBrushResult(terrain, &brush, 0.005, 0.005, 0.005, 0.0025, 0.0, 0.0, 0);
/* Test cumulative effect */
terrainBrushFlatten(terrain->height_map, &brush, 0.5, 0.01);
terrain->height_map->brushFlatten(brush, 0.5, 0.01);
_checkBrushResult(terrain, &brush, 0.00995, 0.00995, 0.00995, 0.0049875, 0.0, 0.0, 0);
/* Test with height modifier */
terrain->height = 10.0;
terrainClearPainting(terrain->height_map);
terrain->height_map->clearPainting();
_checkBrushResult(terrain, &brush, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0);
terrainBrushFlatten(terrain->height_map, &brush, 0.5, 1.0);
terrain->height_map->brushFlatten(brush, 0.5, 1.0);
_checkBrushResult(terrain, &brush, 0.05, 0.05, 0.05, 0.025, 0.0, 0.0, 0);
/* Test with scaling modifier */
terrain->height = 10.0;
terrain->scaling = 2.0;
terrainClearPainting(terrain->height_map);
terrain->height_map->clearPainting();
_checkBrushResult(terrain, &brush, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0);
terrainBrushFlatten(terrain->height_map, &brush, 0.5, 1.0);
terrain->height_map->brushFlatten(brush, 0.5, 1.0);
_checkBrushResult(terrain, &brush, 0.05, 0.05, 0.05, 0.025, 0.0, 0.0, 0);
}
TEST_F(TerrainPainting_Test, brush_reset)
{
/* Set up */
TerrainBrush brush = {0.0, 0.0, 2.0, 2.0, 4.0};
TerrainBrush brush_full = {0.0, 0.0, 4.0, 0.0, 4.0};
TerrainHeightMapBrush brush(0.0, 0.0, 2.0, 2.0, 4.0);
TerrainHeightMapBrush brush_full(0.0, 0.0, 4.0, 0.0, 4.0);
terrain->height = 1.0;
terrain->scaling = 1.0;
terrain->_height_noise->forceValue(1.0);
/* Test resetting at center */
_checkBrushResult(terrain, &brush, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0);
terrainBrushFlatten(terrain->height_map, &brush_full, 2.0, 1.0);
terrain->height_map->brushFlatten(brush_full, 2.0, 1.0);
_checkBrushResult(terrain, &brush, 2.0, 2.0, 2.0, 2.0, 2.0, 1.0, 0);
terrainBrushReset(terrain->height_map, &brush, 1.0);
terrain->height_map->brushReset(brush, 1.0);
_checkBrushResult(terrain, &brush, 1.0, 1.0, 1.0, 1.5, 2.0, 1.0, 0);
/* Test brush strength */
terrainClearPainting(terrain->height_map);
terrain->height_map->clearPainting();
_checkBrushResult(terrain, &brush, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0);
terrainBrushFlatten(terrain->height_map, &brush_full, 2.0, 1.0);
terrain->height_map->brushFlatten(brush_full, 2.0, 1.0);
_checkBrushResult(terrain, &brush, 2.0, 2.0, 2.0, 2.0, 2.0, 1.0, 0);
terrainBrushReset(terrain->height_map, &brush, 0.1);
terrain->height_map->brushReset(brush, 0.1);
_checkBrushResult(terrain, &brush, 1.9, 1.9, 1.9, 1.95, 2.0, 1.0, 0);
/* Test cumulative effect */
terrainBrushReset(terrain->height_map, &brush, 0.1);
terrain->height_map->brushReset(brush, 0.1);
_checkBrushResult(terrain, &brush, 1.81, 1.81, 1.81, 1.9025, 2.0, 1.0, 0);
/* Test with height modifier */
terrain->height = 10.0;
terrainClearPainting(terrain->height_map);
terrain->height_map->clearPainting();
_checkBrushResult(terrain, &brush, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0);
terrainBrushFlatten(terrain->height_map, &brush_full, 2.0, 1.0);
terrain->height_map->brushFlatten(brush_full, 2.0, 1.0);
_checkBrushResult(terrain, &brush, 1.1, 1.1, 1.1, 1.1, 1.1, 1.0, 0);
terrainBrushReset(terrain->height_map, &brush, 0.1);
terrain->height_map->brushReset(brush, 0.1);
_checkBrushResult(terrain, &brush, 1.099, 1.099, 1.099, 1.0995, 1.1, 1.0, 0);
/* Test with scaling modifier */
terrain->height = 10.0;
terrain->scaling = 2.0;
terrainClearPainting(terrain->height_map);
terrain->height_map->clearPainting();
_checkBrushResult(terrain, &brush, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0);
terrainBrushFlatten(terrain->height_map, &brush_full, 2.0, 1.0);
terrain->height_map->brushFlatten(brush_full, 2.0, 1.0);
_checkBrushResult(terrain, &brush, 1.1, 1.1, 1.1, 1.1, 1.1, 1.0, 0);
terrainBrushReset(terrain->height_map, &brush, 0.1);
terrain->height_map->brushReset(brush, 0.1);
_checkBrushResult(terrain, &brush, 1.099, 1.099, 1.099, 1.0995, 1.1, 1.0, 0);
}
TEST_F(TerrainPainting_Test, brush_reset_basevalue)
{
/* Set up */
TerrainBrush brush = {0.0, 0.0, 2.0, 2.0, 4.0};
TerrainBrush brush_full = {0.0, 0.0, 4.0, 0.0, 4.0};
TerrainHeightMapBrush brush(0.0, 0.0, 2.0, 2.0, 4.0);
TerrainHeightMapBrush brush_full(0.0, 0.0, 4.0, 0.0, 4.0);
terrain->height = 1.0;
terrain->scaling = 1.0;
@ -212,8 +214,8 @@ TEST_F(TerrainPainting_Test, brush_reset_basevalue)
terrain->height = 1.0;
terrain->scaling = 2.0;
_checkBrushResult(terrain, &brush, 0.0, 0.309016994375, 0.587785252292, 0.809016994375, 0.951056516295, 1.0, 1);
terrainBrushFlatten(terrain->height_map, &brush_full, 2.0, 1.0);
terrain->height_map->brushFlatten(brush_full, 2.0, 1.0);
_checkBrushResultSides(terrain, &brush, 2.0, 2.0, 2.0, 2.0, 2.0, 1.0, 2.0, 2.0, 2.0, 2.0, -1.0);
terrainBrushReset(terrain->height_map, &brush, 1.0);
terrain->height_map->brushReset(brush, 1.0);
_checkBrushResultSides(terrain, &brush, 0.0, 0.309016994375, 0.587785252292, 2.0 - (2.0 - 0.809016994375) * 0.5, 2.0, 1.0, -0.309016994375, -0.587785252292, 2.0 - (2.0 + 0.809016994375) * 0.5, 2.0, -1.0);
}