From eabe68b77dcbeb8bc434603bba6b196c514c60e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sun, 29 Dec 2013 14:14:49 +0100 Subject: [PATCH] New terrain walker (now used for ray casting) --- src/definition/TexturesDefinition.cpp | 11 ++ src/definition/TexturesDefinition.h | 2 + src/interface/desktop/common/mainwindow.cpp | 8 - src/interface/desktop/desktop.pro | 2 - src/interface/desktop/formtextures.cpp | 171 ------------------ src/interface/desktop/formtextures.h | 34 ---- .../desktop/terrain/mainterrainform.cpp | 8 +- src/render/software/TerrainRayWalker.cpp | 103 +++++++++++ src/render/software/TerrainRayWalker.h | 59 ++++++ src/render/software/TerrainRenderer.cpp | 64 ++----- src/render/software/TerrainRenderer.h | 1 + src/render/software/software.pro | 6 +- src/render/software/software_global.h | 2 + 13 files changed, 200 insertions(+), 271 deletions(-) delete mode 100644 src/interface/desktop/formtextures.cpp delete mode 100644 src/interface/desktop/formtextures.h create mode 100644 src/render/software/TerrainRayWalker.cpp create mode 100644 src/render/software/TerrainRayWalker.h diff --git a/src/definition/TexturesDefinition.cpp b/src/definition/TexturesDefinition.cpp index b2b8675..31d12ee 100644 --- a/src/definition/TexturesDefinition.cpp +++ b/src/definition/TexturesDefinition.cpp @@ -64,3 +64,14 @@ void TexturesDefinition::applyPreset(TexturesPreset preset) /* TODO */ } } + +double TexturesDefinition::getMaximalDisplacement() +{ + double result = 0.0; + int n = count(); + for (int i = 0; i < n; i++) + { + result += getTextureLayer(i)->displacement_height; + } + return result; +} diff --git a/src/definition/TexturesDefinition.h b/src/definition/TexturesDefinition.h index 325d0b8..3d1460f 100644 --- a/src/definition/TexturesDefinition.h +++ b/src/definition/TexturesDefinition.h @@ -23,6 +23,8 @@ public: TEXTURES_PRESET_CANYON } TexturesPreset; void applyPreset(TexturesPreset preset); + + double getMaximalDisplacement(); }; } diff --git a/src/interface/desktop/common/mainwindow.cpp b/src/interface/desktop/common/mainwindow.cpp index b55b570..7824ca8 100644 --- a/src/interface/desktop/common/mainwindow.cpp +++ b/src/interface/desktop/common/mainwindow.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include "BasePreview.h" #include "PreviewOsd.h" @@ -36,7 +35,6 @@ MainWindow* MainWindow::_instance = NULL; int main(int argc, char** argv) { MainWindow* window; - QSplashScreen* splash; int result; QApplication app(argc, argv); @@ -47,9 +45,6 @@ int main(int argc, char** argv) return 1; } - splash = new QSplashScreen(QPixmap(getDataPath("images/logo_256.png"))); - splash->show(); - QTranslator qtTranslator; QTranslator myTranslator; @@ -74,9 +69,6 @@ int main(int argc, char** argv) window = new MainWindow(); window->show(); //window->showMaximized(); - splash->finish(window); - - delete splash; result = app.exec(); diff --git a/src/interface/desktop/desktop.pro b/src/interface/desktop/desktop.pro index 1bd30be..b0a4422 100644 --- a/src/interface/desktop/desktop.pro +++ b/src/interface/desktop/desktop.pro @@ -25,7 +25,6 @@ HEADERS += \ inputcamera.h \ inputboolean.h \ formwater.h \ - formtextures.h \ formrender.h \ formclouds.h \ formatmosphere.h \ @@ -74,7 +73,6 @@ SOURCES += \ inputcamera.cpp \ inputboolean.cpp \ formwater.cpp \ - formtextures.cpp \ formrender.cpp \ formclouds.cpp \ formatmosphere.cpp \ diff --git a/src/interface/desktop/formtextures.cpp b/src/interface/desktop/formtextures.cpp deleted file mode 100644 index fd74c6a..0000000 --- a/src/interface/desktop/formtextures.cpp +++ /dev/null @@ -1,171 +0,0 @@ -#include "formtextures.h" - -#include "DesktopScenery.h" -#include "BasePreview.h" -#include "tools.h" -#include "CameraDefinition.h" -#include "TexturesDefinition.h" -#include "TextureLayerDefinition.h" -#include "SoftwareRenderer.h" -#include "TerrainRenderer.h" - -/**************** Previews ****************/ -class PreviewTexturesCoverage : public BasePreview -{ -public: - - PreviewTexturesCoverage(QWidget* parent, TextureLayerDefinition* layer) : BasePreview(parent) - { - _renderer = new SoftwareRenderer(); - _renderer->render_quality = 3; - - _original_layer = layer; - - addOsd(QString("geolocation")); - - configScaling(20.0, 500.0, 20.0, 50.0); - configScrolling(-1000.0, 1000.0, 0.0, -1000.0, 1000.0, 0.0); - } - - ~PreviewTexturesCoverage() - { - delete _renderer; - } -protected: - - Color getColor(double x, double y) - { - Vector3 location; - Color result; - location.x = x; - location.y = _renderer->getTerrainRenderer()->getHeight(x, y, 1); - location.z = y; - //result.r = result.g = result.b = texturesGetLayerCoverage(_preview_layer, _renderer, location, this->scaling); - return result; - } - - void updateData() - { - TexturesDefinition* textures = _renderer->getScenery()->getTextures(); - textures->clear(); - textures->addLayer(); - _original_layer->copy(textures->getLayer(0)); - - _renderer->prepare(); - } - -private: - SoftwareRenderer* _renderer; - TextureLayerDefinition* _original_layer; -}; - -class PreviewTexturesColor : public BasePreview -{ -public: - - PreviewTexturesColor(QWidget* parent, TextureLayerDefinition* layer) : BasePreview(parent) - { - _original_layer = layer; - - _renderer = new SoftwareRenderer(); - _renderer->render_quality = 3; - - _renderer->render_camera->setLocation(Vector3(0.0, 20.0, 0.0)); - - configScaling(0.01, 1.0, 0.01, 0.1); - configScrolling(-1000.0, 1000.0, 0.0, -1000.0, 1000.0, 0.0); - } - - ~PreviewTexturesColor() - { - delete _renderer; - } -protected: - - Color getColor(double x, double y) - { - Vector3 location; - location.x = x; - location.y = 0.0; - location.z = y; - //return texturesGetLayerColor(_preview_layer, _renderer, location, this->scaling); - return COLOR_BLACK; - } - - void updateData() - { - TexturesDefinition* textures = _renderer->getScenery()->getTextures(); - textures->clear(); - textures->addLayer(); - _original_layer->copy(textures->getLayer(0)); - - _renderer->prepare(); - } -private: - SoftwareRenderer* _renderer; - TextureLayerDefinition* _original_layer; -}; - -/**************** Form ****************/ -FormTextures::FormTextures(QWidget *parent) : -BaseFormLayer(parent) -{ - addAutoPreset(tr("Rock")); - addAutoPreset(tr("Grass")); - addAutoPreset(tr("Sand")); - addAutoPreset(tr("Snow")); - - _definition = new TexturesDefinition(NULL); - _layer = new TextureLayerDefinition(NULL); - - _previewCoverage = new PreviewTexturesCoverage(this, _layer); - _previewColor = new PreviewTexturesColor(this, _layer); - addPreview(_previewCoverage, tr("Coverage preview")); - addPreview(_previewColor, tr("Lighted sample")); - - addInputDouble(tr("Displacement height"), &_layer->displacement_height, 0.0, 0.1, 0.001, 0.01); - addInputDouble(tr("Displacement scaling"), &_layer->displacement_scaling, 0.003, 0.3, 0.003, 0.03); - addInputMaterial(tr("Material"), _layer->material); - /*addInputCurve(tr("Coverage by altitude"), _layer->terrain_zone->value_by_height, -20.0, 20.0, 0.0, 1.0, tr("Terrain altitude"), tr("Texture coverage")); - addInputCurve(tr("Coverage by slope"), _layer->terrain_zone->value_by_slope, 0.0, 5.0, 0.0, 1.0, tr("Terrain slope"), tr("Texture coverage"));*/ - - /*addInputDouble(tr("Amplitude for slope coverage"), &_layer->slope_range, 0.001, 0.1, 0.001, 0.01); - addInputDouble(tr("Layer thickness"), &_layer->thickness, 0.0, 0.1, 0.001, 0.01); - addInputDouble(tr("Transparency thickness"), &_layer->thickness_transparency, 0.0, 0.1, 0.001, 0.01);*/ - - setLayers(_definition); -} - -FormTextures::~FormTextures() -{ - delete _definition; - delete _layer; -} - -void FormTextures::revertConfig() -{ - DesktopScenery::getCurrent()->getTextures(_definition); - BaseFormLayer::revertConfig(); -} - -void FormTextures::applyConfig() -{ - BaseFormLayer::applyConfig(); - DesktopScenery::getCurrent()->setTextures(_definition); -} - -void FormTextures::layerReadCurrentFrom(void* layer_definition) -{ - ((TextureLayerDefinition*)layer_definition)->copy(_layer); -} - -void FormTextures::layerWriteCurrentTo(void* layer_definition) -{ - _layer->copy((TextureLayerDefinition*)layer_definition); -} - -void FormTextures::autoPresetSelected(int preset) -{ - _layer->applyPreset((TextureLayerDefinition::TextureLayerPreset)preset); - BaseForm::autoPresetSelected(preset); -} diff --git a/src/interface/desktop/formtextures.h b/src/interface/desktop/formtextures.h deleted file mode 100644 index 0fa2089..0000000 --- a/src/interface/desktop/formtextures.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _PAYSAGES_QT_FORMTEXTURES_H_ -#define _PAYSAGES_QT_FORMTEXTURES_H_ - -#include "desktop_global.h" - -#include "baseformlayer.h" - -class QWidget; - -class FormTextures : public BaseFormLayer -{ - Q_OBJECT - -public: - explicit FormTextures(QWidget *parent = 0); - ~FormTextures(); - -public slots: - virtual void revertConfig(); - virtual void applyConfig(); - -protected: - virtual void layerReadCurrentFrom(void* layer_definition); - virtual void layerWriteCurrentTo(void* layer_definition); - virtual void autoPresetSelected(int preset); - -private: - TexturesDefinition* _definition; - TextureLayerDefinition* _layer; - BasePreview* _previewCoverage; - BasePreview* _previewColor; -}; - -#endif diff --git a/src/interface/desktop/terrain/mainterrainform.cpp b/src/interface/desktop/terrain/mainterrainform.cpp index dd0ab4f..94bb0a1 100644 --- a/src/interface/desktop/terrain/mainterrainform.cpp +++ b/src/interface/desktop/terrain/mainterrainform.cpp @@ -8,6 +8,7 @@ #include "common/freeformhelper.h" #include "tools.h" #include "DesktopScenery.h" +#include "TexturesDefinition.h" #include "TerrainDefinition.h" #include "TerrainHeightMap.h" @@ -70,8 +71,7 @@ void MainTerrainForm::refreshFromLocalData() void MainTerrainForm::refreshFromFellowData() { - //double disp = texturesGetMaximalDisplacement(RenderingScenery::getCurrent()->getTextures()); - double disp = -1000.0; + double disp = DesktopScenery::getCurrent()->getTextures()->getMaximalDisplacement(); if (disp == 0.0) { @@ -79,7 +79,9 @@ void MainTerrainForm::refreshFromFellowData() } else { - ui->label_info_textures->setText(tr("Maximal displacement : %1% of total height").arg(100.0 * disp / _terrain->height, 0, 'f', 1)); + HeightInfo info = DesktopScenery::getCurrent()->getTerrain()->getHeightInfo(); + double terrain_height = info.max_height - info.min_height; + ui->label_info_textures->setText(tr("Maximal displacement : %1% of total height").arg(100.0 * disp / terrain_height, 0, 'f', 1)); } } diff --git a/src/render/software/TerrainRayWalker.cpp b/src/render/software/TerrainRayWalker.cpp new file mode 100644 index 0000000..000fc2b --- /dev/null +++ b/src/render/software/TerrainRayWalker.cpp @@ -0,0 +1,103 @@ +#include "TerrainRayWalker.h" + +#include "SoftwareRenderer.h" +#include "Scenery.h" +#include "TerrainDefinition.h" +#include "TexturesDefinition.h" +#include "TerrainRenderer.h" +#include "TexturesRenderer.h" + +TerrainRayWalker::TerrainRayWalker(SoftwareRenderer* renderer): + renderer(renderer) +{ +} + +void TerrainRayWalker::update() +{ + TerrainDefinition* terrain = renderer->getScenery()->getTerrain(); + HeightInfo info = terrain->getHeightInfo(); + + TexturesDefinition* textures = renderer->getScenery()->getTextures(); + double disp = textures->getMaximalDisplacement(); + + ymin = info.min_height - disp; + ymax = info.max_height + disp; + + ydispmin = -disp; + ydispmax = disp; + + minstep = 0.01 * terrain->scaling / (double)renderer->render_quality; + maxstep = 1.0 * terrain->scaling; +} + +bool TerrainRayWalker::startWalking(Vector3 start, const Vector3 &direction, double escaping_factor, double max_length, TerrainHitResult &result) +{ + TerrainRenderer* terrain_renderer = renderer->getTerrainRenderer(); + TexturesRenderer* textures_renderer = renderer->getTexturesRenderer(); + TerrainRenderer::TerrainResult terrain_result; + Vector3 end, displaced; + bool hit; + double diff; + + double step_length = minstep; + double walked_length = 0.0; + + do + { + // Perform a step + end = start.add(direction.scale(step_length)); + + // Get the terrain info at end (without textures displacement) + terrain_result = terrain_renderer->getResult(end.x, end.z, true, false); + diff = end.y - terrain_result.location.y; + + // If we are very under the terrain, consider a hit + if (diff < ydispmin) + { + hit = true; + } + + // If we are close enough to the terrain, apply displacement + else if (diff < ydispmax) + { + displaced = textures_renderer->displaceTerrain(terrain_result); + diff = end.y - displaced.y; + hit = (diff < 0.0); + } + + if (hit) + { + // Refine the hit with dichotomy at high quality + /*if (renderer->render_quality > 7) + { + end = refineHit(start, end, step_length); + }*/ + + // Find an escape + /*if (escaping_factor != 0.0) + { + result.escape_length = findEscape(end, walked_length, escaping_factor, max_length); + }*/ + + result.hit_location = end; + } + else + { + // Prepare next step + start = end; + walked_length += step_length; + + step_length = diff / (double)renderer->render_quality; + if (step_length < minstep) + { + step_length = minstep; + } + else if (step_length > maxstep) + { + step_length = maxstep; + } + } + } while (not hit and start.y < ymax and walked_length < max_length); + + return hit; +} diff --git a/src/render/software/TerrainRayWalker.h b/src/render/software/TerrainRayWalker.h new file mode 100644 index 0000000..c8c9dd6 --- /dev/null +++ b/src/render/software/TerrainRayWalker.h @@ -0,0 +1,59 @@ +#ifndef TERRAINRAYWALKER_H +#define TERRAINRAYWALKER_H + +#include "software_global.h" + +#include "Vector3.h" + +namespace paysages { +namespace software { + +/*! + * \brief Ray walker to find intersections with terrain. + * + * This walker can be used to find a hard intersection between + * a ray and the terrain (e.g. for raytracing), or a soft intersection + * (e.g. for shadows). + */ +class SOFTWARESHARED_EXPORT TerrainRayWalker +{ +public: + typedef struct { + Vector3 hit_location; // Location of the hit + double escape_length; // Length walked before terrain was escaped after hit (0.0 if no escape) + } TerrainHitResult; + +public: + TerrainRayWalker(SoftwareRenderer* renderer); + + /*! + * \brief Update the walker internal data, from the renderer and scenery. + */ + void update(); + + /*! + * \brief Start the walking process to find intersection + * + * \param start Point of origin of the ray + * \param direction Ray direction (normalized vector) + * \param escaping_factor Factor used to escape the terrain on hit (mainly for shadows computing) + * \param max_length Maximum length to walk before considering no hit + * \param result Object to store the results info + * \return true if there was a hit + */ + bool startWalking(Vector3 start, const Vector3 &direction, double escaping_factor, double max_length, TerrainHitResult &result); + +private: + SoftwareRenderer* renderer; + double ymin; + double ymax; + double ydispmin; + double ydispmax; + double minstep; + double maxstep; +}; + +} +} + +#endif // TERRAINRAYWALKER_H diff --git a/src/render/software/TerrainRenderer.cpp b/src/render/software/TerrainRenderer.cpp index 66ad070..6627a1c 100644 --- a/src/render/software/TerrainRenderer.cpp +++ b/src/render/software/TerrainRenderer.cpp @@ -5,18 +5,22 @@ #include "TerrainDefinition.h" #include "TexturesRenderer.h" #include "LightComponent.h" +#include "TerrainRayWalker.h" TerrainRenderer::TerrainRenderer(SoftwareRenderer* parent): parent(parent) { + walker = new TerrainRayWalker(parent); } TerrainRenderer::~TerrainRenderer() { + delete walker; } void TerrainRenderer::update() { + walker->update(); } double TerrainRenderer::getHeight(double x, double z, int with_painting) @@ -130,59 +134,17 @@ Color TerrainRenderer::getFinalColor(const Vector3 &location, double) RayCastingResult TerrainRenderer::castRay(const Vector3 &start, const Vector3 &direction) { RayCastingResult result; - TerrainDefinition* definition = parent->getScenery()->getTerrain(); - Vector3 inc_vector, direction_norm, cursor; - double inc_value, inc_base, inc_factor, height, diff, lastdiff, length; - - cursor = start; - direction_norm = direction.normalize(); - inc_factor = (double)parent->render_quality; - inc_base = 1.0; - inc_value = inc_base / inc_factor; - lastdiff = start.y - getHeight(start.x, start.z, 1); - - length = 0.0; - do + TerrainRayWalker::TerrainHitResult walk_result; + if (walker->startWalking(start, direction.normalize(), 0.0, 200.0, walk_result)) { - inc_vector = direction_norm.scale(inc_value); - length += inc_vector.getNorm(); - cursor = cursor.add(inc_vector); - height = getHeight(cursor.x, cursor.z, 1); - diff = cursor.y - height; - if (diff < 0.0) - { - if (fabs(diff - lastdiff) > 0.00001) - { - cursor = cursor.add(inc_vector.scale(-diff / (diff - lastdiff))); - cursor.y = getHeight(cursor.x, cursor.z, 1); - } - else - { - cursor.y = height; - } - result.hit = 1; - result.hit_location = cursor; - result.hit_color = getFinalColor(cursor, parent->getPrecision(result.hit_location)); - return result; - } - - if (diff < inc_base / inc_factor) - { - inc_value = inc_base / inc_factor; - } - else if (diff > inc_base) - { - inc_value = inc_base; - } - else - { - inc_value = diff; - } - lastdiff = diff; + result.hit = true; + result.hit_location = walk_result.hit_location; + result.hit_color = getFinalColor(walk_result.hit_location, parent->getPrecision(walk_result.hit_location)); + } + else + { + result.hit = false; } - while (length < 50.0 && cursor.y <= definition->_max_height); - - result.hit = 0; return result; } diff --git a/src/render/software/TerrainRenderer.h b/src/render/software/TerrainRenderer.h index 301ce88..ee4bf0c 100644 --- a/src/render/software/TerrainRenderer.h +++ b/src/render/software/TerrainRenderer.h @@ -35,6 +35,7 @@ public: private: SoftwareRenderer* parent; + TerrainRayWalker* walker; }; } diff --git a/src/render/software/software.pro b/src/render/software/software.pro index f00ec48..ec32efa 100644 --- a/src/render/software/software.pro +++ b/src/render/software/software.pro @@ -36,7 +36,8 @@ SOURCES += SoftwareRenderer.cpp \ WaterRenderer.cpp \ RenderArea.cpp \ RayCastingManager.cpp \ - NightSky.cpp + NightSky.cpp \ + TerrainRayWalker.cpp HEADERS += SoftwareRenderer.h\ software_global.h \ @@ -62,7 +63,8 @@ HEADERS += SoftwareRenderer.h\ WaterRenderer.h \ RenderArea.h \ RayCastingManager.h \ - NightSky.h + NightSky.h \ + TerrainRayWalker.h unix:!symbian { maemo5 { diff --git a/src/render/software/software_global.h b/src/render/software/software_global.h index a7f2c68..180bcca 100644 --- a/src/render/software/software_global.h +++ b/src/render/software/software_global.h @@ -42,6 +42,8 @@ namespace software { class LightComponent; class NightSky; + + class TerrainRayWalker; } }