Refactored CelestialBodyDefinition, with new sun/moon widget

This commit is contained in:
Michaël Lemaire 2015-12-30 00:20:20 +01:00
parent 06cd5e31fd
commit 61a43410db
34 changed files with 425 additions and 279 deletions

View file

@ -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<AtmosphereDefinition *>(_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);

View file

@ -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<Star> stars;
private:
GodRaysDefinition *godrays;
CelestialBodyDefinition *sun;
CelestialBodyDefinition *moon;
FloatNode *humidity;
FloatNode *daytime;
FloatNode *sun_radius;
};
}
}

View file

@ -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};

View file

@ -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

View file

@ -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();

View file

@ -32,6 +32,7 @@ class LayersDiff;
class CloudsDefinition;
class CloudLayerDefinition;
class AtmosphereDefinition;
class CelestialBodyDefinition;
class GodRaysDefinition;
class TexturesDefinition;
class TextureLayerDefinition;

View file

@ -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);
}
}

View file

@ -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());
}

View file

@ -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;
};
}
}

View file

@ -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<unique_ptr<IntPropertyBind>> int_bindings;
vector<unique_ptr<FloatPropertyBind>> 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<IntNode *>(main->getScenery()->findByPath(path));
if (node) {
impl->int_bindings.push_back(make_unique<IntPropertyBind>(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<FloatNode *>(main->getScenery()->findByPath(path));
if (node) {
impl->float_bindings.push_back(make_unique<FloatPropertyBind>(main, object, property, node));
} else {
Logs::error("UI") << "Can't find float node for binding : " << path << endl;
}
}

View file

@ -0,0 +1,35 @@
#ifndef BASEMODELERTOOL_H
#define BASEMODELERTOOL_H
#include "modeler_global.h"
#include <memory>
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<pimpl> impl;
MainModelerWindow *main;
};
}
}
#endif // BASEMODELERTOOL_H

View file

@ -6,27 +6,30 @@
#include <cmath>
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);
}
}

View file

@ -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;
};
}

View file

@ -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);
}
}

View file

@ -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;
};
}

View file

@ -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<QObject *>(objectName);
return rootObject()->findChild<QObject *>(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() {

View file

@ -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;

View file

@ -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() {

View file

@ -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());
}
}

View file

@ -10,6 +10,8 @@ namespace modeler {
class MainModelerWindow;
class OpenGLView;
class BaseModelerTool;
class AtmosphereModeler;
class WaterModeler;

View file

@ -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
}

View file

@ -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
}
}
]
}

View file

@ -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: {

View file

@ -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
}
}

View file

@ -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)
}
}
}

View file

@ -53,5 +53,9 @@
<file>images/icon_render_final.png</file>
<file>images/icon_cancel.png</file>
<file>images/icon_sun_radius.png</file>
<file>images/bg_phi_coord.png</file>
<file>WidgetSphericalCoords.qml</file>
<file>images/bg_theta_coord.png</file>
<file>WidgetDayTime.qml</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

View file

@ -12,9 +12,10 @@
#include "FloatNode.h"
#include "Logs.h"
static const string path_daytime = "/atmosphere/daytime";
static const string path_humidity = "/atmosphere/humidity";
static const string path_sun_radius = "/atmosphere/sun_radius";
static const string path_sun_phi = "/atmosphere/sun/phi";
static const string path_sun_theta = "/atmosphere/sun/theta";
static const string path_sun_radius = "/atmosphere/sun/radius";
OpenGLSkybox::OpenGLSkybox(OpenGLRenderer *renderer) : OpenGLPart(renderer, "skybox") {
program = createShader("skybox");
@ -56,9 +57,10 @@ OpenGLSkybox::~OpenGLSkybox() {
void OpenGLSkybox::initialize() {
// Watch for definition changes
Scenery *scenery = renderer->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);

View file

@ -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();
}
}

View file

@ -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;

View file

@ -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<LightComponent> &, const Vector3 &) const {

View file

@ -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<LightComponent> &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;

View file

@ -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());
}