From 61a43410db7ccd3f2cdfcfea9f852dc6256d0b23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Wed, 30 Dec 2015 00:20:20 +0100 Subject: [PATCH] Refactored CelestialBodyDefinition, with new sun/moon widget --- src/definition/AtmosphereDefinition.cpp | 62 +++--- src/definition/AtmosphereDefinition.h | 23 ++- src/definition/CelestialBodyDefinition.cpp | 18 ++ src/definition/CelestialBodyDefinition.h | 38 ++++ src/definition/TimeManager.cpp | 2 +- src/definition/definition_global.h | 1 + src/interface/commandline/tests.cpp | 2 +- src/interface/modeler/AtmosphereModeler.cpp | 22 +-- src/interface/modeler/AtmosphereModeler.h | 10 +- src/interface/modeler/BaseModelerTool.cpp | 39 ++++ src/interface/modeler/BaseModelerTool.h | 35 ++++ src/interface/modeler/FloatPropertyBind.cpp | 17 +- src/interface/modeler/FloatPropertyBind.h | 6 +- src/interface/modeler/IntPropertyBind.cpp | 15 +- src/interface/modeler/IntPropertyBind.h | 6 +- src/interface/modeler/MainModelerWindow.cpp | 22 +-- src/interface/modeler/MainModelerWindow.h | 10 +- src/interface/modeler/ModelerCameras.cpp | 3 +- src/interface/modeler/RenderProcess.cpp | 2 +- src/interface/modeler/modeler_global.h | 2 + src/interface/modeler/qml/BaseSlider.qml | 2 - .../modeler/qml/PanelAtmosphereDaytime.qml | 181 ++++-------------- .../modeler/qml/PanelPictureChoice.qml | 2 - src/interface/modeler/qml/WidgetDayTime.qml | 77 ++++++++ .../modeler/qml/WidgetSphericalCoords.qml | 45 +++++ src/interface/modeler/qml/app.qrc | 4 + .../modeler/qml/images/bg_phi_coord.png | Bin 0 -> 3304 bytes .../modeler/qml/images/bg_theta_coord.png | Bin 0 -> 10033 bytes src/render/opengl/OpenGLSkybox.cpp | 14 +- src/render/opengl/OpenGLTerrain.cpp | 14 +- .../software/AtmosphereModelBruneton.cpp | 3 +- src/render/software/AtmosphereRenderer.cpp | 7 +- src/render/software/NightSky.cpp | 12 +- src/tests/Scenery_Test.cpp | 8 +- 34 files changed, 425 insertions(+), 279 deletions(-) create mode 100644 src/definition/CelestialBodyDefinition.cpp create mode 100644 src/definition/CelestialBodyDefinition.h create mode 100644 src/interface/modeler/BaseModelerTool.cpp create mode 100644 src/interface/modeler/BaseModelerTool.h create mode 100644 src/interface/modeler/qml/WidgetDayTime.qml create mode 100644 src/interface/modeler/qml/WidgetSphericalCoords.qml create mode 100644 src/interface/modeler/qml/images/bg_phi_coord.png create mode 100644 src/interface/modeler/qml/images/bg_theta_coord.png diff --git a/src/definition/AtmosphereDefinition.cpp b/src/definition/AtmosphereDefinition.cpp index 761a029..265f632 100644 --- a/src/definition/AtmosphereDefinition.cpp +++ b/src/definition/AtmosphereDefinition.cpp @@ -5,29 +5,24 @@ #include "RandomGenerator.h" #include "FloatNode.h" #include "GodRaysDefinition.h" +#include "CelestialBodyDefinition.h" AtmosphereDefinition::AtmosphereDefinition(DefinitionNode *parent) : DefinitionNode(parent, "atmosphere", "atmosphere") { model = ATMOSPHERE_MODEL_DISABLED; godrays = new GodRaysDefinition(this); - daytime = new FloatNode(this, "daytime"); + sun = new CelestialBodyDefinition(this, "sun"); + moon = new CelestialBodyDefinition(this, "moon"); humidity = new FloatNode(this, "humidity"); - sun_radius = new FloatNode(this, "sun_radius"); sun_color = COLOR_RED; } -AtmosphereDefinition::~AtmosphereDefinition() { -} - void AtmosphereDefinition::save(PackStream *stream) const { DefinitionNode::save(stream); stream->write((int *)&model); sun_color.save(stream); stream->write(&dome_lighting); - stream->write(&moon_radius); - stream->write(&moon_theta); - stream->write(&moon_phi); int star_count = stars.size(); stream->write(&star_count); @@ -44,9 +39,6 @@ void AtmosphereDefinition::load(PackStream *stream) { stream->read((int *)&model); sun_color.load(stream); stream->read(&dome_lighting); - stream->read(&moon_radius); - stream->read(&moon_theta); - stream->read(&moon_phi); int star_count; stream->read(&star_count); @@ -66,39 +58,41 @@ void AtmosphereDefinition::load(PackStream *stream) { void AtmosphereDefinition::copy(DefinitionNode *_destination) const { DefinitionNode::copy(_destination); - AtmosphereDefinition *destination = (AtmosphereDefinition *)_destination; + AtmosphereDefinition *destination = static_cast(_destination); + if (destination) { + destination->model = model; + destination->sun_color = sun_color; + destination->dome_lighting = dome_lighting; + destination->stars = stars; - destination->model = model; - destination->sun_color = sun_color; - destination->dome_lighting = dome_lighting; - destination->moon_radius = moon_radius; - destination->moon_theta = moon_theta; - destination->moon_phi = moon_phi; - destination->stars = stars; - - destination->validate(); + destination->validate(); + } } void AtmosphereDefinition::setDayTime(double value) { - daytime->setValue(value); + sun->propTheta()->setValue((value + 0.75) * M_2PI); } void AtmosphereDefinition::setDayTime(int hour, int minute, int second) { setDayTime(to_double(hour) / 24.0 + to_double(minute) / 1440.0 + to_double(second) / 86400.0); } -void AtmosphereDefinition::getHMS(int *hour, int *minute, int *second) const { - double value = daytime->getValue(); +double AtmosphereDefinition::getDaytime() const { + double value = (sun->propTheta()->getValue() / M_2PI) - 0.75; if (value >= 0.0) { value = fmod(value, 1.0); } else { value = 1.0 - fmod(-value, 1.0); } - value *= 86400.0; - *hour = value / 3600.0; - value -= 3600.0 * *hour; - *minute = value / 60.0; - *second = value - *minute * 60.0; + return value; +} + +void AtmosphereDefinition::getHMS(int *hour, int *minute, int *second) const { + double value = getDaytime() * 86400.0; + *hour = round_to_int(value / 3600.0); + value -= 3600.0 * to_double(*hour); + *minute = round_to_int(value / 60.0); + *second = round_to_int(value - to_double(*minute) * 60.0); } void AtmosphereDefinition::applyPreset(AtmospherePreset preset, RandomGenerator &random) { @@ -106,10 +100,10 @@ void AtmosphereDefinition::applyPreset(AtmospherePreset preset, RandomGenerator sun_color.g = 0.95; sun_color.b = 0.9; sun_color.a = 1.0; - sun_radius->setValue(0.8); - moon_radius = 1.0; - moon_theta = 0.3; - moon_phi = 0.5; + sun->propRadius()->setValue(1.0); + moon->propRadius()->setValue(1.0); + moon->propPhi()->setValue(0.5); + moon->propTheta()->setValue(0.3); model = ATMOSPHERE_MODEL_BRUNETON; @@ -139,8 +133,6 @@ void AtmosphereDefinition::applyPreset(AtmospherePreset preset, RandomGenerator humidity->setValue(0.9); dome_lighting = 0.05; break; - default: - ; } generateStars(2000, random); diff --git a/src/definition/AtmosphereDefinition.h b/src/definition/AtmosphereDefinition.h index 4ef63a5..70d93f0 100644 --- a/src/definition/AtmosphereDefinition.h +++ b/src/definition/AtmosphereDefinition.h @@ -31,7 +31,6 @@ class DEFINITIONSHARED_EXPORT AtmosphereDefinition : public DefinitionNode { public: AtmosphereDefinition(DefinitionNode *parent); - virtual ~AtmosphereDefinition(); virtual void save(PackStream *stream) const override; virtual void load(PackStream *stream) override; @@ -41,15 +40,15 @@ class DEFINITIONSHARED_EXPORT AtmosphereDefinition : public DefinitionNode { inline GodRaysDefinition *childGodRays() const { return godrays; } - inline FloatNode *propDayTime() const { - return daytime; + inline CelestialBodyDefinition *childSun() const { + return sun; + } + inline CelestialBodyDefinition *childMoon() const { + return moon; } inline FloatNode *propHumidity() const { return humidity; } - inline FloatNode *propSunRadius() const { - return sun_radius; - } /** * Set the daytime from a 0.0-1.0 value. @@ -59,6 +58,10 @@ class DEFINITIONSHARED_EXPORT AtmosphereDefinition : public DefinitionNode { * Set the daytime from hour/minute/second info. */ void setDayTime(int hour, int minute = 0, int second = 0); + /** + * Get the daytime info, in 0.0-1.0 value. + */ + double getDaytime() const; /** * Get the daytime info, in hour/minute/second. */ @@ -73,17 +76,13 @@ class DEFINITIONSHARED_EXPORT AtmosphereDefinition : public DefinitionNode { Color sun_color; double dome_lighting; - double moon_radius; - double moon_theta; - double moon_phi; - vector stars; private: GodRaysDefinition *godrays; + CelestialBodyDefinition *sun; + CelestialBodyDefinition *moon; FloatNode *humidity; - FloatNode *daytime; - FloatNode *sun_radius; }; } } diff --git a/src/definition/CelestialBodyDefinition.cpp b/src/definition/CelestialBodyDefinition.cpp new file mode 100644 index 0000000..3777868 --- /dev/null +++ b/src/definition/CelestialBodyDefinition.cpp @@ -0,0 +1,18 @@ +#include "CelestialBodyDefinition.h" + +#include "Vector3.h" +#include "FloatNode.h" + +CelestialBodyDefinition::CelestialBodyDefinition(DefinitionNode *parent, const string &name) + : DefinitionNode(parent, name) { + phi = new FloatNode(this, "phi"); + theta = new FloatNode(this, "theta"); + radius = new FloatNode(this, "radius"); +} + +Vector3 CelestialBodyDefinition::getDirection() const { + VectorSpherical spc = {1.0, theta->getValue(), -phi->getValue()}; + return Vector3(spc); +} + +// VectorSpherical moon_location_s = {MOON_DISTANCE_SCALED, atmosphere->moon_theta, -atmosphere->moon_phi}; diff --git a/src/definition/CelestialBodyDefinition.h b/src/definition/CelestialBodyDefinition.h new file mode 100644 index 0000000..9d86a98 --- /dev/null +++ b/src/definition/CelestialBodyDefinition.h @@ -0,0 +1,38 @@ +#ifndef CELESTIALBODYDEFINITION_H +#define CELESTIALBODYDEFINITION_H + +#include "definition_global.h" + +#include "DefinitionNode.h" + +namespace paysages { +namespace definition { + +class DEFINITIONSHARED_EXPORT CelestialBodyDefinition : public DefinitionNode { + public: + CelestialBodyDefinition(DefinitionNode *parent, const string &name); + + inline FloatNode *propPhi() const { + return phi; + } + inline FloatNode *propTheta() const { + return theta; + } + inline FloatNode *propRadius() const { + return radius; + } + + /** + * Get the normalized direction toward the celestial body (from the center of the earth). + */ + Vector3 getDirection() const; + + private: + FloatNode *phi; + FloatNode *theta; + FloatNode *radius; +}; +} +} + +#endif // CELESTIALBODYDEFINITION_H diff --git a/src/definition/TimeManager.cpp b/src/definition/TimeManager.cpp index 2455877..5ad2d56 100644 --- a/src/definition/TimeManager.cpp +++ b/src/definition/TimeManager.cpp @@ -14,7 +14,7 @@ TimeManager::TimeManager() { void TimeManager::moveForward(Scenery *scenery, double amount) { // Move the sun - scenery->getAtmosphere()->setDayTime(scenery->getAtmosphere()->propDayTime()->getValue() + amount); + scenery->getAtmosphere()->setDayTime(scenery->getAtmosphere()->getDaytime() + amount); // Move the clouds int n = scenery->getClouds()->getLayerCount(); diff --git a/src/definition/definition_global.h b/src/definition/definition_global.h index efc710e..4ec2e55 100644 --- a/src/definition/definition_global.h +++ b/src/definition/definition_global.h @@ -32,6 +32,7 @@ class LayersDiff; class CloudsDefinition; class CloudLayerDefinition; class AtmosphereDefinition; +class CelestialBodyDefinition; class GodRaysDefinition; class TexturesDefinition; class TextureLayerDefinition; diff --git a/src/interface/commandline/tests.cpp b/src/interface/commandline/tests.cpp index ff1eed9..7981aed 100644 --- a/src/interface/commandline/tests.cpp +++ b/src/interface/commandline/tests.cpp @@ -270,7 +270,7 @@ static void testAtmosphereBruneton() { for (int i = 0; i <= 60; i++) { double daytime = (i < 40) ? (0.24 + 0.0005 * to_double(i)) : (0.26 + 0.005 * to_double(i - 40)); - scenery.getAtmosphere()->propDayTime()->setValue(daytime); + scenery.getAtmosphere()->setDayTime(daytime); startTestRender(&renderer, "atmosphere_bruneton", i); } } diff --git a/src/interface/modeler/AtmosphereModeler.cpp b/src/interface/modeler/AtmosphereModeler.cpp index e17d94e..a63783f 100644 --- a/src/interface/modeler/AtmosphereModeler.cpp +++ b/src/interface/modeler/AtmosphereModeler.cpp @@ -3,19 +3,15 @@ #include "MainModelerWindow.h" #include "Scenery.h" #include "AtmosphereDefinition.h" -#include "FloatPropertyBind.h" -AtmosphereModeler::AtmosphereModeler(MainModelerWindow *main) { - prop_daytime = - new FloatPropertyBind(main, "atmosphere_daytime", "value", main->getScenery()->getAtmosphere()->propDayTime()); - prop_humidity = new FloatPropertyBind(main, "atmosphere_humidity", "value", - main->getScenery()->getAtmosphere()->propHumidity()); - prop_sun_radius = new FloatPropertyBind(main, "atmosphere_sun_radius", "value", - main->getScenery()->getAtmosphere()->propSunRadius()); -} +AtmosphereModeler::AtmosphereModeler(MainModelerWindow *main) : BaseModelerTool(main) { + addFloatBinding("atmosphere_humidity", "value", "/atmosphere/humidity"); + addFloatBinding("atmosphere_sun_direction", "phi", "/atmosphere/sun/phi"); + addFloatBinding("atmosphere_sun_direction", "theta", "/atmosphere/sun/theta"); + addFloatBinding("atmosphere_sun_radius", "value", "/atmosphere/sun/radius"); + addFloatBinding("atmosphere_moon_direction", "phi", "/atmosphere/moon/phi"); + addFloatBinding("atmosphere_moon_direction", "theta", "/atmosphere/moon/theta"); + // addFloatBinding("atmosphere_moon_radius", "value", "/atmosphere/moon/radius"); -AtmosphereModeler::~AtmosphereModeler() { - delete prop_daytime; - delete prop_humidity; - delete prop_sun_radius; + main->setQmlProperty("atmosphere_daytime", "value", main->getScenery()->getAtmosphere()->getDaytime()); } diff --git a/src/interface/modeler/AtmosphereModeler.h b/src/interface/modeler/AtmosphereModeler.h index 8615e1b..88ce375 100644 --- a/src/interface/modeler/AtmosphereModeler.h +++ b/src/interface/modeler/AtmosphereModeler.h @@ -3,18 +3,14 @@ #include "modeler_global.h" +#include "BaseModelerTool.h" + namespace paysages { namespace modeler { -class AtmosphereModeler { +class AtmosphereModeler : protected BaseModelerTool { public: AtmosphereModeler(MainModelerWindow *main); - ~AtmosphereModeler(); - - private: - FloatPropertyBind *prop_daytime; - FloatPropertyBind *prop_humidity; - FloatPropertyBind *prop_sun_radius; }; } } diff --git a/src/interface/modeler/BaseModelerTool.cpp b/src/interface/modeler/BaseModelerTool.cpp new file mode 100644 index 0000000..0b0d129 --- /dev/null +++ b/src/interface/modeler/BaseModelerTool.cpp @@ -0,0 +1,39 @@ +#include "BaseModelerTool.h" + +#include "MainModelerWindow.h" +#include "Scenery.h" +#include "IntNode.h" +#include "IntPropertyBind.h" +#include "FloatNode.h" +#include "FloatPropertyBind.h" +#include "Logs.h" + +class BaseModelerTool::pimpl { + public: + vector> int_bindings; + vector> float_bindings; +}; + +BaseModelerTool::BaseModelerTool(MainModelerWindow *main) : impl(new pimpl), main(main) { +} + +BaseModelerTool::~BaseModelerTool() { +} + +void BaseModelerTool::addIntBinding(const string &object, const string &property, const string &path) { + auto node = static_cast(main->getScenery()->findByPath(path)); + if (node) { + impl->int_bindings.push_back(make_unique(main, object, property, node)); + } else { + Logs::error("UI") << "Can't find int node for binding : " << path << endl; + } +} + +void BaseModelerTool::addFloatBinding(const string &object, const string &property, const string &path) { + auto node = static_cast(main->getScenery()->findByPath(path)); + if (node) { + impl->float_bindings.push_back(make_unique(main, object, property, node)); + } else { + Logs::error("UI") << "Can't find float node for binding : " << path << endl; + } +} diff --git a/src/interface/modeler/BaseModelerTool.h b/src/interface/modeler/BaseModelerTool.h new file mode 100644 index 0000000..8efeab1 --- /dev/null +++ b/src/interface/modeler/BaseModelerTool.h @@ -0,0 +1,35 @@ +#ifndef BASEMODELERTOOL_H +#define BASEMODELERTOOL_H + +#include "modeler_global.h" + +#include + +namespace paysages { +namespace modeler { + +class BaseModelerTool { + public: + BaseModelerTool(MainModelerWindow *main); + virtual ~BaseModelerTool(); + + /** + * Add an automated two-way binding between a QML int property and a scenery IntNode. + */ + void addIntBinding(const string &object, const string &property, const string &path); + + /** + * Add an automated two-way binding between a QML int property and a scenery IntNode. + */ + void addFloatBinding(const string &object, const string &property, const string &path); + + private: + class pimpl; + unique_ptr impl; + + MainModelerWindow *main; +}; +} +} + +#endif // BASEMODELERTOOL_H diff --git a/src/interface/modeler/FloatPropertyBind.cpp b/src/interface/modeler/FloatPropertyBind.cpp index e110b40..2b411f2 100644 --- a/src/interface/modeler/FloatPropertyBind.cpp +++ b/src/interface/modeler/FloatPropertyBind.cpp @@ -6,27 +6,30 @@ #include -FloatPropertyBind::FloatPropertyBind(MainModelerWindow *window, const QString &object_name, - const QString &property_name, FloatNode *node) +FloatPropertyBind::FloatPropertyBind(MainModelerWindow *window, const string &object_name, const string &property_name, + FloatNode *node) : QObject(window), node(node), property(property_name) { item = window->findQmlObject(object_name); if (item) { node->addWatcher(this, true); - connect(item, SIGNAL(changed(double)), this, SLOT(propertyChanged(double))); + string signal_name("2" + property_name + "Changed()"); + connect(item, signal_name.c_str(), this, SLOT(propertyChanged())); } else { item = NULL; - Logs::error("UI") << "Can't find object :" << object_name.toStdString() << endl; + Logs::error("UI") << "Can't find object :" << object_name << endl; } } void FloatPropertyBind::nodeChanged(const DefinitionNode *, const DefinitionDiff *) { if (item) { - item->setProperty(property.toLocal8Bit(), node->getValue()); + item->setProperty(property.c_str(), node->getValue()); } } -void FloatPropertyBind::propertyChanged(double value) { - if (fabs(value - node->getValue()) > 0.00000001) { +void FloatPropertyBind::propertyChanged() { + bool ok; + double value = item->property(property.c_str()).toDouble(&ok); + if (ok and fabs(value - node->getValue()) > 0.00000001) { node->setValue(value); } } diff --git a/src/interface/modeler/FloatPropertyBind.h b/src/interface/modeler/FloatPropertyBind.h index 84f5bac..e1e1f23 100644 --- a/src/interface/modeler/FloatPropertyBind.h +++ b/src/interface/modeler/FloatPropertyBind.h @@ -17,17 +17,17 @@ namespace modeler { class FloatPropertyBind : public QObject, public DefinitionWatcher { Q_OBJECT public: - FloatPropertyBind(MainModelerWindow *window, const QString &object_name, const QString &property_name, + FloatPropertyBind(MainModelerWindow *window, const string &object_name, const string &property_name, FloatNode *node); virtual void nodeChanged(const DefinitionNode *node, const DefinitionDiff *diff) override; private slots: - void propertyChanged(double value); + void propertyChanged(); private: FloatNode *node; - QString property; + string property; QObject *item; }; } diff --git a/src/interface/modeler/IntPropertyBind.cpp b/src/interface/modeler/IntPropertyBind.cpp index 659477b..b7b2cb4 100644 --- a/src/interface/modeler/IntPropertyBind.cpp +++ b/src/interface/modeler/IntPropertyBind.cpp @@ -4,27 +4,30 @@ #include "IntNode.h" #include "Logs.h" -IntPropertyBind::IntPropertyBind(MainModelerWindow *window, const QString &object_name, const QString &property_name, +IntPropertyBind::IntPropertyBind(MainModelerWindow *window, const string &object_name, const string &property_name, IntNode *node) : QObject(window), node(node), property(property_name) { item = window->findQmlObject(object_name); if (item) { node->addWatcher(this, true); - connect(item, SIGNAL(changed(int)), this, SLOT(propertyChanged(int))); + string signal_name("2" + property_name + "Changed()"); + connect(item, signal_name.c_str(), this, SLOT(propertyChanged())); } else { item = NULL; - Logs::error("UI") << "Can't find object :" << object_name.toStdString() << endl; + Logs::error("UI") << "Can't find object :" << object_name << endl; } } void IntPropertyBind::nodeChanged(const DefinitionNode *, const DefinitionDiff *) { if (item) { - item->setProperty(property.toLocal8Bit(), node->getValue()); + item->setProperty(property.c_str(), node->getValue()); } } -void IntPropertyBind::propertyChanged(int value) { - if (value != node->getValue()) { +void IntPropertyBind::propertyChanged() { + bool ok; + int value = item->property(property.c_str()).toInt(&ok); + if (ok and value != node->getValue()) { node->setValue(value); } } diff --git a/src/interface/modeler/IntPropertyBind.h b/src/interface/modeler/IntPropertyBind.h index 7824aba..3f89c5e 100644 --- a/src/interface/modeler/IntPropertyBind.h +++ b/src/interface/modeler/IntPropertyBind.h @@ -17,16 +17,16 @@ namespace modeler { class IntPropertyBind : public QObject, public DefinitionWatcher { Q_OBJECT public: - IntPropertyBind(MainModelerWindow *window, const QString &object_name, const QString &property_name, IntNode *node); + IntPropertyBind(MainModelerWindow *window, const string &object_name, const string &property_name, IntNode *node); virtual void nodeChanged(const DefinitionNode *node, const DefinitionDiff *diff) override; private slots: - void propertyChanged(int value); + void propertyChanged(); private: IntNode *node; - QString property; + string property; QObject *item; }; } diff --git a/src/interface/modeler/MainModelerWindow.cpp b/src/interface/modeler/MainModelerWindow.cpp index 3e0bb28..0228a4a 100644 --- a/src/interface/modeler/MainModelerWindow.cpp +++ b/src/interface/modeler/MainModelerWindow.cpp @@ -60,39 +60,39 @@ MainModelerWindow::~MainModelerWindow() { delete scenery; } -QObject *MainModelerWindow::findQmlObject(const QString &objectName) { +QObject *MainModelerWindow::findQmlObject(const string &objectName) { if (objectName == "ui" || objectName == "root") { return rootObject(); } else { - return rootObject()->findChild(objectName); + return rootObject()->findChild(QString::fromStdString(objectName)); } } -void MainModelerWindow::setQmlProperty(const QString &objectName, const QString &propertyName, const QVariant &value) { +void MainModelerWindow::setQmlProperty(const string &objectName, const string &propertyName, const QVariant &value) { QObject *item = findQmlObject(objectName); if (item) { - item->setProperty(propertyName.toLocal8Bit(), value); + item->setProperty(propertyName.c_str(), value); } else { - Logs::error("UI") << "QML object not found :" << objectName.toStdString() << endl; + Logs::error("UI") << "QML object not found :" << objectName << endl; } } -void MainModelerWindow::connectQmlSignal(const QString &objectName, const char *signal, const QObject *receiver, +void MainModelerWindow::connectQmlSignal(const string &objectName, const char *signal, const QObject *receiver, const char *method) { QObject *item = findQmlObject(objectName); if (item) { connect(item, signal, receiver, method); } else { - Logs::error("UI") << "QML object not found :" << objectName.toStdString() << endl; + Logs::error("UI") << "QML object not found :" << objectName << endl; } } -QString MainModelerWindow::getState() const { - return rootObject()->property("state").toString(); +string MainModelerWindow::getState() const { + return rootObject()->property("state").toString().toStdString(); } -void MainModelerWindow::setState(const QString &stateName) { - rootObject()->setProperty("state", stateName); +void MainModelerWindow::setState(const string &stateName) { + rootObject()->setProperty("state", QString::fromStdString(stateName)); } void MainModelerWindow::newFile() { diff --git a/src/interface/modeler/MainModelerWindow.h b/src/interface/modeler/MainModelerWindow.h index 8850865..939a26f 100644 --- a/src/interface/modeler/MainModelerWindow.h +++ b/src/interface/modeler/MainModelerWindow.h @@ -14,12 +14,12 @@ class MainModelerWindow : public QQuickView { MainModelerWindow(); virtual ~MainModelerWindow(); - QObject *findQmlObject(const QString &objectName); - void setQmlProperty(const QString &objectName, const QString &propertyName, const QVariant &value); - void connectQmlSignal(const QString &objectName, const char *signal, const QObject *receiver, const char *method); + QObject *findQmlObject(const string &objectName); + void setQmlProperty(const string &objectName, const string &propertyName, const QVariant &value); + void connectQmlSignal(const string &objectName, const char *signal, const QObject *receiver, const char *method); - QString getState() const; - void setState(const QString &stateName); + string getState() const; + void setState(const string &stateName); inline Scenery *getScenery() const { return scenery; diff --git a/src/interface/modeler/ModelerCameras.cpp b/src/interface/modeler/ModelerCameras.cpp index b8ffab5..2dca938 100644 --- a/src/interface/modeler/ModelerCameras.cpp +++ b/src/interface/modeler/ModelerCameras.cpp @@ -62,7 +62,8 @@ void ModelerCameras::startSunTool() { current->copy(tool); active = tool; - parent->getScenery()->getAtmosphere()->propDayTime()->addWatcher(this, true); + // FIXME + // parent->getScenery()->getAtmosphere()->propDayTime()->addWatcher(this, true); } void ModelerCameras::endTool() { diff --git a/src/interface/modeler/RenderProcess.cpp b/src/interface/modeler/RenderProcess.cpp index 21f477e..f2f7085 100644 --- a/src/interface/modeler/RenderProcess.cpp +++ b/src/interface/modeler/RenderProcess.cpp @@ -149,7 +149,7 @@ void RenderProcess::stopRender() { renderer->interrupt(); } else { destination->hide(); - window->setState(window->rootObject()->property("previous_state").toString()); + window->setState(window->rootObject()->property("previous_state").toString().toStdString()); } } diff --git a/src/interface/modeler/modeler_global.h b/src/interface/modeler/modeler_global.h index c007929..68a170a 100644 --- a/src/interface/modeler/modeler_global.h +++ b/src/interface/modeler/modeler_global.h @@ -10,6 +10,8 @@ namespace modeler { class MainModelerWindow; class OpenGLView; +class BaseModelerTool; + class AtmosphereModeler; class WaterModeler; diff --git a/src/interface/modeler/qml/BaseSlider.qml b/src/interface/modeler/qml/BaseSlider.qml index f9338d6..038c41a 100644 --- a/src/interface/modeler/qml/BaseSlider.qml +++ b/src/interface/modeler/qml/BaseSlider.qml @@ -2,7 +2,5 @@ import QtQuick 2.2 import QtQuick.Controls 1.2 Slider { - signal changed(real value) - onValueChanged: changed(value) opacity: enabled ? 1.0 : 0.1 } diff --git a/src/interface/modeler/qml/PanelAtmosphereDaytime.qml b/src/interface/modeler/qml/PanelAtmosphereDaytime.qml index b943310..e7eded7 100644 --- a/src/interface/modeler/qml/PanelAtmosphereDaytime.qml +++ b/src/interface/modeler/qml/PanelAtmosphereDaytime.qml @@ -1,148 +1,49 @@ import QtQuick 2.0 -import QtQuick.Controls 1.1 -import QtQuick.Layouts 1.1 BasePanel { - id: daytime - width: 100 + width: 200 - objectName: "atmosphere_daytime" - default property real value: day_night.value == 2 ? 0.0 : slider.value * 0.54 + 0.23; - signal changed(real value) + Column { + anchors.centerIn: parent + width: parent.width - 10 + spacing: 30 - onValueChanged: { - changed(value); - day_night.value = (value >= 0.23 && value <= 0.77) ? 1 : 2; - if (day_night.value == 1) - { - slider.value = (value - 0.23) / 0.54; + Text { + text: "Sun location in the sky" + anchors.horizontalCenter: parent.horizontalCenter + } + + WidgetSphericalCoords { + id: atmosphere_sun_direction + objectName: "atmosphere_sun_direction" + anchors.horizontalCenter: parent.horizontalCenter + icon: "images/icon_atmosphere_day.png" + width: parent.width + } + + Text { + text: "Time of day" + anchors.horizontalCenter: parent.horizontalCenter + } + + WidgetDayTime { + id: atmosphere_daytime + objectName: "atmosphere_daytime" + anchors.horizontalCenter: parent.horizontalCenter + onValueChanged: atmosphere_sun_direction.theta = (atmosphere_daytime.value + 0.75) * Math.PI * 2.0 + } + + Text { + text: "Moon location in the sky" + anchors.horizontalCenter: parent.horizontalCenter + } + + WidgetSphericalCoords { + id: atmosphere_moon_direction + objectName: "atmosphere_moon_direction" + icon: "images/icon_atmosphere_night.png" + width: parent.width + anchors.horizontalCenter: parent.horizontalCenter } } - - ColumnLayout - { - height: parent.height - anchors.horizontalCenter: parent.horizontalCenter - spacing: 20 - - Item {height: 1} - - BaseChoice { - id: day_night - - Layout.alignment: Qt.AlignHCenter - spacing: 10 - width: 90 - height: 40 - - BaseChoiceItem { - icon: "images/icon_atmosphere_day.png" - value: 1 - checked: true - } - BaseChoiceItem { - icon: "images/icon_atmosphere_night.png" - value: 2 - } - } - - BaseSlider { - id: slider - orientation: Qt.Vertical - Layout.maximumWidth: 15 - Layout.fillHeight: true - Layout.alignment: Qt.AlignHCenter - } - - Grid { - id: clock - property int hour: daytime.value * 86400 / 3600 - property int minute: (daytime.value * 86400 - 3600 * hour) / 60 - property int second: daytime.value * 86400 - 3600 * hour - 60 * minute - rows: 3 - columns: 5 - rowSpacing: 4 - - ClickableImage { - width: 20 - height: 10 - source: "qrc:/images/arrow_up.png" - onClicked: slider.value += (1.0 / 24.0) / 0.54 - } - Item {width: 1; height: 1} - ClickableImage { - width: 20 - height: 10 - source: "qrc:/images/arrow_up.png" - onClicked: slider.value += (1.0 / 1440.0) / 0.54 - } - Item {width: 1; height: 1} - ClickableImage { - width: 20 - height: 10 - source: "qrc:/images/arrow_up.png" - onClicked: slider.value += (1.0 / 86400.0) / 0.54 - } - - Text { - text: (clock.hour > 9 ? "" : "0") + clock.hour.toString() - font.pixelSize: 14 - } - Text { - text: " : " - font.pixelSize: 14 - } - Text { - text: (clock.minute > 9 ? "" : "0") + clock.minute.toString() - font.pixelSize: 14 - } - Text { - text: " : " - font.pixelSize: 14 - } - Text { - text: (clock.second > 9 ? "" : "0") + clock.second.toString() - font.pixelSize: 14 - } - - ClickableImage { - width: 20 - height: 10 - source: "qrc:/images/arrow_down.png" - onClicked: slider.value -= (1.0 / 24.0) / 0.54 - } - Item {width: 1; height: 1} - ClickableImage { - width: 20 - height: 10 - source: "qrc:/images/arrow_down.png" - onClicked: slider.value -= (1.0 / 1440.0) / 0.54 - } - Item {width: 1; height: 1} - ClickableImage { - width: 20 - height: 10 - source: "qrc:/images/arrow_down.png" - onClicked: slider.value -= (1.0 / 86400.0) / 0.54 - } - } - - Item {height: 1} - } - - states: [ - State { - name: "night" - when: day_night.value == 2 - PropertyChanges { - target: slider - enabled: false - } - PropertyChanges { - target: clock - enabled: false - } - } - - ] } diff --git a/src/interface/modeler/qml/PanelPictureChoice.qml b/src/interface/modeler/qml/PanelPictureChoice.qml index d347a0a..372cbe3 100644 --- a/src/interface/modeler/qml/PanelPictureChoice.qml +++ b/src/interface/modeler/qml/PanelPictureChoice.qml @@ -8,7 +8,6 @@ BasePanel { property alias items: container.children property int value: -1 width: items[0].width + 10 - signal changed(int value) ExclusiveGroup { id: exclusive_item @@ -30,7 +29,6 @@ BasePanel { exclusive_item.current = null; } } - changed(value); } onItemsChanged: { diff --git a/src/interface/modeler/qml/WidgetDayTime.qml b/src/interface/modeler/qml/WidgetDayTime.qml new file mode 100644 index 0000000..a343af2 --- /dev/null +++ b/src/interface/modeler/qml/WidgetDayTime.qml @@ -0,0 +1,77 @@ +import QtQuick 2.0 + +Grid { + id: clock + + property real value + + property int hour: value * 86400 / 3600 + property int minute: (value * 86400 - 3600 * hour) / 60 + property int second: value * 86400 - 3600 * hour - 60 * minute + rows: 3 + columns: 5 + rowSpacing: 4 + + ClickableImage { + width: 20 + height: 10 + source: "images/arrow_up.png" + onClicked: value += 1.0 / 24.0 + } + Item {width: 1; height: 1} + ClickableImage { + width: 20 + height: 10 + source: "images/arrow_up.png" + onClicked: value += 1.0 / 1440.0 + } + Item {width: 1; height: 1} + ClickableImage { + width: 20 + height: 10 + source: "images/arrow_up.png" + onClicked: value += 1.0 / 86400.0 + } + + Text { + text: (clock.hour > 9 ? "" : "0") + clock.hour.toString() + font.pixelSize: 14 + } + Text { + text: " : " + font.pixelSize: 14 + } + Text { + text: (clock.minute > 9 ? "" : "0") + clock.minute.toString() + font.pixelSize: 14 + } + Text { + text: " : " + font.pixelSize: 14 + } + Text { + text: (clock.second > 9 ? "" : "0") + clock.second.toString() + font.pixelSize: 14 + } + + ClickableImage { + width: 20 + height: 10 + source: "images/arrow_down.png" + onClicked: value -= 1.0 / 24.0 + } + Item {width: 1; height: 1} + ClickableImage { + width: 20 + height: 10 + source: "images/arrow_down.png" + onClicked: value -= 1.0 / 1440.0 + } + Item {width: 1; height: 1} + ClickableImage { + width: 20 + height: 10 + source: "images/arrow_down.png" + onClicked: value -= 1.0 / 86400.0 + } +} diff --git a/src/interface/modeler/qml/WidgetSphericalCoords.qml b/src/interface/modeler/qml/WidgetSphericalCoords.qml new file mode 100644 index 0000000..355c7ea --- /dev/null +++ b/src/interface/modeler/qml/WidgetSphericalCoords.qml @@ -0,0 +1,45 @@ +import QtQuick 2.0 + +// Widget to edit spherical coordinates +Row { + id: widget + property real theta: 0 + property real phi: 0 + property string icon + + height: width / 2 + + Item { + height: parent.height + width: height + Image { + source: "images/bg_phi_coord.png" + anchors.fill: parent + } + Image { + source: widget.icon + width: parent.width / 10 + height: parent.width / 10 + anchors.centerIn: parent + anchors.horizontalCenterOffset: width * 4 * Math.cos(phi) * Math.cos(theta) + anchors.verticalCenterOffset: -width * 4 * Math.sin(phi) * Math.cos(theta) + } + } + + Item { + height: parent.height + width: height + Image { + source: "images/bg_theta_coord.png" + anchors.fill: parent + } + Image { + source: widget.icon + width: parent.width / 10 + height: parent.width / 10 + anchors.centerIn: parent + anchors.horizontalCenterOffset: width * 4.5 * Math.cos(theta) + anchors.verticalCenterOffset: -width * 4.5 * Math.sin(theta) + } + } +} diff --git a/src/interface/modeler/qml/app.qrc b/src/interface/modeler/qml/app.qrc index cea9132..6944240 100644 --- a/src/interface/modeler/qml/app.qrc +++ b/src/interface/modeler/qml/app.qrc @@ -53,5 +53,9 @@ images/icon_render_final.png images/icon_cancel.png images/icon_sun_radius.png + images/bg_phi_coord.png + WidgetSphericalCoords.qml + images/bg_theta_coord.png + WidgetDayTime.qml diff --git a/src/interface/modeler/qml/images/bg_phi_coord.png b/src/interface/modeler/qml/images/bg_phi_coord.png new file mode 100644 index 0000000000000000000000000000000000000000..a26bacecdc2d9482f5d9445295d89d4b9e57283a GIT binary patch literal 3304 zcmZ8k30M=?8vXA~5&}tB)BpiwQHxRZIgkoiK_i>kiUmcMx{VbAMNlhh6$J-S+@hj& z3DyOqrM6PcGm2tChPqV^688Wqh;5{biUmB^cj6!OMWL~&0HXffg<#KKd)#QYWKvkLS%cVF=<^Y= z{r*J&@w!Pt6C#(_J-PGAVy7`;zEbyW^~3$=^eWqprKduhcCUbmCxwmDL)&}aAY9-wRiesgN<28<4fuJI+U+3;n?$5sz{7Iv0asTGY*6X49+xj%L6^Ays)ez`Zx9KuN< zO)ZLW%(wnS5p(nCsR$n&`$c@3-`G4_ese^U7>NaglB@>URpcC~3-TYtROJTl`*9kN zsu1jP2zr9!)_{?R<9Sqf&d#*J^z5vv97u9T>J(^4guU3wU?-%L#IoaSoUaa+3&m1{ zLP)=s*eoSq3z0e#y|zGVgqjsjzBxp*504U{=JDO@0&l%aBH9NNnpdi5QNE82o4CMm zIBhx<79jsk5Yj)}x#J{{I__|LMRrCAJlHHV)D!j#FEZmM!h>piLmLjxFg+7tzF&fc zDl^uVd45Zz5eexqfyT;|4I%T8iEkOCK&G6DA26M#H|&+sIYPR;f-spAF*?wA5Sp;C zCN(HRpwJU^0#xhU1iKor_%9hDnV^(ZHdUsUJ`n$90e(W8OlaN4m=`{a6coR@|SJ&tyj^F5?_Nb)839NU3^jw$tK98(%-h&o|hdzGqIK6Vgx3 z=>cv`=TJuK!i^6P3?w|(rVW@aL z=xb_cJ7?P2g5uhlOK&<%u}JeB5mN=4A9j{y^~{umrp&vM320S=J{lGKf<6`%%Yj;0 z*_6O;MC{}j;Zw^u4;uiwXz&0~oGjd(ZN{og(M0FsCw8o#Eo&U~tmHvD48w!DCn z%6RiRp!f{N#(t?`MCAeQ{y`7&;vT8fFG#%V) z9!=?uh^_(EDOeT`nkVDizLz6b&>}HsWQvS2_Mm^=HFE;VNQ{m)piuQJwgyf2%d#v1 zIBK8RF*2FfZ#l$OrI+O6tmG~}9pXO1$^qO~9q>p5EvnBznr${aedzllrjkFfRYgL) zB2JpVsB{i|oRG6s3-7X)MbpLP8xcyjcdOA{~!eT2T0eZ7LTJq^dIw>Lw_eJKo9$RBgW@|PC95{e+F zLRy|u36rY_I#M9Epk3ym+;oNWarASBfDSqz#N)7@&sbC>F?NVpO>x;k7E?{G+TcxN zs6wv`N8FII?F6h|PBN1NQZEX`fEMtzTaUn@)3OtF%&hSw<&}*UQ(kX>`CJNlYk%7z zu?J$WB?o0lQT(TZgL2)JJ9#l*0@YI+E<{7*;?XCPS+G_Dsbr?zt|~cz4mE$4QOh7# z1_TTYEm?!>hS%rQsy~g{^+ecsq7BiS3$+g|9QvLKTiX}ZA8|ocRY&<>Kw*UO zg#zv-*LY*S2Gld%J)_`y`o6W^G{{R436lt;Sqv;WKKj9F2|d1-&zR*kzbhwqW;1$3 z%CG8=Ucr2Vy=fO3v1gKx;UR3pY(o37<5+^;I5IB*kAQI0T4{j}45?#KK8yPgG3WYI z)el-YDpzrWuRVL35int~U*P_~VLG`(m~J44ehp1|(oM=W#vH zzU|p7Mz>UX=y*!U#=5%WI;j*Epu$u3adKU;A zM|G|=z~q-pZ8>R-n1z!iy&A7EZ&eYl(r@A4s533;N|E?|JsKB5*DM;0J9csir!m3? z!nhk(YxC{G6E2(^prx61Q~~;1`8WMtK1bBKU3yOT`)_HEJ4-O@Y7?=TgB)8wUA3P7 z*GoNzHRmv_Mc^FQ^i*Q3$wbXb^Uve`p>IxZ3l}vd8ApEzJ7-<=#1nvr-+*=FjpN$+i7@=st~nT5h~K>{d(mU= zZNtA8;B~wJ3(%p)wAmaVWh7Mkr@{7xmEV!Z=?a)Wu$qcCfMMj_-p?yexRKVwMjYVQ zuIookx|+}aDn2D;OZK2cO&_Z`6-tKn+C4rkkueb~;;;k|OBgT2fcnzj`o1w1m#89( zJQ8P6Fz=}QASR^>)b}!UDQqbX=i??vLVXsp|G8Ur2T#*SX0y$VxhQd;4<>KTx->*W zesEEcnf9;>LR8_VzA7oYIO%d_X<WZ^D}^-6}{H3Fye8xH@L-2#is5NqWrcC?xKb z)e=TqF}q&^4sh{#ebfq{^H)ksv=fr1+rKwOwN6ANtmHzT7^ID}_YG zHE@+iD!%=*uaf*5{^2UJ^aE1Zu(-By@Ca_t&%%4Y`DM~fX?us;T9UcZsN&eg@XyhK z5oLU;~biL1h&qvhP_)KtSY;>yvLd!M^s6xJ$6tKx1-^<5K0aQmMuUhBUuR;2Gs0I6j z`&Wu)O%TO^qHeYKAC8(_0kx8^4FD>2?4Q#1XCgi*ZVFbNlqdfJrecV40@GoL8UmWb zbJ`U2TA)p7!XFxpejcEU1P>=r9P^4cbXka4^;w*?-p>b8r-6q%v`qz%;gEW5?*MkA zh+T!h#q7+p~$=h*yMh!dyCqGu5e?n#xR{s_SHD1 zi~&=)Zp<`Fq$iO2#B62ngZy$treR-sVy^Olh%T3rX^uFEGt|6}?K6O9g!G4=&9OYn z!NG7C-}^L&@u<;`v%;8+ASir3q1TP^6he0noDYX|{LMhS)Y6$G+p!q;$RJ5ULc5r- z59GHC2~8du5>_y(oxhPF&9IBrl#!wP3QQBW(T?z9Gn~f;SBAtnc1h9L{^t4UZw!7k z0LM;`BCtKq^M7??SdvwrYZmh;-MVjI2m8BWmmGALX*v@=y*?>0#g(aIgC)$tv#wEH zSL}Jz5ZR5isxeuR!wa0b+IOfmo118OEK2|jSwCLYZ?pegH6bFf&T#0?{QXk-l0=!; ziIu6>`b>Yk-pL?#-BE34aCOyG+ZcQq#(Su8UM73%<$M1lxZ6ebxQ>}a-It( M1y2bo381t72L^e@kpKVy literal 0 HcmV?d00001 diff --git a/src/interface/modeler/qml/images/bg_theta_coord.png b/src/interface/modeler/qml/images/bg_theta_coord.png new file mode 100644 index 0000000000000000000000000000000000000000..f7c9be2071626287a0a624c22beea16ba923fb26 GIT binary patch literal 10033 zcmdT~^;=Zovp-As(xo8C(p^e7!qTN6ASK=1u_~doOLw>kh;)O5AfR+f3X6&~EGjO@ z68HGM_qo5^zu=zd+2`z8-ZSsaJ2RgN=7o`g79|-g82|v3aBU3}0Dx@#`;ZWUzeLUV zW`Q?SU+sqh065ZcIt~D?p=uVoa=7NOH6Hr&{XAcuQjz&%L#RUky~JX=v~ zNZPRVjFF2tRx5NYYN^QLOo~B2{C=9uEYg))=Fd8!uSqV8XAN@#*bKEt-YVBi!6$^GSz6GK=}#aUPrK zqL!1b+8E5T(AmQt|>lWKLU1XWYUgm*EwL3>$!?Y(Tq*yz%J`=M=ZBa&$Wlc zXK#*8DZvf1IPalfN*T_Ix`mel`0K9woodb6vpjHoXN>24(w>Jn+22ucrg4lqa=m6o z&8lwTBDX1H9JZT;jK1%n+P30>?XA=eH!;y-8zBeMM;jT{Kl~$*)!)gwRI(IXKw{LiN7R7 zdh`99vUq(EwQ~nP7)uX|eP`9r`{S=}+2o1$*HdZsY>L zeB`B0@l^lr8P9LL9RwK3*}sN#j#{6}Oel_g$_Po4tTx%2bIRMOU5w+I-8Q$RtH9oqZb%UwZ(>o6{UTL-nU+)fKfjy9J9Uq(<1GW zScKwnHgsZ2$y7r=%=RFG0{Cu`K(eSCUi-0lqIq=v)Ppm&__IUX6PF}U$$GbgI(-U5 z{Ns11re@oO`)BJ%2?B@WT%m(fDMefx!S$g_o*r;DqW&81hLd1&{kOZ*ONZAxo&A$5 zJl=O!^~CA0Hm19Rfe@87%ldEe6fvB;VFPib;p?92LoKa;V#!swP7RK-1J&XZ@}{)A z;u^~Iyv0||%D(Q>Ip1hKt%8(_5RP9n&XIr3dt|oa&TxHZg7Ae@EwW?iM!o$@>K7Z; zXZK?%?qj=_vAYLE$N!O7j^n zzTE!mK%=6c$HmiG+AGSQR0NYrNQYEqefU$3>QzuoFo#`oeN`(u(`ugRYTZ_9o(SM1 zwbKb=+7b7JX;his$coXZETD!|wQfprWS^^l*UtCKPtpTSZ{MBAW};#yGLp}^gYEId{ksbX+48m8LCvfq0vnQ66 z-LIZZ`MXkv7$i4Y6PeAx*W1UXcU*;L;2Rhl4JFVOY#ip5N<`6-kb=V<9zFa zm`MeuFNw!2zpe2Q<;cX$wT>^s)scEt2yvy!fJV6k|5Qjn^DVyXbjcS4zJ0zEcVU;1 zGQ5p!g*!js?8-SU>AsLKVW}yG_M|0!>koJh=dGwVg`xI1Y6!R6C)3!~@c=5sNT=dz z0j{f<8baqE^&}w4B_0ADrHs1dGps*#8X(9V8Vd^_RBkHD02J)hi&4iEa0uW2(2-=A zNbp^1p8gvT__{mZ&806H!0put%rur1MhYi;P+{J9u14)!yMNd#7s<^k?nWvY`kXx& zAdo6<4NJuM@b#+PPdfJbMgO%mmelno`eQ&-A3PMn|I@iR>6;HVdueYR_Zr{n2nV32 z*#7(XJ#k+ADqY*aox`nOC290vx};dE|Mo_uKYQ6|?zRL%PTbZcZS4LZ7l(S2(uHxU zDgDZTwh@KOnNo9G*TSheuTa^?y^}6f^L5ETtb^qGDE)9%_GcujgO4=j88)iIg7hIo z?l`;^v8m5hy7tZ|WL2t*@V%_xQ7Cy*sFC?m=I@IXo8Q*NMqK6-Cc$$)mEYuZs3Ada zb-Fa{ZACcXb^2;^tfVabNmp-2G5@K{8APvaf4s&%;wM{XOW`pBu$ zvZn#Mkebi~K*ioW?Arr1{7mn-Lf(gw&b^aSw!nh59okSPNB#lz?b4PE{#~O;Wd_M& zh)jXo7D)t+f&UB@z0Wg?NVfhDGAV^#96~Dg%1E4|ZJixt^RY!@!{xqKEU~Y$n~iU0 zcvJ>8gztTUKf7kclcX@acedTutyl5WKrRB^v6*R0$7=WXP6FKz8GDEr=?L2|og4O$ zItqL*e;Ii2$~rzk_eoTq?bjI3FLI73j_n9(djl%KiEqGOc1rj!;<$gm@MuOs-2%v* zk#x{hv@^><*(cP@=8#e%$U+}}*IJFAuqFr{z72QT>|G*Kp8`fdokuoYmR~35WdMd2 zTPBh9yi$O`PI%7kcgfTJkvP$qNc^0K`oLuTRt~aFY_9JT(uYx33Eu0 z$E(5nTish8Uwj~94E~+lj}k6gULKbkvv$mhO$Edft5Aj-9H^!eeXjl4TpXii0nDeP z-7enlcn>@c$Cl^rK}*|yL}>id9C#M)IUNA|BTJ8t0J&lftXHQwk_=#BBbsNZj1Yj* zG6K>Esy{m%KOZxjIK2&)xx-PNFb!1MD>~N+@Ki#ihYoE<5vU4qM>Y%hEupQt(xZ28 ze$v$=V+mE*;O-Z(Z_P=`-IwXUg~TN9JFac| zdLkMCmG#0_3}IE z`ChCV+ya1*17>qrd}$FO_e49}_xJt)-*~a$c7ZGd->5)BO@~t~AwXuim9A_~!x-K_ zv==0ErvPM7wK-|L8o`D8c0-hg7T{aabugw1@8_1V?k!Pu1xj5d6F=7U%UDTc*EQ2n znjnqDwvXdQ3)Wp(4W-mL9TB!z0zhYh^8xL666elOb1y6>@)BI7<2+Rq&#bS(j{D&7 z4G??iU9fz>C3S*Wvp8)T?}&r~AE$(4nsVd_m+mhG6W+~O7X|b>m^`P-><938mFLgC zBI7_RJf3ChHkX|CWyGF~`jJ5CH|coAr{cq&2{kQ!yh4DOTMQ=M_TfqnyNwN}8USpX zn6(o}-kYTzzymVcK8#nNAa)^XkF^t5Q#D~lAaIDeZBG=sGcXzE8X+cX8d0GOOu)xZ z`VIbl((MKu4Un0(dZb;tlUh)Aw`3YnSsrH^yBK)yB0`A|7%5>DaCwXP1Jo^2t{xl! zVwAzY@{2Aco&s)2O9b$B^A4p;dK$PLG>|ZH14emNCDMz(+mI{`wcPx$+hD4x|RCRbX(NSujm z(=PObe@fr2pJJeiC5A0=Vniy54;1+m9(xuL0$Fqd5=^h&uX%Tqt!it7M|5Y!A9Hwu z=yCao{Y|n>2$+4*eqyZ$!6KMsp#TE>R@Xb?b_%G7yao(wlTo^{5J2DvX>s z|Iq`B6#z`{{}H||P6_}YKUFocv38Tl+)@Da^k-V54@-%^oH zF>*g}yZ7|qvUl(I)u$yWH*=guosKvp88K&);v8 zty3W-CG}w$0Paur*o-LtXOquNX(MigfXYz?V7_{FiTiPilf40y>Rd$kVKHb!2zH|{ zjA-H(@Nt5EW6z4~MI#ibV)K){3#uNG5CcIJ>VYSKz@zxbFaTDO5C9>QbH~RGRJW9bO457*l_9d!smj3w zs7GjMuALELgwcM`&IY8LXwOVf2fB)yZ&bu{wJcAB5 z0V7qBu!ZI^YJcd`{LD<5HcSmUg$c^t6$ zktTQ_KuC}g;K})Kk~}E|(j+IM5&sA)iO2@A5-zP$z>^M%iHV4oSV)1o}Gr+J%(#{tss*wqye9$0y( zf`J%cKQ}@AkPPUiI*_^!8#ua=-POm(B?JcK#%kOy!(xMRUop9|Ie2;`_a?Xq{#%V` zQSQT5_6I?p5?jtpEny!)eTY0mN)XU#e_2 zUUDHXcZvn{V6{E%HU+@Vh>pTxm!WC7vW)b0T5L^}Ajp_x91AJ^`0Ym0P^LlU@2v-*(X_I`(=4GBQ0V@AwJGRYd`&=!T#(M- z;2<`Konc?u6!H6`Ow=tB0?^Qn93hjR zsnqIE&IW{p9emA)#Gp4ALlAh@{y#i#t3yN{6rl7UQ?;~;Q&0k7%<*MyZFg{A_5XYI zAaXca7D`D;!vOjdr+ILmECc;UIa|7vGt;g%Y+%6>*f7(JR05A5_f=Ig=P8~wG6mUH zOH9Qk_u-8Nu)#r1vNK(#jvZWc76Es6wBLuu+xy;P25xq2j)=W10}QJaKehQd@np=@ zJ?h>e#7ESgc6%&}I7xhG|6Rn(h%N;T5#I;DztB+Y>FLoR2K2z24vd!YH!oj*g{4!^ zQ(c~nz5RVI0l*HtnM%ky*Vqn@7lE&hy5S%Rn!}L(W^4a%ZlIvWZ=a(oYl&A@SEVH+ z)Et4(^^YH)gHMMEC3gZqav68f(WSMu`q6zQAAw_`J~XD~SJvZ60>aSpD}9riKPo;x zqDlV1aWLfP-$I^>wtQJS`i&-8cV%i&wIa+2UY7VWS1C)gx>#KbQq>v1(T{hElx|Y( zH;%A3PhH_7;+d!t{;Wq}WPd0RA|+L!p|dwj+(7ovcV4A|k{?@RPG6-dH8I&1UxI+r z!sNN6MM?W2c5Y7;nC?(S>J9fE$9tp_fN<7hSAtTugcd8u*nqyJL5y&rprF{f`1>0> z7$X$`Q=}#H)lAkt&%4}sf=`@FL)m{rb8vg^34W?P#nt%u%TmC6oC;oV1^w{duN<#m z@}~d#zOy$-_**Jm=OHvOBxH`9X!^JZeRSlF`jEi) zH>qk`TR%siHT~z$`MXW}cU--^oWgVf%1@Y6u)3_dDO8}` zVcX7dhxPN@qV6Q`QP#Y>sb8Q!L#?BtqAWXnIg1P{)jRfTmr!hvtXR77+rAOe+Yq@D?w_k}1MtU=E8vlFByM;x_l30?{SywIanP zAN;nekeKY)Y}w~3u)>$b*;KIl&xscNOdP7h=awZWJHGWk|ao$wrE3LG>fjDw( z&ib9crNAfbzWQ)@_*`_ut5@n}M$dPEsvBiS+H7oW2BJOut8!olnryIYk zD=SBo!lZJ>qB)K(O%NUyb!F==URAq+mN@L8sT3=>8sPpwiuH4E6zqGNeAhl|cfoeAmu*3_xNmAoM}uc1nV+9uh&|8B8x(m_ww?HA-ss^P za?9dzkKKE`TI)_EryF1@LQhuR+Is(`_J?XZ@idYd{JL%O!Z0j(5eVxUyoM6=ly>fP znf5!IpE9uD_Vc?zUU@t13+^6>o}8RevjL`)+)O?8WA;@5D&wD{vm zm&ro=JRRUO{9LJIvQYNBS!As&8U02)Qn1S$Y>;#YY+JmhRk^S6%D6~AWU~6q#%t_; zDR8%N4C&o&>vXi-to1XrP%8s4i?wG?9QnS|?DFLeGCnUugpQl6fyo+qQhm7r;w3#* z!V4-y6M4emN~=fCoNh_JEGfO6;ZFK|`N8nQks0-P8qh=R_J?Qvg|^PX9b z7ZQ*)xWHh9PB#*jz(8S8qNE=PWKQhPRR&=X9^&i=$5lyhYe2AX*0A`8hli{zESwSm zkC&sP2Kc1;gB?smKcoltq0lR~GNH#Dr_UgIIx;sG-ajKQvN^BKi^%;WJ46Vymg&!~ zE#ON!kAvx-;)gmopun^ERz?lBg^c*fJiTo-N4@j2YMzD(sQR(Ij zuPWxJDPLK%uLa+*V#4#q82^n7-!2L%v^fufU#rEslMhn2{>^iQadXGLEin!VXns&@ zS)szAk_jZg)Tw9*!PtPg$Ntx36sOZE*WI1J3rmD_oK>=&beqvQ(hRGSEIf*S0cw)u zI$obK?oKT>&7T#-$+KSscBc$P-&(b&j${CQ^kigkt+sXcTnHzEX?e!)RMf~gMk^uRq&ibhUVgck`j~G}Y<_vU+DyPnv2ctg zEw2;5^@4@=X_wzClwY@$!o~66Nh}1)%E~$mX5B?LUGP~JP`CH~#{OvX_{5c_P;Mvo zkxK`m72XSG7Aw6`-K$plnNf*&(y5#~=Pxr`EU0d{_@H|q&A6H=-MYm)Jx#j04Z=o{ zU~kU&P1S$$kmZS1n`ZwI2;kk?`&=U(bsl(|K&tA=6UgCm^GNR_HxVXluIeN{V}x;7 z>i3B>rE@+-`%*|sa!1;cUkSIOcccyqvjdw^0UC*T z$<-Mz4~rWzi`XWbvQ#d0DohOM>ioCm{&r7_8!R(38OMi7D-2@~S3zj|;J~KBhK)>! zkN@H`WW7CTal41@=-`MkeWcunl}S+CRv+!~soglxwf4qruOw*j z-W-6w)dl*`>R1~59N*a8Gg@tfv_$(n1J#$|6(1*g|2*Bxf2K=@{US(*{;NN@Pd4IO#M}zx9GK*x3^8_n*MshGDi%z9s6(C2;>X|h zOg~XB3Lg{}7Vg@8U2s4S0o$o|VpVgMhBZAsYqg6w403^vAM=&HAw=|D8$40_{PpF~ zLdpr>Dcg~ouk78EgN29@%10qDI&A^BA|Qq2cpIDAqI;!5w-aR z1uy80H0l>Ir~AKtjQ!(&brq|-!oPd#dG5$6IcF*5&gdKY0+{00lh^xo-3E8pLthPi z6{EqohGoEuWCQMPPZkA4jQMaY?)n}*!K2v0ho643_s@nYUY&hMe(169AHYme@$}-3 zx(!6PCo9&FN4%D$z$+u4Pz#g(U48RML0LzA$^}{$!?eXp_Q{@PmmANZ^Jp{%+m?yq z=&>&{2ZwFL6d zS^4^NtMZWNUlJQ&V01SL*c#_FaShE8d1T_@QL{SM8L;UN&w0W4%bs6{{(DoN+0~~* z%G%o6y`!UrA7eSo9?U5@d{Ih|dLtjMt*!k{tRD~fP0bbXXa5T3Ac(yBD+!H|& zelz8oUEfpX9hr$TT8wVNXFO|S&gV+zXI_R}nWdq^G$`nXOfqv12)|6hq;)NM-109e z8!hzI)z$xXJz5uS#_-syb_Z@yB?Rrw^9Kb6?tqD)w@=U81FCx-J0HNPIG+ zi>kYr}&&>uN`dPswg( znN!=QGB+Q9YD9iQb#-^M$qzeQMOn=jj2_u()H8vv7a^LGW|;JB1kLN_--Rv1E9f0E zyN`7QoH;2yyvJJ~A@GvBFf?f4U1@ks5oQ9sxmg!sn3Oy7Tk%s0!U2cVFLhwd8Vg44B8C%xK->f2sYi z78<%(2|(VVRy0CO+f`OjWu{y#Whf z?u<{7K2xooi`4=*T>*75@fI;N* z;$mf>TrC!hb%;I;f{z3`RpsH{fgQX%9d_sbB%vGe5MBa?( zd~oALR8UY5KQqM}&?hr{Dy+EKvQFNr-@xPR?}w57OydsX$0;Vw36m4O=;?dy5rY;=Cc9BeDMbqV27% z{L~-oY9wT2EXFOzgU4VK+4DSZxg^i9j1>ASDvCCzQfS*-aWzNnLRKku^@%S_2U zy)|rZloGllM%SD9;pqC9V)VtC;}ugxR*#SJqvcgXHmVW^us6)Q1kEb?@;kfdnfab< zlj}^mxTYX8#h#$;-_efcg?RhSU!ESCacX6LryclD5McG7;C#=YC&O4vOY2jSV*+!u z)-v3z548&#x(Yb2GXA2Vrx{L8^z3_T#hhEMReRkA*WHY@zn|o2Mh`JK&v3_n`-e+getScenery(); - startWatching(scenery, path_daytime); - startWatching(scenery, path_humidity); + startWatching(scenery, path_sun_phi); + startWatching(scenery, path_sun_theta); startWatching(scenery, path_sun_radius); + startWatching(scenery, path_humidity); } void OpenGLSkybox::update() { @@ -79,14 +81,14 @@ void OpenGLSkybox::nodeChanged(const DefinitionNode *node, const DefinitionDiff OpenGLSharedState *state = renderer->getSharedState(); AtmosphereDefinition *newdef = renderer->getScenery()->getAtmosphere(); - if (node->getPath() == path_daytime) { + if (node->getPath() == path_sun_phi or node->getPath() == path_sun_theta) { Vector3 sun_direction = renderer->getAtmosphereRenderer()->getSunDirection(false); state->set("sunDirection", sun_direction); Color sun_color = newdef->sun_color; state->set("sunColor", sun_color); - state->set("dayTime", newdef->propDayTime()->getValue()); + state->set("dayTime", newdef->getDaytime()); } DefinitionWatcher::nodeChanged(node, diff); diff --git a/src/render/opengl/OpenGLTerrain.cpp b/src/render/opengl/OpenGLTerrain.cpp index 1b994e0..7c2da82 100644 --- a/src/render/opengl/OpenGLTerrain.cpp +++ b/src/render/opengl/OpenGLTerrain.cpp @@ -9,12 +9,7 @@ #include "Thread.h" #include "Mutex.h" #include "OpenGLTerrainChunk.h" -#include "WaterRenderer.h" -#include "CameraDefinition.h" -#include "AtmosphereDefinition.h" #include "Scenery.h" -#include "FloatNode.h" -#include "FloatDiff.h" class ChunkMaintenanceThreads : public ParallelPool { public: @@ -92,8 +87,11 @@ void OpenGLTerrain::initialize() { work->start(); // Watch for definition changes - renderer->getScenery()->getTerrain()->propWaterHeight()->addWatcher(this); - renderer->getScenery()->getAtmosphere()->propDayTime()->addWatcher(this); + startWatching(renderer->getScenery(), "/terrain/water_height"); + startWatching(renderer->getScenery(), "/atmosphere/sun/phi"); + startWatching(renderer->getScenery(), "/atmosphere/sun/theta"); + startWatching(renderer->getScenery(), "/atmosphere/moon/phi"); + startWatching(renderer->getScenery(), "/atmosphere/moon/theta"); } void OpenGLTerrain::update() { @@ -170,7 +168,7 @@ void OpenGLTerrain::performChunksMaintenance() { void OpenGLTerrain::nodeChanged(const DefinitionNode *node, const DefinitionDiff *) { if (node->getPath() == "/terrain/water_height") { resetTextures(); - } else if (node->getPath() == "/atmosphere/daytime") { + } else if (node->getPath().find("/atmosphere") == 0) { resetTextures(); } } diff --git a/src/render/software/AtmosphereModelBruneton.cpp b/src/render/software/AtmosphereModelBruneton.cpp index c2657df..d3a9339 100644 --- a/src/render/software/AtmosphereModelBruneton.cpp +++ b/src/render/software/AtmosphereModelBruneton.cpp @@ -18,6 +18,7 @@ #include "AtmosphereResult.h" #include "SoftwareRenderer.h" #include "WaterRenderer.h" +#include "CelestialBodyDefinition.h" #include "LightComponent.h" #include "LightStatus.h" #include "Texture2D.h" @@ -1079,7 +1080,7 @@ AtmosphereResult AtmosphereModelBruneton::getSkyColor(Vector3 eye, const Vector3 AtmosphereResult result; Vector3 attenuation; Color sunColor = - _sunColor(v, s, r, mu, parent->getScenery()->getAtmosphere()->propSunRadius()->getValue()); /* L0 */ + _sunColor(v, s, r, mu, parent->getScenery()->getAtmosphere()->childSun()->propRadius()->getValue()); /* L0 */ /*result.base.r = base.r + sunColor.r; result.base.g = base.g + sunColor.g; diff --git a/src/render/software/AtmosphereRenderer.cpp b/src/render/software/AtmosphereRenderer.cpp index 8a4dc4c..9bccf03 100644 --- a/src/render/software/AtmosphereRenderer.cpp +++ b/src/render/software/AtmosphereRenderer.cpp @@ -10,6 +10,7 @@ #include "LightStatus.h" #include "Scenery.h" #include "NightSky.h" +#include "CelestialBodyDefinition.h" #include "FloatNode.h" /* Factor to convert software units to kilometers */ @@ -40,7 +41,7 @@ static inline void _applyWeatherEffects(AtmosphereDefinition *definition, Atmosp } distancefactor = (distance > max_distance ? max_distance : distance) / max_distance; /* TODO Get day lighting from model */ - dayfactor = _getDayFactor(definition->propDayTime()->getValue()); + dayfactor = _getDayFactor(definition->getDaytime()); /* Fog masking */ if (humidity > 0.3) { @@ -87,9 +88,7 @@ AtmosphereResult BaseAtmosphereRenderer::getSkyColor(const Vector3 &) { } Vector3 BaseAtmosphereRenderer::getSunDirection(bool) const { - AtmosphereDefinition *atmosphere = getDefinition(); - double sun_angle = (atmosphere->propDayTime()->getValue() + 0.75) * M_PI * 2.0; - return Vector3(cos(sun_angle), sin(sun_angle), 0.0); + return getDefinition()->childSun()->getDirection(); } bool BaseAtmosphereRenderer::getLightsAt(vector &, const Vector3 &) const { diff --git a/src/render/software/NightSky.cpp b/src/render/software/NightSky.cpp index c48316f..0bee210 100644 --- a/src/render/software/NightSky.cpp +++ b/src/render/software/NightSky.cpp @@ -10,6 +10,8 @@ #include "SurfaceMaterial.h" #include "LightComponent.h" #include "LightStatus.h" +#include "CelestialBodyDefinition.h" +#include "FloatNode.h" #define WORLD_SCALING 0.05 #define MOON_DISTANCE 384403.0 @@ -56,11 +58,10 @@ const Color NightSky::getColor(double altitude, const Vector3 &direction) { } // Get moon - VectorSpherical moon_location_s = {MOON_DISTANCE_SCALED, atmosphere->moon_theta, -atmosphere->moon_phi}; - Vector3 moon_position(moon_location_s); - Vector3 moon_direction = moon_position.normalize(); + Vector3 moon_direction = atmosphere->childMoon()->getDirection(); + Vector3 moon_position = moon_direction.scale(MOON_DISTANCE_SCALED); if (moon_direction.dotProduct(direction) >= 0) { - double moon_radius = MOON_RADIUS_SCALED * 5.0 * atmosphere->moon_radius; + double moon_radius = MOON_RADIUS_SCALED * 5.0 * atmosphere->childMoon()->propRadius()->getValue(); Vector3 hit1, hit2; int hits = Geometry::rayIntersectSphere(location, direction, moon_position, moon_radius, &hit1, &hit2); if (hits > 1) { @@ -87,10 +88,9 @@ bool NightSky::getLightsAt(vector &result, const Vector3 &) cons LightComponent moon, sky; AtmosphereDefinition *atmosphere = renderer->getScenery()->getAtmosphere(); - VectorSpherical moon_location_s = {MOON_DISTANCE_SCALED, atmosphere->moon_theta, -atmosphere->moon_phi}; moon.color = Color(0.03, 0.03, 0.03); // TODO take moon phase into account - moon.direction = Vector3(moon_location_s).normalize().scale(-1.0); + moon.direction = atmosphere->childMoon()->getDirection().scale(-1.0); moon.reflection = 0.2; moon.altered = 1; diff --git a/src/tests/Scenery_Test.cpp b/src/tests/Scenery_Test.cpp index e7ad5a8..93ee780 100644 --- a/src/tests/Scenery_Test.cpp +++ b/src/tests/Scenery_Test.cpp @@ -10,15 +10,15 @@ TEST(Scenery, saveGlobal) { Scenery scenery1; scenery1.autoPreset(); scenery1.getTerrain()->propWaterHeight()->setValue(0.2); - scenery1.getAtmosphere()->propDayTime()->setValue(0.53); + scenery1.getAtmosphere()->setDayTime(0.53); Scenery::FileOperationResult result = scenery1.saveGlobal("/tmp/test_paysages_scenery"); - EXPECT_EQ((int)Scenery::FILE_OPERATION_OK, result); + EXPECT_EQ(Scenery::FILE_OPERATION_OK, result); Scenery scenery2; result = scenery2.loadGlobal("/tmp/test_paysages_scenery"); - EXPECT_EQ((int)Scenery::FILE_OPERATION_OK, result); + EXPECT_EQ(Scenery::FILE_OPERATION_OK, result); EXPECT_DOUBLE_EQ(0.2, scenery2.getTerrain()->propWaterHeight()->getValue()); - EXPECT_DOUBLE_EQ(0.53, scenery2.getAtmosphere()->propDayTime()->getValue()); + EXPECT_DOUBLE_EQ(0.53, scenery2.getAtmosphere()->getDaytime()); }