diff --git a/src/basics/Interpolation.cpp b/src/basics/Interpolation.cpp index 93db00d..9268131 100644 --- a/src/basics/Interpolation.cpp +++ b/src/basics/Interpolation.cpp @@ -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); } diff --git a/src/basics/Interpolation.h b/src/basics/Interpolation.h index 2e18243..0c4043c 100644 --- a/src/basics/Interpolation.h +++ b/src/basics/Interpolation.h @@ -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); }; } diff --git a/src/definition/BaseDefinition.cpp b/src/definition/BaseDefinition.cpp index c9be136..6aa1c6f 100644 --- a/src/definition/BaseDefinition.cpp +++ b/src/definition/BaseDefinition.cpp @@ -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); diff --git a/src/definition/BaseDefinition.h b/src/definition/BaseDefinition.h index 305a899..ddf9fd0 100644 --- a/src/definition/BaseDefinition.h +++ b/src/definition/BaseDefinition.h @@ -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;} diff --git a/src/definition/Scenery.cpp b/src/definition/Scenery.cpp new file mode 100644 index 0000000..cbbf7f5 --- /dev/null +++ b/src/definition/Scenery.cpp @@ -0,0 +1,144 @@ +#include "Scenery.h" + +#include + +#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))); + } +} diff --git a/src/rendering/Scenery.h b/src/definition/Scenery.h similarity index 71% rename from src/rendering/Scenery.h rename to src/definition/Scenery.h index 3e1bb30..462216b 100644 --- a/src/rendering/Scenery.h +++ b/src/definition/Scenery.h @@ -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 diff --git a/src/definition/TerrainDefinition.cpp b/src/definition/TerrainDefinition.cpp new file mode 100644 index 0000000..42f4b2a --- /dev/null +++ b/src/definition/TerrainDefinition.cpp @@ -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(); +} diff --git a/src/definition/TerrainDefinition.h b/src/definition/TerrainDefinition.h new file mode 100644 index 0000000..9849349 --- /dev/null +++ b/src/definition/TerrainDefinition.h @@ -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 diff --git a/src/definition/TerrainHeightMap.cpp b/src/definition/TerrainHeightMap.cpp new file mode 100644 index 0000000..56a0e94 --- /dev/null +++ b/src/definition/TerrainHeightMap.cpp @@ -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 + +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); +} diff --git a/src/definition/TerrainHeightMap.h b/src/definition/TerrainHeightMap.h new file mode 100644 index 0000000..495e8b5 --- /dev/null +++ b/src/definition/TerrainHeightMap.h @@ -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 diff --git a/src/definition/TerrainHeightMapBrush.cpp b/src/definition/TerrainHeightMapBrush.cpp new file mode 100644 index 0000000..af16d8a --- /dev/null +++ b/src/definition/TerrainHeightMapBrush.cpp @@ -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; +} diff --git a/src/definition/TerrainHeightMapBrush.h b/src/definition/TerrainHeightMapBrush.h new file mode 100644 index 0000000..4161965 --- /dev/null +++ b/src/definition/TerrainHeightMapBrush.h @@ -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 diff --git a/src/definition/TextureLayerDefinition.cpp b/src/definition/TextureLayerDefinition.cpp index 138c094..562d92c 100644 --- a/src/definition/TextureLayerDefinition.cpp +++ b/src/definition/TextureLayerDefinition.cpp @@ -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 diff --git a/src/definition/WaterDefinition.h b/src/definition/WaterDefinition.h index d242463..929984c 100644 --- a/src/definition/WaterDefinition.h +++ b/src/definition/WaterDefinition.h @@ -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: diff --git a/src/definition/definition.pro b/src/definition/definition.pro index ca271af..21b6b85 100644 --- a/src/definition/definition.pro +++ b/src/definition/definition.pro @@ -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 { diff --git a/src/definition/definition_global.h b/src/definition/definition_global.h index 0ae9d9a..7279f08 100644 --- a/src/definition/definition_global.h +++ b/src/definition/definition_global.h @@ -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; diff --git a/src/interface/commandline/main.cpp b/src/interface/commandline/main.cpp index 9854fe1..7826e1e 100644 --- a/src/interface/commandline/main.cpp +++ b/src/interface/commandline/main.cpp @@ -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) diff --git a/src/interface/desktop/common/freeformhelper.cpp b/src/interface/desktop/common/freeformhelper.cpp index ac4cd65..606b344 100644 --- a/src/interface/desktop/common/freeformhelper.cpp +++ b/src/interface/desktop/common/freeformhelper.cpp @@ -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); diff --git a/src/interface/desktop/common/mainwindow.cpp b/src/interface/desktop/common/mainwindow.cpp index 5ed6a42..54152be 100644 --- a/src/interface/desktop/common/mainwindow.cpp +++ b/src/interface/desktop/common/mainwindow.cpp @@ -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(); } diff --git a/src/interface/desktop/formatmosphere.cpp b/src/interface/desktop/formatmosphere.cpp index 27bf622..3eeaf6f 100644 --- a/src/interface/desktop/formatmosphere.cpp +++ b/src/interface/desktop/formatmosphere.cpp @@ -7,7 +7,7 @@ #include #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(); } diff --git a/src/interface/desktop/formclouds.cpp b/src/interface/desktop/formclouds.cpp index 397a58a..2c58a72 100644 --- a/src/interface/desktop/formclouds.cpp +++ b/src/interface/desktop/formclouds.cpp @@ -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) diff --git a/src/interface/desktop/formrender.cpp b/src/interface/desktop/formrender.cpp index 8bad8ca..97c1ca3 100644 --- a/src/interface/desktop/formrender.cpp +++ b/src/interface/desktop/formrender.cpp @@ -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); diff --git a/src/interface/desktop/formtextures.cpp b/src/interface/desktop/formtextures.cpp index 00f6a42..6a177b5 100644 --- a/src/interface/desktop/formtextures.cpp +++ b/src/interface/desktop/formtextures.cpp @@ -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) diff --git a/src/interface/desktop/formwater.cpp b/src/interface/desktop/formwater.cpp index c886b77..a1187ea 100644 --- a/src/interface/desktop/formwater.cpp +++ b/src/interface/desktop/formwater.cpp @@ -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); } diff --git a/src/interface/desktop/terrain/dialogterrainpainting.cpp b/src/interface/desktop/terrain/dialogterrainpainting.cpp index e329a47..c617ebe 100644 --- a/src/interface/desktop/terrain/dialogterrainpainting.cpp +++ b/src/interface/desktop/terrain/dialogterrainpainting.cpp @@ -1,10 +1,11 @@ #include "dialogterrainpainting.h" #include "ui_dialogterrainpainting.h" -#include "tools.h" #include #include #include +#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); diff --git a/src/interface/desktop/terrain/mainterrainform.cpp b/src/interface/desktop/terrain/mainterrainform.cpp index 26cc6c5..3d008a4 100644 --- a/src/interface/desktop/terrain/mainterrainform.cpp +++ b/src/interface/desktop/terrain/mainterrainform.cpp @@ -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(); } } } diff --git a/src/interface/desktop/terrain/paintingbrush.cpp b/src/interface/desktop/terrain/paintingbrush.cpp index 0d48dd1..bd017f5 100644 --- a/src/interface/desktop/terrain/paintingbrush.cpp +++ b/src/interface/desktop/terrain/paintingbrush.cpp @@ -3,6 +3,9 @@ #include #include #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; diff --git a/src/interface/desktop/terrain/widgetheightmap.cpp b/src/interface/desktop/terrain/widgetheightmap.cpp index 493c1bd..b9a6987 100644 --- a/src/interface/desktop/terrain/widgetheightmap.cpp +++ b/src/interface/desktop/terrain/widgetheightmap.cpp @@ -7,6 +7,8 @@ #include #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); } } diff --git a/src/interface/desktop/textures/maintexturesform.cpp b/src/interface/desktop/textures/maintexturesform.cpp index abf54c8..818ae15 100644 --- a/src/interface/desktop/textures/maintexturesform.cpp +++ b/src/interface/desktop/textures/maintexturesform.cpp @@ -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() diff --git a/src/render/opengl/WidgetExplorer.cpp b/src/render/opengl/WidgetExplorer.cpp index 01c7caf..8105013 100644 --- a/src/render/opengl/WidgetExplorer.cpp +++ b/src/render/opengl/WidgetExplorer.cpp @@ -6,7 +6,7 @@ #include #include #include -#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); diff --git a/src/render/preview/Base2dPreviewRenderer.h b/src/render/preview/Base2dPreviewRenderer.h index 8e685e0..1f17eb2 100644 --- a/src/render/preview/Base2dPreviewRenderer.h +++ b/src/render/preview/Base2dPreviewRenderer.h @@ -6,8 +6,6 @@ #include "SoftwareRenderer.h" #include "tools/color.h" -class Scenery; - namespace paysages { namespace preview { diff --git a/src/render/preview/preview_global.h b/src/render/preview/preview_global.h index ced5573..90eeefc 100644 --- a/src/render/preview/preview_global.h +++ b/src/render/preview/preview_global.h @@ -11,9 +11,6 @@ #include "software_global.h" -// TEMP -class Scenery; - namespace paysages { namespace preview { class PreviewOsd; diff --git a/src/render/software/SoftwareRenderer.cpp b/src/render/software/SoftwareRenderer.cpp index e2b287f..6fe122f 100644 --- a/src/render/software/SoftwareRenderer.cpp +++ b/src/render/software/SoftwareRenderer.cpp @@ -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); diff --git a/src/render/software/SoftwareRenderer.h b/src/render/software/SoftwareRenderer.h index 53ba7b2..6eeaa35 100644 --- a/src/render/software/SoftwareRenderer.h +++ b/src/render/software/SoftwareRenderer.h @@ -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;} diff --git a/src/rendering/RenderingScenery.cpp b/src/rendering/RenderingScenery.cpp new file mode 100644 index 0000000..6a30fd4 --- /dev/null +++ b/src/rendering/RenderingScenery.cpp @@ -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); +} diff --git a/src/rendering/RenderingScenery.h b/src/rendering/RenderingScenery.h new file mode 100644 index 0000000..462c853 --- /dev/null +++ b/src/rendering/RenderingScenery.h @@ -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 diff --git a/src/rendering/Scenery.cpp b/src/rendering/Scenery.cpp deleted file mode 100644 index 58e87f1..0000000 --- a/src/rendering/Scenery.cpp +++ /dev/null @@ -1,244 +0,0 @@ -#include "Scenery.h" - -#include - -#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); -} diff --git a/src/rendering/main.cpp b/src/rendering/main.cpp index eb816c9..2a3f4c7 100644 --- a/src/rendering/main.cpp +++ b/src/rendering/main.cpp @@ -2,6 +2,7 @@ #include #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; } diff --git a/src/rendering/renderer.cpp b/src/rendering/renderer.cpp index 25f48a2..65a556f 100644 --- a/src/rendering/renderer.cpp +++ b/src/rendering/renderer.cpp @@ -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" diff --git a/src/rendering/renderer.h b/src/rendering/renderer.h index 9ffe4d8..718ea01 100644 --- a/src/rendering/renderer.h +++ b/src/rendering/renderer.h @@ -19,6 +19,7 @@ public: virtual ~Renderer(); virtual void prepare() {} + virtual void setScenery(Scenery*) {} /* Render base configuration */ int render_quality; diff --git a/src/rendering/rendering.pro b/src/rendering/rendering.pro index bbdd519..606d1ad 100644 --- a/src/rendering/rendering.pro +++ b/src/rendering/rendering.pro @@ -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 diff --git a/src/rendering/terrain/private.h b/src/rendering/terrain/private.h index 9595d36..286ab87 100644 --- a/src/rendering/terrain/private.h +++ b/src/rendering/terrain/private.h @@ -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 diff --git a/src/rendering/terrain/public.h b/src/rendering/terrain/public.h index dd2b2d8..cd91446 100644 --- a/src/rendering/terrain/public.h +++ b/src/rendering/terrain/public.h @@ -2,41 +2,10 @@ #define _PAYSAGES_TERRAIN_PUBLIC_H_ #include "../rendering_global.h" -#include #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 diff --git a/src/rendering/terrain/ter_definition.cpp b/src/rendering/terrain/ter_definition.cpp deleted file mode 100644 index 15201e3..0000000 --- a/src/rendering/terrain/ter_definition.cpp +++ /dev/null @@ -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; -} diff --git a/src/rendering/terrain/ter_painting.cpp b/src/rendering/terrain/ter_painting.cpp index ecb572a..e69de29 100644 --- a/src/rendering/terrain/ter_painting.cpp +++ b/src/rendering/terrain/ter_painting.cpp @@ -1,603 +0,0 @@ -#include "private.h" - -/* - * Terrain height map painting. - */ - -#include -#include -#include -#include -#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); -} diff --git a/src/rendering/terrain/ter_presets.cpp b/src/rendering/terrain/ter_presets.cpp deleted file mode 100644 index 9171f17..0000000 --- a/src/rendering/terrain/ter_presets.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "private.h" - -#include -#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); -} diff --git a/src/rendering/terrain/ter_render.cpp b/src/rendering/terrain/ter_render.cpp index 4e84d35..0d7f8a4 100644 --- a/src/rendering/terrain/ter_render.cpp +++ b/src/rendering/terrain/ter_render.cpp @@ -1,10 +1,11 @@ #include "private.h" -#include -#include +#include +#include #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; diff --git a/src/rendering/textures/tex_preview.cpp b/src/rendering/textures/tex_preview.cpp index 1148729..6b7f271 100644 --- a/src/rendering/textures/tex_preview.cpp +++ b/src/rendering/textures/tex_preview.cpp @@ -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); } diff --git a/src/rendering/tools.cpp b/src/rendering/tools.cpp index 858ee50..f3df0f1 100644 --- a/src/rendering/tools.cpp +++ b/src/rendering/tools.cpp @@ -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 */ diff --git a/src/rendering/tools.h b/src/rendering/tools.h index 379f5d1..0811288 100644 --- a/src/rendering/tools.h +++ b/src/rendering/tools.h @@ -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 diff --git a/src/rendering/tools/memory.cpp b/src/rendering/tools/memory.cpp index cb9163c..456558e 100644 --- a/src/rendering/tools/memory.cpp +++ b/src/rendering/tools/memory.cpp @@ -4,22 +4,6 @@ #include #include -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; diff --git a/src/rendering/tools/memory.h b/src/rendering/tools/memory.h index bb3a8ae..59475e5 100644 --- a/src/rendering/tools/memory.h +++ b/src/rendering/tools/memory.h @@ -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 diff --git a/src/system/Memory.cpp b/src/system/Memory.cpp new file mode 100644 index 0000000..7c48f12 --- /dev/null +++ b/src/system/Memory.cpp @@ -0,0 +1,20 @@ +#include "Memory.h" + +#include +#include + +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; +} diff --git a/src/system/Memory.h b/src/system/Memory.h new file mode 100644 index 0000000..3257c79 --- /dev/null +++ b/src/system/Memory.h @@ -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 diff --git a/src/system/system.pro b/src/system/system.pro index 09a3116..5e672a2 100644 --- a/src/system/system.pro +++ b/src/system/system.pro @@ -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 { diff --git a/src/tests/Bruneton_Test.cpp b/src/tests/Bruneton_Test.cpp index 7d21df1..3d3e18e 100644 --- a/src/tests/Bruneton_Test.cpp +++ b/src/tests/Bruneton_Test.cpp @@ -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(); diff --git a/src/tests/TerrainPainting_Test.cpp b/src/tests/TerrainPainting_Test.cpp index 3bb14ac..b63fa42 100644 --- a/src/tests/TerrainPainting_Test.cpp +++ b/src/tests/TerrainPainting_Test.cpp @@ -2,7 +2,9 @@ #include #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); }