Fixed sun and moon radius being inconsistent
This commit is contained in:
parent
6b6710f15c
commit
f4bc02c5ca
14 changed files with 84 additions and 33 deletions
|
@ -102,8 +102,8 @@ void AtmosphereDefinition::applyPreset(AtmospherePreset preset, RandomGenerator
|
|||
sun_color.g = 0.95;
|
||||
sun_color.b = 0.9;
|
||||
sun_color.a = 1.0;
|
||||
sun->propRadius()->setValue(1.0);
|
||||
sun->propDistance()->setValue(Scenery::SUN_DISTANCE_SCALED);
|
||||
sun->propRadius()->setValue(Scenery::SUN_RADIUS_SCALED);
|
||||
moon->propDistance()->setValue(384403.0 * Scenery::KM_TO_UNIT);
|
||||
moon->propRadius()->setValue(1737.4 * Scenery::KM_TO_UNIT);
|
||||
moon->propPhi()->setValue(0.5);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "CelestialBodyDefinition.h"
|
||||
|
||||
#include <cmath>
|
||||
#include "Vector3.h"
|
||||
#include "FloatNode.h"
|
||||
#include "Scenery.h"
|
||||
|
@ -12,6 +13,11 @@ CelestialBodyDefinition::CelestialBodyDefinition(DefinitionNode *parent, const s
|
|||
radius = new FloatNode(this, "radius");
|
||||
}
|
||||
|
||||
Vector3 CelestialBodyDefinition::getGlobalDirection() const {
|
||||
VectorSpherical spc = {1.0, theta->getValue(), -phi->getValue()};
|
||||
return Vector3(spc);
|
||||
}
|
||||
|
||||
Vector3 CelestialBodyDefinition::getLocation(bool over_water) const {
|
||||
VectorSpherical spc = {distance->getValue(), theta->getValue(), -phi->getValue()};
|
||||
if (over_water) {
|
||||
|
@ -20,3 +26,7 @@ Vector3 CelestialBodyDefinition::getLocation(bool over_water) const {
|
|||
return Vector3(spc);
|
||||
}
|
||||
}
|
||||
|
||||
double CelestialBodyDefinition::getAngularRadius() const {
|
||||
return 2.0 * atan(radius->getValue() / distance->getValue());
|
||||
}
|
||||
|
|
|
@ -25,6 +25,11 @@ class DEFINITIONSHARED_EXPORT CelestialBodyDefinition : public DefinitionNode {
|
|||
return radius;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the normalized direction of the celestial body, from the center of the earth.
|
||||
*/
|
||||
Vector3 getGlobalDirection() const;
|
||||
|
||||
/**
|
||||
* Get the location of the celestial body.
|
||||
*
|
||||
|
@ -33,6 +38,11 @@ class DEFINITIONSHARED_EXPORT CelestialBodyDefinition : public DefinitionNode {
|
|||
*/
|
||||
Vector3 getLocation(bool over_water = true) const;
|
||||
|
||||
/**
|
||||
* Get the angular radius, when viewed from earth.
|
||||
*/
|
||||
double getAngularRadius() const;
|
||||
|
||||
private:
|
||||
FloatNode *distance;
|
||||
FloatNode *phi;
|
||||
|
|
|
@ -39,7 +39,7 @@ class DEFINITIONSHARED_EXPORT Scenery : public DefinitionNode {
|
|||
static constexpr double SUN_DISTANCE_SCALED = SUN_DISTANCE * KM_TO_UNIT;
|
||||
|
||||
static constexpr double SUN_RADIUS = 6.955e5;
|
||||
static constexpr double SUN_RADIUS_SCALED = EARTH_RADIUS * KM_TO_UNIT;
|
||||
static constexpr double SUN_RADIUS_SCALED = SUN_RADIUS * KM_TO_UNIT;
|
||||
|
||||
static constexpr double FAR_LIMIT_SCALED = 20000.0;
|
||||
|
||||
|
|
|
@ -414,13 +414,12 @@ static void testTextures() {
|
|||
}
|
||||
}
|
||||
|
||||
static void testMoonRendering() {
|
||||
static void testCelestialBodies() {
|
||||
Scenery scenery;
|
||||
scenery.autoPreset(8);
|
||||
scenery.getTerrain()->propHeightNoise()->setConfig(0.0);
|
||||
scenery.getClouds()->clear();
|
||||
scenery.getCamera()->setLocation(VECTOR_ZERO);
|
||||
scenery.getCamera()->setTarget(scenery.getAtmosphere()->childMoon()->getLocation());
|
||||
scenery.getCamera()->setFov(0.1);
|
||||
|
||||
SoftwareCanvasRenderer renderer(&scenery);
|
||||
renderer.setSize(600, 600);
|
||||
|
@ -429,25 +428,40 @@ static void testMoonRendering() {
|
|||
/*SkyRasterizer rasterizer(&renderer, renderer.getProgressHelper(), 0);
|
||||
renderer.setSoloRasterizer(&rasterizer);*/
|
||||
|
||||
// During the day
|
||||
scenery.getCamera()->setTarget(scenery.getAtmosphere()->childMoon()->getLocation());
|
||||
scenery.getCamera()->setFov(0.02);
|
||||
|
||||
scenery.getAtmosphere()->setDayTime(17, 30);
|
||||
startTestRender(&renderer, "moon", 0);
|
||||
startTestRender(&renderer, "celestial_bodies_moon_day");
|
||||
|
||||
// At night
|
||||
scenery.getAtmosphere()->setDayTime(23);
|
||||
startTestRender(&renderer, "moon", 1);
|
||||
startTestRender(&renderer, "celestial_bodies_moon_night");
|
||||
|
||||
// Eclipse
|
||||
scenery.getAtmosphere()->childSun()->propPhi()->setValue(scenery.getAtmosphere()->childMoon()->propPhi()->getValue());
|
||||
scenery.getAtmosphere()->childSun()->propTheta()->setValue(scenery.getAtmosphere()->childMoon()->propTheta()->getValue());
|
||||
startTestRender(&renderer, "moon", 2);
|
||||
scenery.getCamera()->setFov(0.2);
|
||||
|
||||
scenery.getAtmosphere()->setDayTime(6);
|
||||
scenery.getCamera()->setTarget(scenery.getAtmosphere()->childSun()->getLocation());
|
||||
startTestRender(&renderer, "celestial_bodies_sun_horizon");
|
||||
|
||||
scenery.getAtmosphere()->setDayTime(6, 30);
|
||||
scenery.getCamera()->setTarget(scenery.getAtmosphere()->childSun()->getLocation());
|
||||
startTestRender(&renderer, "celestial_bodies_sun_rising");
|
||||
|
||||
scenery.getAtmosphere()->setDayTime(11);
|
||||
scenery.getCamera()->setFov(0.1);
|
||||
|
||||
scenery.getAtmosphere()->childSun()->propPhi()->setValue(
|
||||
scenery.getAtmosphere()->childMoon()->propPhi()->getValue());
|
||||
scenery.getAtmosphere()->childSun()->propTheta()->setValue(
|
||||
scenery.getAtmosphere()->childMoon()->propTheta()->getValue());
|
||||
startTestRender(&renderer, "celestial_bodies_solar_eclipse");
|
||||
}
|
||||
|
||||
void runTestSuite() {
|
||||
testNoise();
|
||||
testTextures();
|
||||
testGodRays();
|
||||
testMoonRendering();
|
||||
testCelestialBodies();
|
||||
testNearFrustum();
|
||||
testCloudsNearGround();
|
||||
testVegetationModels();
|
||||
|
|
|
@ -91,8 +91,7 @@ void ModelerCameras::timerEvent(QTimerEvent *) {
|
|||
|
||||
void ModelerCameras::nodeChanged(const DefinitionNode *node, const DefinitionDiff *) {
|
||||
if (node->getPath().find("/atmosphere/sun/") == 0 and tool_mode == TOOL_SUN) {
|
||||
Vector3 direction = parent->getRenderer()->getAtmosphereRenderer()->getSunDirection();
|
||||
tool->setTarget(tool->getLocation().add(direction));
|
||||
tool->setTarget(parent->getRenderer()->getAtmosphereRenderer()->getSunLocation());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ BaseSection {
|
|||
id: panel_sun_radius
|
||||
anchors.left: toolbar.right
|
||||
minimumValue: 0
|
||||
maximumValue: 3
|
||||
maximumValue: 30000000
|
||||
enabled: false
|
||||
objectName: "atmosphere_sun_radius"
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "OpenGLShaderProgram.h"
|
||||
#include "OpenGLSharedState.h"
|
||||
#include "OpenGLVertexArray.h"
|
||||
#include "CelestialBodyDefinition.h"
|
||||
#include "Scenery.h"
|
||||
#include "AtmosphereDefinition.h"
|
||||
#include "AtmosphereRenderer.h"
|
||||
|
@ -82,7 +83,7 @@ void OpenGLSkybox::nodeChanged(const DefinitionNode *node, const DefinitionDiff
|
|||
AtmosphereDefinition *newdef = renderer->getScenery()->getAtmosphere();
|
||||
|
||||
if (node->getPath() == path_sun_phi or node->getPath() == path_sun_theta) {
|
||||
Vector3 sun_direction = renderer->getAtmosphereRenderer()->getSunDirection();
|
||||
Vector3 sun_direction = newdef->childSun()->getGlobalDirection();
|
||||
state->set("sunDirection", sun_direction);
|
||||
|
||||
Color sun_color = newdef->sun_color;
|
||||
|
@ -100,6 +101,6 @@ void OpenGLSkybox::floatNodeChanged(const string &path, double new_value, double
|
|||
if (path == path_humidity) {
|
||||
state->set("atmosphereHumidity", new_value);
|
||||
} else if (path == path_sun_radius) {
|
||||
state->set("sunRadius", new_value);
|
||||
state->set("sunRadius", renderer->getScenery()->getAtmosphere()->childSun()->getAngularRadius());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ vec4 _sunTransmittance(vec3 v, vec3 s, float r, float mu, float radius)
|
|||
vec4 transmittance = r <= Rt ? _transmittanceWithShadow(r, mu) : vec4(1.0); /* T(x,xo) */
|
||||
float d = _limit(r, mu);
|
||||
radius *= (1.0 + 15.0 * d / Rt); /* Inflating due to lens effect near horizon */
|
||||
float isun = step(cos(radius * M_PI / 180.0), dot(v, s)) * ISun; /* Lsun */
|
||||
float isun = step(cos(radius), dot(v, s)) * ISun; /* Lsun */
|
||||
transmittance.r *= isun;
|
||||
transmittance.g *= isun;
|
||||
transmittance.b *= isun;
|
||||
|
|
|
@ -861,8 +861,8 @@ static Color _getInscatterColor(Vector3 *_x, double *_t, Vector3 v, Vector3 s, d
|
|||
static Color _sunColor(Vector3 v, Vector3 s, double r, double mu, double radius) {
|
||||
Color transmittance = r <= Rt ? _transmittanceWithShadow(r, mu) : COLOR_WHITE; /* T(x,xo) */
|
||||
double d = _limit(r, mu);
|
||||
radius *= (1.0 + 15.0 * d / Rt); /* Inflating due to lens effect near horizon */
|
||||
double isun = step(cos(radius * Maths::PI / 180.0), v.dotProduct(s)) * ISun; /* Lsun */
|
||||
radius *= (1.0 + 15.0 * d / Rt); /* Inflating due to lens effect near horizon */
|
||||
double isun = step(cos(radius), v.dotProduct(s)) * ISun; /* Lsun */
|
||||
transmittance.r *= isun;
|
||||
transmittance.g *= isun;
|
||||
transmittance.b *= isun;
|
||||
|
@ -1063,6 +1063,7 @@ AtmosphereModelBruneton::~AtmosphereModelBruneton() {
|
|||
|
||||
AtmosphereResult AtmosphereModelBruneton::getSkyColor(Vector3 eye, const Vector3 &direction,
|
||||
const Vector3 &sun_position, const Color &base) const {
|
||||
auto definition = parent->getScenery()->getAtmosphere();
|
||||
Vector3 x = {0.0, Rg + eye.y * Scenery::UNIT_TO_KM, 0.0};
|
||||
Vector3 v = direction.normalize();
|
||||
Vector3 s = sun_position.sub(x).normalize();
|
||||
|
@ -1073,8 +1074,7 @@ AtmosphereResult AtmosphereModelBruneton::getSkyColor(Vector3 eye, const Vector3
|
|||
|
||||
AtmosphereResult result;
|
||||
Vector3 attenuation;
|
||||
Color sunColor =
|
||||
_sunColor(v, s, r, mu, parent->getScenery()->getAtmosphere()->childSun()->propRadius()->getValue()); /* L0 */
|
||||
Color sunColor = _sunColor(v, s, r, mu, definition->childSun()->getAngularRadius()); /* L0 */
|
||||
|
||||
/*result.base.r = base.r + sunColor.r;
|
||||
result.base.g = base.g + sunColor.g;
|
||||
|
@ -1090,10 +1090,11 @@ AtmosphereResult AtmosphereModelBruneton::getSkyColor(Vector3 eye, const Vector3
|
|||
}
|
||||
|
||||
AtmosphereResult AtmosphereModelBruneton::applyAerialPerspective(Vector3 location, const Color &base) const {
|
||||
auto definition = parent->getScenery()->getAtmosphere();
|
||||
Vector3 eye = parent->getCameraLocation();
|
||||
eye.y = max(eye.y, 0.0);
|
||||
location.y = max(location.y, 0.0);
|
||||
Vector3 sun_position = parent->getAtmosphereRenderer()->getSunDirection().scale(Scenery::SUN_DISTANCE);
|
||||
Vector3 sun_position = definition->childSun()->getLocation(false).scale(Scenery::UNIT_TO_KM);
|
||||
|
||||
Vector3 direction = location.sub(eye).scale(Scenery::UNIT_TO_KM);
|
||||
double t = direction.getNorm();
|
||||
|
@ -1134,6 +1135,7 @@ AtmosphereResult AtmosphereModelBruneton::applyAerialPerspective(Vector3 locatio
|
|||
}
|
||||
|
||||
bool AtmosphereModelBruneton::getLightsAt(vector<LightComponent> &result, const Vector3 &location) const {
|
||||
auto definition = parent->getScenery()->getAtmosphere();
|
||||
LightComponent sun, irradiance;
|
||||
double muS;
|
||||
|
||||
|
@ -1141,13 +1143,13 @@ bool AtmosphereModelBruneton::getLightsAt(vector<LightComponent> &result, const
|
|||
|
||||
double r0 = Rg + WORKAROUND_OFFSET + altitude;
|
||||
Vector3 up = {0.0, 1.0, 0.0};
|
||||
Vector3 sun_position = parent->getAtmosphereRenderer()->getSunDirection().scale(Scenery::SUN_DISTANCE);
|
||||
Vector3 sun_position = definition->childSun()->getLocation(false).scale(Scenery::UNIT_TO_KM);
|
||||
Vector3 x = {0.0, r0, 0.0};
|
||||
Vector3 s = sun_position.sub(x).normalize();
|
||||
|
||||
muS = up.dotProduct(s);
|
||||
if (altitude > RL) {
|
||||
sun.color = parent->getScenery()->getAtmosphere()->sun_color;
|
||||
sun.color = definition->sun_color;
|
||||
} else {
|
||||
sun.color = _transmittanceWithShadow(r0, muS);
|
||||
}
|
||||
|
|
|
@ -80,6 +80,10 @@ AtmosphereResult BaseAtmosphereRenderer::getSkyColor(const Vector3 &) {
|
|||
return result;
|
||||
}
|
||||
|
||||
Vector3 BaseAtmosphereRenderer::getSunLocation() const {
|
||||
return getDefinition()->childSun()->getLocation();
|
||||
}
|
||||
|
||||
Vector3 BaseAtmosphereRenderer::getSunDirection() const {
|
||||
auto sun_location = getDefinition()->childSun()->getLocation();
|
||||
return sun_location.sub(parent->getCameraLocation()).normalize();
|
||||
|
@ -127,15 +131,14 @@ AtmosphereResult SoftwareBrunetonAtmosphereRenderer::applyAerialPerspective(cons
|
|||
|
||||
AtmosphereResult SoftwareBrunetonAtmosphereRenderer::getSkyColor(const Vector3 &direction) {
|
||||
AtmosphereDefinition *definition;
|
||||
Vector3 sun_direction, sun_position, camera_location;
|
||||
Vector3 sun_position, camera_location;
|
||||
Color base;
|
||||
|
||||
definition = getDefinition();
|
||||
camera_location = parent->getCameraLocation();
|
||||
|
||||
sun_direction = getSunDirection();
|
||||
Vector3 direction_norm = direction.normalize();
|
||||
sun_position = sun_direction.scale(Scenery::SUN_DISTANCE_SCALED);
|
||||
sun_position = getSunLocation();
|
||||
|
||||
base = COLOR_BLACK;
|
||||
|
||||
|
@ -145,7 +148,7 @@ AtmosphereResult SoftwareBrunetonAtmosphereRenderer::getSkyColor(const Vector3 &
|
|||
// Get sun shape
|
||||
/*if (v3Dot(sun_direction, direction) >= 0)
|
||||
{
|
||||
double sun_radius = definition->sun_radius * SUN_RADIUS_SCALED * 5.0; // FIXME Why should we multiply by 5 ?
|
||||
double sun_radius = definition->sun_radius * SUN_RADIUS_SCALED;
|
||||
Vector3 hit1, hit2;
|
||||
int hits = euclidRayIntersectSphere(camera_location, direction, sun_position, sun_radius, &hit1, &hit2);
|
||||
if (hits > 1)
|
||||
|
|
|
@ -17,6 +17,7 @@ class BaseAtmosphereRenderer : public LightSource {
|
|||
virtual AtmosphereResult applyAerialPerspective(const Vector3 &location, const Color &base);
|
||||
virtual AtmosphereResult getSkyColor(const Vector3 &direction);
|
||||
virtual Vector3 getSunDirection() const;
|
||||
virtual Vector3 getSunLocation() const;
|
||||
|
||||
virtual bool getLightsAt(vector<LightComponent> &result, const Vector3 &location) const override;
|
||||
|
||||
|
|
|
@ -55,8 +55,7 @@ const Color NightSky::getColor(double altitude, const Vector3 &direction) {
|
|||
Vector3 moon_position = atmosphere->childMoon()->getLocation();
|
||||
Vector3 moon_direction = moon_position.sub(renderer->getCameraLocation()).normalize();
|
||||
if (moon_direction.dotProduct(direction) >= 0) {
|
||||
// TODO Why need the multiplier ?
|
||||
double moon_radius = atmosphere->childMoon()->propRadius()->getValue() * 5.0;
|
||||
double moon_radius = atmosphere->childMoon()->propRadius()->getValue();
|
||||
Vector3 hit1, hit2;
|
||||
int hits = Geometry::rayIntersectSphere(location, direction, moon_position, moon_radius, &hit1, &hit2);
|
||||
if (hits > 1) {
|
||||
|
|
12
src/tests/CelestialBodyDefinition_Test.cpp
Normal file
12
src/tests/CelestialBodyDefinition_Test.cpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include "BaseTestCase.h"
|
||||
#include "CelestialBodyDefinition.h"
|
||||
|
||||
#include "FloatNode.h"
|
||||
|
||||
TEST(CelestialBodyDefinition, getAngularRadius) {
|
||||
CelestialBodyDefinition moon(NULL, "moon");
|
||||
moon.propDistance()->setValue(384403.0);
|
||||
moon.propRadius()->setValue(1737.4);
|
||||
|
||||
EXPECT_DOUBLE_EQ(0.0090394100441593961, moon.getAngularRadius());
|
||||
}
|
Loading…
Reference in a new issue