Refactored CelestialBodyDefinition, with new sun/moon widget
This commit is contained in:
parent
06cd5e31fd
commit
61a43410db
34 changed files with 425 additions and 279 deletions
|
@ -5,29 +5,24 @@
|
||||||
#include "RandomGenerator.h"
|
#include "RandomGenerator.h"
|
||||||
#include "FloatNode.h"
|
#include "FloatNode.h"
|
||||||
#include "GodRaysDefinition.h"
|
#include "GodRaysDefinition.h"
|
||||||
|
#include "CelestialBodyDefinition.h"
|
||||||
|
|
||||||
AtmosphereDefinition::AtmosphereDefinition(DefinitionNode *parent)
|
AtmosphereDefinition::AtmosphereDefinition(DefinitionNode *parent)
|
||||||
: DefinitionNode(parent, "atmosphere", "atmosphere") {
|
: DefinitionNode(parent, "atmosphere", "atmosphere") {
|
||||||
model = ATMOSPHERE_MODEL_DISABLED;
|
model = ATMOSPHERE_MODEL_DISABLED;
|
||||||
godrays = new GodRaysDefinition(this);
|
godrays = new GodRaysDefinition(this);
|
||||||
daytime = new FloatNode(this, "daytime");
|
sun = new CelestialBodyDefinition(this, "sun");
|
||||||
|
moon = new CelestialBodyDefinition(this, "moon");
|
||||||
humidity = new FloatNode(this, "humidity");
|
humidity = new FloatNode(this, "humidity");
|
||||||
sun_radius = new FloatNode(this, "sun_radius");
|
|
||||||
sun_color = COLOR_RED;
|
sun_color = COLOR_RED;
|
||||||
}
|
}
|
||||||
|
|
||||||
AtmosphereDefinition::~AtmosphereDefinition() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void AtmosphereDefinition::save(PackStream *stream) const {
|
void AtmosphereDefinition::save(PackStream *stream) const {
|
||||||
DefinitionNode::save(stream);
|
DefinitionNode::save(stream);
|
||||||
|
|
||||||
stream->write((int *)&model);
|
stream->write((int *)&model);
|
||||||
sun_color.save(stream);
|
sun_color.save(stream);
|
||||||
stream->write(&dome_lighting);
|
stream->write(&dome_lighting);
|
||||||
stream->write(&moon_radius);
|
|
||||||
stream->write(&moon_theta);
|
|
||||||
stream->write(&moon_phi);
|
|
||||||
|
|
||||||
int star_count = stars.size();
|
int star_count = stars.size();
|
||||||
stream->write(&star_count);
|
stream->write(&star_count);
|
||||||
|
@ -44,9 +39,6 @@ void AtmosphereDefinition::load(PackStream *stream) {
|
||||||
stream->read((int *)&model);
|
stream->read((int *)&model);
|
||||||
sun_color.load(stream);
|
sun_color.load(stream);
|
||||||
stream->read(&dome_lighting);
|
stream->read(&dome_lighting);
|
||||||
stream->read(&moon_radius);
|
|
||||||
stream->read(&moon_theta);
|
|
||||||
stream->read(&moon_phi);
|
|
||||||
|
|
||||||
int star_count;
|
int star_count;
|
||||||
stream->read(&star_count);
|
stream->read(&star_count);
|
||||||
|
@ -66,39 +58,41 @@ void AtmosphereDefinition::load(PackStream *stream) {
|
||||||
void AtmosphereDefinition::copy(DefinitionNode *_destination) const {
|
void AtmosphereDefinition::copy(DefinitionNode *_destination) const {
|
||||||
DefinitionNode::copy(_destination);
|
DefinitionNode::copy(_destination);
|
||||||
|
|
||||||
AtmosphereDefinition *destination = (AtmosphereDefinition *)_destination;
|
AtmosphereDefinition *destination = static_cast<AtmosphereDefinition *>(_destination);
|
||||||
|
if (destination) {
|
||||||
destination->model = model;
|
destination->model = model;
|
||||||
destination->sun_color = sun_color;
|
destination->sun_color = sun_color;
|
||||||
destination->dome_lighting = dome_lighting;
|
destination->dome_lighting = dome_lighting;
|
||||||
destination->moon_radius = moon_radius;
|
|
||||||
destination->moon_theta = moon_theta;
|
|
||||||
destination->moon_phi = moon_phi;
|
|
||||||
destination->stars = stars;
|
destination->stars = stars;
|
||||||
|
|
||||||
destination->validate();
|
destination->validate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AtmosphereDefinition::setDayTime(double value) {
|
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) {
|
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);
|
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 AtmosphereDefinition::getDaytime() const {
|
||||||
double value = daytime->getValue();
|
double value = (sun->propTheta()->getValue() / M_2PI) - 0.75;
|
||||||
if (value >= 0.0) {
|
if (value >= 0.0) {
|
||||||
value = fmod(value, 1.0);
|
value = fmod(value, 1.0);
|
||||||
} else {
|
} else {
|
||||||
value = 1.0 - fmod(-value, 1.0);
|
value = 1.0 - fmod(-value, 1.0);
|
||||||
}
|
}
|
||||||
value *= 86400.0;
|
return value;
|
||||||
*hour = value / 3600.0;
|
}
|
||||||
value -= 3600.0 * *hour;
|
|
||||||
*minute = value / 60.0;
|
void AtmosphereDefinition::getHMS(int *hour, int *minute, int *second) const {
|
||||||
*second = value - *minute * 60.0;
|
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) {
|
void AtmosphereDefinition::applyPreset(AtmospherePreset preset, RandomGenerator &random) {
|
||||||
|
@ -106,10 +100,10 @@ void AtmosphereDefinition::applyPreset(AtmospherePreset preset, RandomGenerator
|
||||||
sun_color.g = 0.95;
|
sun_color.g = 0.95;
|
||||||
sun_color.b = 0.9;
|
sun_color.b = 0.9;
|
||||||
sun_color.a = 1.0;
|
sun_color.a = 1.0;
|
||||||
sun_radius->setValue(0.8);
|
sun->propRadius()->setValue(1.0);
|
||||||
moon_radius = 1.0;
|
moon->propRadius()->setValue(1.0);
|
||||||
moon_theta = 0.3;
|
moon->propPhi()->setValue(0.5);
|
||||||
moon_phi = 0.5;
|
moon->propTheta()->setValue(0.3);
|
||||||
|
|
||||||
model = ATMOSPHERE_MODEL_BRUNETON;
|
model = ATMOSPHERE_MODEL_BRUNETON;
|
||||||
|
|
||||||
|
@ -139,8 +133,6 @@ void AtmosphereDefinition::applyPreset(AtmospherePreset preset, RandomGenerator
|
||||||
humidity->setValue(0.9);
|
humidity->setValue(0.9);
|
||||||
dome_lighting = 0.05;
|
dome_lighting = 0.05;
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
generateStars(2000, random);
|
generateStars(2000, random);
|
||||||
|
|
|
@ -31,7 +31,6 @@ class DEFINITIONSHARED_EXPORT AtmosphereDefinition : public DefinitionNode {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AtmosphereDefinition(DefinitionNode *parent);
|
AtmosphereDefinition(DefinitionNode *parent);
|
||||||
virtual ~AtmosphereDefinition();
|
|
||||||
|
|
||||||
virtual void save(PackStream *stream) const override;
|
virtual void save(PackStream *stream) const override;
|
||||||
virtual void load(PackStream *stream) override;
|
virtual void load(PackStream *stream) override;
|
||||||
|
@ -41,15 +40,15 @@ class DEFINITIONSHARED_EXPORT AtmosphereDefinition : public DefinitionNode {
|
||||||
inline GodRaysDefinition *childGodRays() const {
|
inline GodRaysDefinition *childGodRays() const {
|
||||||
return godrays;
|
return godrays;
|
||||||
}
|
}
|
||||||
inline FloatNode *propDayTime() const {
|
inline CelestialBodyDefinition *childSun() const {
|
||||||
return daytime;
|
return sun;
|
||||||
|
}
|
||||||
|
inline CelestialBodyDefinition *childMoon() const {
|
||||||
|
return moon;
|
||||||
}
|
}
|
||||||
inline FloatNode *propHumidity() const {
|
inline FloatNode *propHumidity() const {
|
||||||
return humidity;
|
return humidity;
|
||||||
}
|
}
|
||||||
inline FloatNode *propSunRadius() const {
|
|
||||||
return sun_radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the daytime from a 0.0-1.0 value.
|
* 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.
|
* Set the daytime from hour/minute/second info.
|
||||||
*/
|
*/
|
||||||
void setDayTime(int hour, int minute = 0, int second = 0);
|
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.
|
* Get the daytime info, in hour/minute/second.
|
||||||
*/
|
*/
|
||||||
|
@ -73,17 +76,13 @@ class DEFINITIONSHARED_EXPORT AtmosphereDefinition : public DefinitionNode {
|
||||||
Color sun_color;
|
Color sun_color;
|
||||||
double dome_lighting;
|
double dome_lighting;
|
||||||
|
|
||||||
double moon_radius;
|
|
||||||
double moon_theta;
|
|
||||||
double moon_phi;
|
|
||||||
|
|
||||||
vector<Star> stars;
|
vector<Star> stars;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GodRaysDefinition *godrays;
|
GodRaysDefinition *godrays;
|
||||||
|
CelestialBodyDefinition *sun;
|
||||||
|
CelestialBodyDefinition *moon;
|
||||||
FloatNode *humidity;
|
FloatNode *humidity;
|
||||||
FloatNode *daytime;
|
|
||||||
FloatNode *sun_radius;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
18
src/definition/CelestialBodyDefinition.cpp
Normal file
18
src/definition/CelestialBodyDefinition.cpp
Normal 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};
|
38
src/definition/CelestialBodyDefinition.h
Normal file
38
src/definition/CelestialBodyDefinition.h
Normal 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
|
|
@ -14,7 +14,7 @@ TimeManager::TimeManager() {
|
||||||
|
|
||||||
void TimeManager::moveForward(Scenery *scenery, double amount) {
|
void TimeManager::moveForward(Scenery *scenery, double amount) {
|
||||||
// Move the sun
|
// Move the sun
|
||||||
scenery->getAtmosphere()->setDayTime(scenery->getAtmosphere()->propDayTime()->getValue() + amount);
|
scenery->getAtmosphere()->setDayTime(scenery->getAtmosphere()->getDaytime() + amount);
|
||||||
|
|
||||||
// Move the clouds
|
// Move the clouds
|
||||||
int n = scenery->getClouds()->getLayerCount();
|
int n = scenery->getClouds()->getLayerCount();
|
||||||
|
|
|
@ -32,6 +32,7 @@ class LayersDiff;
|
||||||
class CloudsDefinition;
|
class CloudsDefinition;
|
||||||
class CloudLayerDefinition;
|
class CloudLayerDefinition;
|
||||||
class AtmosphereDefinition;
|
class AtmosphereDefinition;
|
||||||
|
class CelestialBodyDefinition;
|
||||||
class GodRaysDefinition;
|
class GodRaysDefinition;
|
||||||
class TexturesDefinition;
|
class TexturesDefinition;
|
||||||
class TextureLayerDefinition;
|
class TextureLayerDefinition;
|
||||||
|
|
|
@ -270,7 +270,7 @@ static void testAtmosphereBruneton() {
|
||||||
|
|
||||||
for (int i = 0; i <= 60; i++) {
|
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));
|
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);
|
startTestRender(&renderer, "atmosphere_bruneton", i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,19 +3,15 @@
|
||||||
#include "MainModelerWindow.h"
|
#include "MainModelerWindow.h"
|
||||||
#include "Scenery.h"
|
#include "Scenery.h"
|
||||||
#include "AtmosphereDefinition.h"
|
#include "AtmosphereDefinition.h"
|
||||||
#include "FloatPropertyBind.h"
|
|
||||||
|
|
||||||
AtmosphereModeler::AtmosphereModeler(MainModelerWindow *main) {
|
AtmosphereModeler::AtmosphereModeler(MainModelerWindow *main) : BaseModelerTool(main) {
|
||||||
prop_daytime =
|
addFloatBinding("atmosphere_humidity", "value", "/atmosphere/humidity");
|
||||||
new FloatPropertyBind(main, "atmosphere_daytime", "value", main->getScenery()->getAtmosphere()->propDayTime());
|
addFloatBinding("atmosphere_sun_direction", "phi", "/atmosphere/sun/phi");
|
||||||
prop_humidity = new FloatPropertyBind(main, "atmosphere_humidity", "value",
|
addFloatBinding("atmosphere_sun_direction", "theta", "/atmosphere/sun/theta");
|
||||||
main->getScenery()->getAtmosphere()->propHumidity());
|
addFloatBinding("atmosphere_sun_radius", "value", "/atmosphere/sun/radius");
|
||||||
prop_sun_radius = new FloatPropertyBind(main, "atmosphere_sun_radius", "value",
|
addFloatBinding("atmosphere_moon_direction", "phi", "/atmosphere/moon/phi");
|
||||||
main->getScenery()->getAtmosphere()->propSunRadius());
|
addFloatBinding("atmosphere_moon_direction", "theta", "/atmosphere/moon/theta");
|
||||||
}
|
// addFloatBinding("atmosphere_moon_radius", "value", "/atmosphere/moon/radius");
|
||||||
|
|
||||||
AtmosphereModeler::~AtmosphereModeler() {
|
main->setQmlProperty("atmosphere_daytime", "value", main->getScenery()->getAtmosphere()->getDaytime());
|
||||||
delete prop_daytime;
|
|
||||||
delete prop_humidity;
|
|
||||||
delete prop_sun_radius;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,18 +3,14 @@
|
||||||
|
|
||||||
#include "modeler_global.h"
|
#include "modeler_global.h"
|
||||||
|
|
||||||
|
#include "BaseModelerTool.h"
|
||||||
|
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace modeler {
|
namespace modeler {
|
||||||
|
|
||||||
class AtmosphereModeler {
|
class AtmosphereModeler : protected BaseModelerTool {
|
||||||
public:
|
public:
|
||||||
AtmosphereModeler(MainModelerWindow *main);
|
AtmosphereModeler(MainModelerWindow *main);
|
||||||
~AtmosphereModeler();
|
|
||||||
|
|
||||||
private:
|
|
||||||
FloatPropertyBind *prop_daytime;
|
|
||||||
FloatPropertyBind *prop_humidity;
|
|
||||||
FloatPropertyBind *prop_sun_radius;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
39
src/interface/modeler/BaseModelerTool.cpp
Normal file
39
src/interface/modeler/BaseModelerTool.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
35
src/interface/modeler/BaseModelerTool.h
Normal file
35
src/interface/modeler/BaseModelerTool.h
Normal 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
|
|
@ -6,27 +6,30 @@
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
FloatPropertyBind::FloatPropertyBind(MainModelerWindow *window, const QString &object_name,
|
FloatPropertyBind::FloatPropertyBind(MainModelerWindow *window, const string &object_name, const string &property_name,
|
||||||
const QString &property_name, FloatNode *node)
|
FloatNode *node)
|
||||||
: QObject(window), node(node), property(property_name) {
|
: QObject(window), node(node), property(property_name) {
|
||||||
item = window->findQmlObject(object_name);
|
item = window->findQmlObject(object_name);
|
||||||
if (item) {
|
if (item) {
|
||||||
node->addWatcher(this, true);
|
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 {
|
} else {
|
||||||
item = NULL;
|
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 *) {
|
void FloatPropertyBind::nodeChanged(const DefinitionNode *, const DefinitionDiff *) {
|
||||||
if (item) {
|
if (item) {
|
||||||
item->setProperty(property.toLocal8Bit(), node->getValue());
|
item->setProperty(property.c_str(), node->getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FloatPropertyBind::propertyChanged(double value) {
|
void FloatPropertyBind::propertyChanged() {
|
||||||
if (fabs(value - node->getValue()) > 0.00000001) {
|
bool ok;
|
||||||
|
double value = item->property(property.c_str()).toDouble(&ok);
|
||||||
|
if (ok and fabs(value - node->getValue()) > 0.00000001) {
|
||||||
node->setValue(value);
|
node->setValue(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,17 +17,17 @@ namespace modeler {
|
||||||
class FloatPropertyBind : public QObject, public DefinitionWatcher {
|
class FloatPropertyBind : public QObject, public DefinitionWatcher {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
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);
|
FloatNode *node);
|
||||||
|
|
||||||
virtual void nodeChanged(const DefinitionNode *node, const DefinitionDiff *diff) override;
|
virtual void nodeChanged(const DefinitionNode *node, const DefinitionDiff *diff) override;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void propertyChanged(double value);
|
void propertyChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FloatNode *node;
|
FloatNode *node;
|
||||||
QString property;
|
string property;
|
||||||
QObject *item;
|
QObject *item;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,27 +4,30 @@
|
||||||
#include "IntNode.h"
|
#include "IntNode.h"
|
||||||
#include "Logs.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)
|
IntNode *node)
|
||||||
: QObject(window), node(node), property(property_name) {
|
: QObject(window), node(node), property(property_name) {
|
||||||
item = window->findQmlObject(object_name);
|
item = window->findQmlObject(object_name);
|
||||||
if (item) {
|
if (item) {
|
||||||
node->addWatcher(this, true);
|
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 {
|
} else {
|
||||||
item = NULL;
|
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 *) {
|
void IntPropertyBind::nodeChanged(const DefinitionNode *, const DefinitionDiff *) {
|
||||||
if (item) {
|
if (item) {
|
||||||
item->setProperty(property.toLocal8Bit(), node->getValue());
|
item->setProperty(property.c_str(), node->getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntPropertyBind::propertyChanged(int value) {
|
void IntPropertyBind::propertyChanged() {
|
||||||
if (value != node->getValue()) {
|
bool ok;
|
||||||
|
int value = item->property(property.c_str()).toInt(&ok);
|
||||||
|
if (ok and value != node->getValue()) {
|
||||||
node->setValue(value);
|
node->setValue(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,16 +17,16 @@ namespace modeler {
|
||||||
class IntPropertyBind : public QObject, public DefinitionWatcher {
|
class IntPropertyBind : public QObject, public DefinitionWatcher {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
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;
|
virtual void nodeChanged(const DefinitionNode *node, const DefinitionDiff *diff) override;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void propertyChanged(int value);
|
void propertyChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IntNode *node;
|
IntNode *node;
|
||||||
QString property;
|
string property;
|
||||||
QObject *item;
|
QObject *item;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,39 +60,39 @@ MainModelerWindow::~MainModelerWindow() {
|
||||||
delete scenery;
|
delete scenery;
|
||||||
}
|
}
|
||||||
|
|
||||||
QObject *MainModelerWindow::findQmlObject(const QString &objectName) {
|
QObject *MainModelerWindow::findQmlObject(const string &objectName) {
|
||||||
if (objectName == "ui" || objectName == "root") {
|
if (objectName == "ui" || objectName == "root") {
|
||||||
return rootObject();
|
return rootObject();
|
||||||
} else {
|
} 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);
|
QObject *item = findQmlObject(objectName);
|
||||||
if (item) {
|
if (item) {
|
||||||
item->setProperty(propertyName.toLocal8Bit(), value);
|
item->setProperty(propertyName.c_str(), value);
|
||||||
} else {
|
} 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) {
|
const char *method) {
|
||||||
QObject *item = findQmlObject(objectName);
|
QObject *item = findQmlObject(objectName);
|
||||||
if (item) {
|
if (item) {
|
||||||
connect(item, signal, receiver, method);
|
connect(item, signal, receiver, method);
|
||||||
} else {
|
} else {
|
||||||
Logs::error("UI") << "QML object not found :" << objectName.toStdString() << endl;
|
Logs::error("UI") << "QML object not found :" << objectName << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString MainModelerWindow::getState() const {
|
string MainModelerWindow::getState() const {
|
||||||
return rootObject()->property("state").toString();
|
return rootObject()->property("state").toString().toStdString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainModelerWindow::setState(const QString &stateName) {
|
void MainModelerWindow::setState(const string &stateName) {
|
||||||
rootObject()->setProperty("state", stateName);
|
rootObject()->setProperty("state", QString::fromStdString(stateName));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainModelerWindow::newFile() {
|
void MainModelerWindow::newFile() {
|
||||||
|
|
|
@ -14,12 +14,12 @@ class MainModelerWindow : public QQuickView {
|
||||||
MainModelerWindow();
|
MainModelerWindow();
|
||||||
virtual ~MainModelerWindow();
|
virtual ~MainModelerWindow();
|
||||||
|
|
||||||
QObject *findQmlObject(const QString &objectName);
|
QObject *findQmlObject(const string &objectName);
|
||||||
void setQmlProperty(const QString &objectName, const QString &propertyName, const QVariant &value);
|
void setQmlProperty(const string &objectName, const string &propertyName, const QVariant &value);
|
||||||
void connectQmlSignal(const QString &objectName, const char *signal, const QObject *receiver, const char *method);
|
void connectQmlSignal(const string &objectName, const char *signal, const QObject *receiver, const char *method);
|
||||||
|
|
||||||
QString getState() const;
|
string getState() const;
|
||||||
void setState(const QString &stateName);
|
void setState(const string &stateName);
|
||||||
|
|
||||||
inline Scenery *getScenery() const {
|
inline Scenery *getScenery() const {
|
||||||
return scenery;
|
return scenery;
|
||||||
|
|
|
@ -62,7 +62,8 @@ void ModelerCameras::startSunTool() {
|
||||||
current->copy(tool);
|
current->copy(tool);
|
||||||
active = tool;
|
active = tool;
|
||||||
|
|
||||||
parent->getScenery()->getAtmosphere()->propDayTime()->addWatcher(this, true);
|
// FIXME
|
||||||
|
// parent->getScenery()->getAtmosphere()->propDayTime()->addWatcher(this, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelerCameras::endTool() {
|
void ModelerCameras::endTool() {
|
||||||
|
|
|
@ -149,7 +149,7 @@ void RenderProcess::stopRender() {
|
||||||
renderer->interrupt();
|
renderer->interrupt();
|
||||||
} else {
|
} else {
|
||||||
destination->hide();
|
destination->hide();
|
||||||
window->setState(window->rootObject()->property("previous_state").toString());
|
window->setState(window->rootObject()->property("previous_state").toString().toStdString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@ namespace modeler {
|
||||||
class MainModelerWindow;
|
class MainModelerWindow;
|
||||||
class OpenGLView;
|
class OpenGLView;
|
||||||
|
|
||||||
|
class BaseModelerTool;
|
||||||
|
|
||||||
class AtmosphereModeler;
|
class AtmosphereModeler;
|
||||||
class WaterModeler;
|
class WaterModeler;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,5 @@ import QtQuick 2.2
|
||||||
import QtQuick.Controls 1.2
|
import QtQuick.Controls 1.2
|
||||||
|
|
||||||
Slider {
|
Slider {
|
||||||
signal changed(real value)
|
|
||||||
onValueChanged: changed(value)
|
|
||||||
opacity: enabled ? 1.0 : 0.1
|
opacity: enabled ? 1.0 : 0.1
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,148 +1,49 @@
|
||||||
import QtQuick 2.0
|
import QtQuick 2.0
|
||||||
import QtQuick.Controls 1.1
|
|
||||||
import QtQuick.Layouts 1.1
|
|
||||||
|
|
||||||
BasePanel {
|
BasePanel {
|
||||||
id: daytime
|
width: 200
|
||||||
width: 100
|
|
||||||
|
|
||||||
objectName: "atmosphere_daytime"
|
Column {
|
||||||
default property real value: day_night.value == 2 ? 0.0 : slider.value * 0.54 + 0.23;
|
anchors.centerIn: parent
|
||||||
signal changed(real value)
|
width: parent.width - 10
|
||||||
|
spacing: 30
|
||||||
|
|
||||||
onValueChanged: {
|
Text {
|
||||||
changed(value);
|
text: "Sun location in the sky"
|
||||||
day_night.value = (value >= 0.23 && value <= 0.77) ? 1 : 2;
|
|
||||||
if (day_night.value == 1)
|
|
||||||
{
|
|
||||||
slider.value = (value - 0.23) / 0.54;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout
|
|
||||||
{
|
|
||||||
height: parent.height
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
spacing: 20
|
}
|
||||||
|
|
||||||
Item {height: 1}
|
WidgetSphericalCoords {
|
||||||
|
id: atmosphere_sun_direction
|
||||||
BaseChoice {
|
objectName: "atmosphere_sun_direction"
|
||||||
id: day_night
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
spacing: 10
|
|
||||||
width: 90
|
|
||||||
height: 40
|
|
||||||
|
|
||||||
BaseChoiceItem {
|
|
||||||
icon: "images/icon_atmosphere_day.png"
|
icon: "images/icon_atmosphere_day.png"
|
||||||
value: 1
|
width: parent.width
|
||||||
checked: true
|
|
||||||
}
|
}
|
||||||
BaseChoiceItem {
|
|
||||||
|
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"
|
icon: "images/icon_atmosphere_night.png"
|
||||||
value: 2
|
width: parent.width
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ BasePanel {
|
||||||
property alias items: container.children
|
property alias items: container.children
|
||||||
property int value: -1
|
property int value: -1
|
||||||
width: items[0].width + 10
|
width: items[0].width + 10
|
||||||
signal changed(int value)
|
|
||||||
|
|
||||||
ExclusiveGroup {
|
ExclusiveGroup {
|
||||||
id: exclusive_item
|
id: exclusive_item
|
||||||
|
@ -30,7 +29,6 @@ BasePanel {
|
||||||
exclusive_item.current = null;
|
exclusive_item.current = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
changed(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onItemsChanged: {
|
onItemsChanged: {
|
||||||
|
|
77
src/interface/modeler/qml/WidgetDayTime.qml
Normal file
77
src/interface/modeler/qml/WidgetDayTime.qml
Normal 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
|
||||||
|
}
|
||||||
|
}
|
45
src/interface/modeler/qml/WidgetSphericalCoords.qml
Normal file
45
src/interface/modeler/qml/WidgetSphericalCoords.qml
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -53,5 +53,9 @@
|
||||||
<file>images/icon_render_final.png</file>
|
<file>images/icon_render_final.png</file>
|
||||||
<file>images/icon_cancel.png</file>
|
<file>images/icon_cancel.png</file>
|
||||||
<file>images/icon_sun_radius.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>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
BIN
src/interface/modeler/qml/images/bg_phi_coord.png
Normal file
BIN
src/interface/modeler/qml/images/bg_phi_coord.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.2 KiB |
BIN
src/interface/modeler/qml/images/bg_theta_coord.png
Normal file
BIN
src/interface/modeler/qml/images/bg_theta_coord.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.8 KiB |
|
@ -12,9 +12,10 @@
|
||||||
#include "FloatNode.h"
|
#include "FloatNode.h"
|
||||||
#include "Logs.h"
|
#include "Logs.h"
|
||||||
|
|
||||||
static const string path_daytime = "/atmosphere/daytime";
|
|
||||||
static const string path_humidity = "/atmosphere/humidity";
|
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") {
|
OpenGLSkybox::OpenGLSkybox(OpenGLRenderer *renderer) : OpenGLPart(renderer, "skybox") {
|
||||||
program = createShader("skybox");
|
program = createShader("skybox");
|
||||||
|
@ -56,9 +57,10 @@ OpenGLSkybox::~OpenGLSkybox() {
|
||||||
void OpenGLSkybox::initialize() {
|
void OpenGLSkybox::initialize() {
|
||||||
// Watch for definition changes
|
// Watch for definition changes
|
||||||
Scenery *scenery = renderer->getScenery();
|
Scenery *scenery = renderer->getScenery();
|
||||||
startWatching(scenery, path_daytime);
|
startWatching(scenery, path_sun_phi);
|
||||||
startWatching(scenery, path_humidity);
|
startWatching(scenery, path_sun_theta);
|
||||||
startWatching(scenery, path_sun_radius);
|
startWatching(scenery, path_sun_radius);
|
||||||
|
startWatching(scenery, path_humidity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLSkybox::update() {
|
void OpenGLSkybox::update() {
|
||||||
|
@ -79,14 +81,14 @@ void OpenGLSkybox::nodeChanged(const DefinitionNode *node, const DefinitionDiff
|
||||||
OpenGLSharedState *state = renderer->getSharedState();
|
OpenGLSharedState *state = renderer->getSharedState();
|
||||||
AtmosphereDefinition *newdef = renderer->getScenery()->getAtmosphere();
|
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);
|
Vector3 sun_direction = renderer->getAtmosphereRenderer()->getSunDirection(false);
|
||||||
state->set("sunDirection", sun_direction);
|
state->set("sunDirection", sun_direction);
|
||||||
|
|
||||||
Color sun_color = newdef->sun_color;
|
Color sun_color = newdef->sun_color;
|
||||||
state->set("sunColor", sun_color);
|
state->set("sunColor", sun_color);
|
||||||
|
|
||||||
state->set("dayTime", newdef->propDayTime()->getValue());
|
state->set("dayTime", newdef->getDaytime());
|
||||||
}
|
}
|
||||||
|
|
||||||
DefinitionWatcher::nodeChanged(node, diff);
|
DefinitionWatcher::nodeChanged(node, diff);
|
||||||
|
|
|
@ -9,12 +9,7 @@
|
||||||
#include "Thread.h"
|
#include "Thread.h"
|
||||||
#include "Mutex.h"
|
#include "Mutex.h"
|
||||||
#include "OpenGLTerrainChunk.h"
|
#include "OpenGLTerrainChunk.h"
|
||||||
#include "WaterRenderer.h"
|
|
||||||
#include "CameraDefinition.h"
|
|
||||||
#include "AtmosphereDefinition.h"
|
|
||||||
#include "Scenery.h"
|
#include "Scenery.h"
|
||||||
#include "FloatNode.h"
|
|
||||||
#include "FloatDiff.h"
|
|
||||||
|
|
||||||
class ChunkMaintenanceThreads : public ParallelPool {
|
class ChunkMaintenanceThreads : public ParallelPool {
|
||||||
public:
|
public:
|
||||||
|
@ -92,8 +87,11 @@ void OpenGLTerrain::initialize() {
|
||||||
work->start();
|
work->start();
|
||||||
|
|
||||||
// Watch for definition changes
|
// Watch for definition changes
|
||||||
renderer->getScenery()->getTerrain()->propWaterHeight()->addWatcher(this);
|
startWatching(renderer->getScenery(), "/terrain/water_height");
|
||||||
renderer->getScenery()->getAtmosphere()->propDayTime()->addWatcher(this);
|
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() {
|
void OpenGLTerrain::update() {
|
||||||
|
@ -170,7 +168,7 @@ void OpenGLTerrain::performChunksMaintenance() {
|
||||||
void OpenGLTerrain::nodeChanged(const DefinitionNode *node, const DefinitionDiff *) {
|
void OpenGLTerrain::nodeChanged(const DefinitionNode *node, const DefinitionDiff *) {
|
||||||
if (node->getPath() == "/terrain/water_height") {
|
if (node->getPath() == "/terrain/water_height") {
|
||||||
resetTextures();
|
resetTextures();
|
||||||
} else if (node->getPath() == "/atmosphere/daytime") {
|
} else if (node->getPath().find("/atmosphere") == 0) {
|
||||||
resetTextures();
|
resetTextures();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "AtmosphereResult.h"
|
#include "AtmosphereResult.h"
|
||||||
#include "SoftwareRenderer.h"
|
#include "SoftwareRenderer.h"
|
||||||
#include "WaterRenderer.h"
|
#include "WaterRenderer.h"
|
||||||
|
#include "CelestialBodyDefinition.h"
|
||||||
#include "LightComponent.h"
|
#include "LightComponent.h"
|
||||||
#include "LightStatus.h"
|
#include "LightStatus.h"
|
||||||
#include "Texture2D.h"
|
#include "Texture2D.h"
|
||||||
|
@ -1079,7 +1080,7 @@ AtmosphereResult AtmosphereModelBruneton::getSkyColor(Vector3 eye, const Vector3
|
||||||
AtmosphereResult result;
|
AtmosphereResult result;
|
||||||
Vector3 attenuation;
|
Vector3 attenuation;
|
||||||
Color sunColor =
|
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.r = base.r + sunColor.r;
|
||||||
result.base.g = base.g + sunColor.g;
|
result.base.g = base.g + sunColor.g;
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "LightStatus.h"
|
#include "LightStatus.h"
|
||||||
#include "Scenery.h"
|
#include "Scenery.h"
|
||||||
#include "NightSky.h"
|
#include "NightSky.h"
|
||||||
|
#include "CelestialBodyDefinition.h"
|
||||||
#include "FloatNode.h"
|
#include "FloatNode.h"
|
||||||
|
|
||||||
/* Factor to convert software units to kilometers */
|
/* 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;
|
distancefactor = (distance > max_distance ? max_distance : distance) / max_distance;
|
||||||
/* TODO Get day lighting from model */
|
/* TODO Get day lighting from model */
|
||||||
dayfactor = _getDayFactor(definition->propDayTime()->getValue());
|
dayfactor = _getDayFactor(definition->getDaytime());
|
||||||
|
|
||||||
/* Fog masking */
|
/* Fog masking */
|
||||||
if (humidity > 0.3) {
|
if (humidity > 0.3) {
|
||||||
|
@ -87,9 +88,7 @@ AtmosphereResult BaseAtmosphereRenderer::getSkyColor(const Vector3 &) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 BaseAtmosphereRenderer::getSunDirection(bool) const {
|
Vector3 BaseAtmosphereRenderer::getSunDirection(bool) const {
|
||||||
AtmosphereDefinition *atmosphere = getDefinition();
|
return getDefinition()->childSun()->getDirection();
|
||||||
double sun_angle = (atmosphere->propDayTime()->getValue() + 0.75) * M_PI * 2.0;
|
|
||||||
return Vector3(cos(sun_angle), sin(sun_angle), 0.0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseAtmosphereRenderer::getLightsAt(vector<LightComponent> &, const Vector3 &) const {
|
bool BaseAtmosphereRenderer::getLightsAt(vector<LightComponent> &, const Vector3 &) const {
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#include "SurfaceMaterial.h"
|
#include "SurfaceMaterial.h"
|
||||||
#include "LightComponent.h"
|
#include "LightComponent.h"
|
||||||
#include "LightStatus.h"
|
#include "LightStatus.h"
|
||||||
|
#include "CelestialBodyDefinition.h"
|
||||||
|
#include "FloatNode.h"
|
||||||
|
|
||||||
#define WORLD_SCALING 0.05
|
#define WORLD_SCALING 0.05
|
||||||
#define MOON_DISTANCE 384403.0
|
#define MOON_DISTANCE 384403.0
|
||||||
|
@ -56,11 +58,10 @@ const Color NightSky::getColor(double altitude, const Vector3 &direction) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get moon
|
// Get moon
|
||||||
VectorSpherical moon_location_s = {MOON_DISTANCE_SCALED, atmosphere->moon_theta, -atmosphere->moon_phi};
|
Vector3 moon_direction = atmosphere->childMoon()->getDirection();
|
||||||
Vector3 moon_position(moon_location_s);
|
Vector3 moon_position = moon_direction.scale(MOON_DISTANCE_SCALED);
|
||||||
Vector3 moon_direction = moon_position.normalize();
|
|
||||||
if (moon_direction.dotProduct(direction) >= 0) {
|
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;
|
Vector3 hit1, hit2;
|
||||||
int hits = Geometry::rayIntersectSphere(location, direction, moon_position, moon_radius, &hit1, &hit2);
|
int hits = Geometry::rayIntersectSphere(location, direction, moon_position, moon_radius, &hit1, &hit2);
|
||||||
if (hits > 1) {
|
if (hits > 1) {
|
||||||
|
@ -87,10 +88,9 @@ bool NightSky::getLightsAt(vector<LightComponent> &result, const Vector3 &) cons
|
||||||
LightComponent moon, sky;
|
LightComponent moon, sky;
|
||||||
|
|
||||||
AtmosphereDefinition *atmosphere = renderer->getScenery()->getAtmosphere();
|
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.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.reflection = 0.2;
|
||||||
moon.altered = 1;
|
moon.altered = 1;
|
||||||
|
|
||||||
|
|
|
@ -10,15 +10,15 @@ TEST(Scenery, saveGlobal) {
|
||||||
Scenery scenery1;
|
Scenery scenery1;
|
||||||
scenery1.autoPreset();
|
scenery1.autoPreset();
|
||||||
scenery1.getTerrain()->propWaterHeight()->setValue(0.2);
|
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");
|
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;
|
Scenery scenery2;
|
||||||
result = scenery2.loadGlobal("/tmp/test_paysages_scenery");
|
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.2, scenery2.getTerrain()->propWaterHeight()->getValue());
|
||||||
EXPECT_DOUBLE_EQ(0.53, scenery2.getAtmosphere()->propDayTime()->getValue());
|
EXPECT_DOUBLE_EQ(0.53, scenery2.getAtmosphere()->getDaytime());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue