diff --git a/src/basics/FractalNoise.cpp b/src/basics/FractalNoise.cpp index 2671c4c..0570aff 100644 --- a/src/basics/FractalNoise.cpp +++ b/src/basics/FractalNoise.cpp @@ -209,7 +209,8 @@ string FractalNoise::checkDistribution() { max = 0.0; mean = 0.0; for (int i = 0; i < samples; i++) { - val = getBase3d((random.genDouble() - 0.5) * 10.0, (random.genDouble() - 0.5) * 10.0, (random.genDouble() - 0.5) * 10.0); + val = getBase3d((random.genDouble() - 0.5) * 10.0, (random.genDouble() - 0.5) * 10.0, + (random.genDouble() - 0.5) * 10.0); min = std::min(val, min); max = std::max(val, max); mean += val * factor; diff --git a/src/basics/FractalNoise.h b/src/basics/FractalNoise.h index 74c8bd1..c9560e9 100644 --- a/src/basics/FractalNoise.h +++ b/src/basics/FractalNoise.h @@ -57,7 +57,7 @@ class BASICSSHARED_EXPORT FractalNoise { /** * Estimate the range of values this generator will yield with a very small detail value. */ - void estimateRange(double *min, double *max, double detail=0.000001) const; + void estimateRange(double *min, double *max, double detail = 0.000001) const; virtual double getBase1d(double x) const; virtual double getBase2d(double x, double y) const; diff --git a/src/definition/AtmosphereDefinition.cpp b/src/definition/AtmosphereDefinition.cpp index c838186..9bf925c 100644 --- a/src/definition/AtmosphereDefinition.cpp +++ b/src/definition/AtmosphereDefinition.cpp @@ -8,6 +8,8 @@ #include "GodRaysDefinition.h" #include "CelestialBodyDefinition.h" +#define WORLD_SCALING 0.05 + AtmosphereDefinition::AtmosphereDefinition(DefinitionNode *parent) : DefinitionNode(parent, "atmosphere", "atmosphere") { model = ATMOSPHERE_MODEL_DISABLED; @@ -102,7 +104,9 @@ void AtmosphereDefinition::applyPreset(AtmospherePreset preset, RandomGenerator sun_color.b = 0.9; sun_color.a = 1.0; sun->propRadius()->setValue(1.0); - moon->propRadius()->setValue(1.0); + sun->propDistance()->setValue(149597870.0 / WORLD_SCALING); + moon->propDistance()->setValue(384403.0 / WORLD_SCALING); + moon->propRadius()->setValue(1737.4 / WORLD_SCALING); moon->propPhi()->setValue(0.5); moon->propTheta()->setValue(0.3); diff --git a/src/definition/CelestialBodyDefinition.cpp b/src/definition/CelestialBodyDefinition.cpp index 3777868..9ae3217 100644 --- a/src/definition/CelestialBodyDefinition.cpp +++ b/src/definition/CelestialBodyDefinition.cpp @@ -3,16 +3,23 @@ #include "Vector3.h" #include "FloatNode.h" +static constexpr double WORLD_SCALING = 0.05; +static constexpr double EARTH_RADIUS = 6360.0; +static constexpr double EARTH_RADIUS_SCALED = EARTH_RADIUS / WORLD_SCALING; + CelestialBodyDefinition::CelestialBodyDefinition(DefinitionNode *parent, const string &name) : DefinitionNode(parent, name) { + distance = new FloatNode(this, "distance"); 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); +Vector3 CelestialBodyDefinition::getLocation(bool over_water) const { + VectorSpherical spc = {distance->getValue(), theta->getValue(), -phi->getValue()}; + if (over_water) { + return Vector3(spc).sub(VECTOR_DOWN.scale(EARTH_RADIUS_SCALED)); + } else { + return Vector3(spc); + } } - -// VectorSpherical moon_location_s = {MOON_DISTANCE_SCALED, atmosphere->moon_theta, -atmosphere->moon_phi}; diff --git a/src/definition/CelestialBodyDefinition.h b/src/definition/CelestialBodyDefinition.h index 9d86a98..a65207b 100644 --- a/src/definition/CelestialBodyDefinition.h +++ b/src/definition/CelestialBodyDefinition.h @@ -12,6 +12,9 @@ class DEFINITIONSHARED_EXPORT CelestialBodyDefinition : public DefinitionNode { public: CelestialBodyDefinition(DefinitionNode *parent, const string &name); + inline FloatNode *propDistance() const { + return distance; + } inline FloatNode *propPhi() const { return phi; } @@ -23,11 +26,15 @@ class DEFINITIONSHARED_EXPORT CelestialBodyDefinition : public DefinitionNode { } /** - * Get the normalized direction toward the celestial body (from the center of the earth). + * Get the location of the celestial body. + * + * If "over_water" is true, the location is given in standard coordinates with y=0.0 as water, + * otherwise in regard to the earth center. */ - Vector3 getDirection() const; + Vector3 getLocation(bool over_water = true) const; private: + FloatNode *distance; FloatNode *phi; FloatNode *theta; FloatNode *radius; diff --git a/src/definition/TerrainDefinition.cpp b/src/definition/TerrainDefinition.cpp index 75039e9..0751828 100644 --- a/src/definition/TerrainDefinition.cpp +++ b/src/definition/TerrainDefinition.cpp @@ -66,8 +66,7 @@ double TerrainDefinition::getGridHeight(int x, int z, bool with_painting) { return h; } -double TerrainDefinition::getInterpolatedHeight(double x, double z, bool with_painting, - bool water_offset) { +double TerrainDefinition::getInterpolatedHeight(double x, double z, bool with_painting, bool water_offset) { double h; if (!with_painting || !has_painting || !height_map->getInterpolatedValue(x, z, &h)) { diff --git a/src/interface/commandline/tests.cpp b/src/interface/commandline/tests.cpp index 5c554da..8450dbc 100644 --- a/src/interface/commandline/tests.cpp +++ b/src/interface/commandline/tests.cpp @@ -24,6 +24,7 @@ #include "VegetationModelDefinition.h" #include "VegetationInstance.h" #include "VegetationRenderer.h" +#include "CelestialBodyDefinition.h" #include "RayCastingResult.h" #include "OpenGLVegetationImpostor.h" #include "Texture2D.h" @@ -413,10 +414,33 @@ static void testTextures() { } } +static void testMoonRendering() { + Scenery scenery; + scenery.autoPreset(8); + 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); + renderer.setQuality(0.1); + renderer.getGodRaysSampler()->setEnabled(false); + /*SkyRasterizer rasterizer(&renderer, renderer.getProgressHelper(), 0); + renderer.setSoloRasterizer(&rasterizer);*/ + + scenery.getAtmosphere()->setDayTime(17, 30); + startTestRender(&renderer, "moon", 0); + + scenery.getAtmosphere()->setDayTime(23); + startTestRender(&renderer, "moon", 1); +} + void runTestSuite() { testNoise(); testTextures(); testGodRays(); + testMoonRendering(); testNearFrustum(); testCloudsNearGround(); testVegetationModels(); diff --git a/src/render/opengl/OpenGLSkybox.cpp b/src/render/opengl/OpenGLSkybox.cpp index cc9cfea..cec51f3 100644 --- a/src/render/opengl/OpenGLSkybox.cpp +++ b/src/render/opengl/OpenGLSkybox.cpp @@ -82,7 +82,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(false); + Vector3 sun_direction = renderer->getAtmosphereRenderer()->getSunDirection(); state->set("sunDirection", sun_direction); Color sun_color = newdef->sun_color; diff --git a/src/render/software/AtmosphereModelBruneton.cpp b/src/render/software/AtmosphereModelBruneton.cpp index 693ffca..c9f5b8e 100644 --- a/src/render/software/AtmosphereModelBruneton.cpp +++ b/src/render/software/AtmosphereModelBruneton.cpp @@ -1097,7 +1097,7 @@ AtmosphereResult AtmosphereModelBruneton::getSkyColor(Vector3 eye, const Vector3 } AtmosphereResult AtmosphereModelBruneton::applyAerialPerspective(Vector3 location, const Color &base) const { - Vector3 eye = parent->getCameraLocation(location); + 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(SUN_DISTANCE); @@ -1105,7 +1105,7 @@ AtmosphereResult AtmosphereModelBruneton::applyAerialPerspective(Vector3 locatio Vector3 direction = location.sub(eye).scale(WORLD_SCALING); double t = direction.getNorm(); if (t < 0.000001) { - direction = parent->getCameraDirection(location).scale(0.001 * WORLD_SCALING); + direction = parent->getCameraDirection().scale(0.001 * WORLD_SCALING); t = direction.getNorm(); } diff --git a/src/render/software/AtmosphereRenderer.cpp b/src/render/software/AtmosphereRenderer.cpp index 9bccf03..135360e 100644 --- a/src/render/software/AtmosphereRenderer.cpp +++ b/src/render/software/AtmosphereRenderer.cpp @@ -87,8 +87,9 @@ AtmosphereResult BaseAtmosphereRenderer::getSkyColor(const Vector3 &) { return result; } -Vector3 BaseAtmosphereRenderer::getSunDirection(bool) const { - return getDefinition()->childSun()->getDirection(); +Vector3 BaseAtmosphereRenderer::getSunDirection() const { + auto sun_location = getDefinition()->childSun()->getLocation(); + return sun_location.sub(parent->getCameraLocation()).normalize(); } bool BaseAtmosphereRenderer::getLightsAt(vector &, const Vector3 &) const { @@ -137,7 +138,7 @@ AtmosphereResult SoftwareBrunetonAtmosphereRenderer::getSkyColor(const Vector3 & Color base; definition = getDefinition(); - camera_location = parent->getCameraLocation(VECTOR_ZERO); + camera_location = parent->getCameraLocation(); sun_direction = getSunDirection(); Vector3 direction_norm = direction.normalize(); diff --git a/src/render/software/AtmosphereRenderer.h b/src/render/software/AtmosphereRenderer.h index e3bc749..d043778 100644 --- a/src/render/software/AtmosphereRenderer.h +++ b/src/render/software/AtmosphereRenderer.h @@ -16,7 +16,7 @@ class BaseAtmosphereRenderer : public LightSource { virtual AtmosphereResult applyAerialPerspective(const Vector3 &location, const Color &base); virtual AtmosphereResult getSkyColor(const Vector3 &direction); - virtual Vector3 getSunDirection(bool cache = true) const; + virtual Vector3 getSunDirection() const; virtual bool getLightsAt(vector &result, const Vector3 &location) const override; diff --git a/src/render/software/CloudBasicLayerRenderer.cpp b/src/render/software/CloudBasicLayerRenderer.cpp index 8c66be3..f4131b7 100644 --- a/src/render/software/CloudBasicLayerRenderer.cpp +++ b/src/render/software/CloudBasicLayerRenderer.cpp @@ -65,7 +65,7 @@ int CloudBasicLayerRenderer::findSegments(BaseCloudsModel *model, const Vector3 model->getDetailRange(&min_step, &max_step); - double distance = parent->getCameraLocation(start).sub(start).getNorm(); + double distance = parent->getCameraLocation().sub(start).getNorm(); render_precision = min_step + (max_step - min_step) * min(distance / (quality + 0.1), 100.0) * 0.01; segment_count = 0; diff --git a/src/render/software/GodRaysSampler.cpp b/src/render/software/GodRaysSampler.cpp index 7bf5e14..cb11394 100644 --- a/src/render/software/GodRaysSampler.cpp +++ b/src/render/software/GodRaysSampler.cpp @@ -38,7 +38,7 @@ GodRaysSampler::~GodRaysSampler() { } void GodRaysSampler::prepare(SoftwareRenderer *renderer) { - setCameraLocation(renderer->getCameraLocation(VECTOR_ZERO)); + setCameraLocation(renderer->getCameraLocation()); setLighting(renderer->getLightingManager()); setAltitudes(renderer->getScenery()->getTerrain()->getHeightInfo().min_height, renderer->getCloudsRenderer()->getHighestAltitude()); diff --git a/src/render/software/NightSky.cpp b/src/render/software/NightSky.cpp index 0bee210..b67fdcc 100644 --- a/src/render/software/NightSky.cpp +++ b/src/render/software/NightSky.cpp @@ -13,12 +13,6 @@ #include "CelestialBodyDefinition.h" #include "FloatNode.h" -#define WORLD_SCALING 0.05 -#define MOON_DISTANCE 384403.0 -#define MOON_DISTANCE_SCALED (MOON_DISTANCE / WORLD_SCALING) -#define MOON_RADIUS 1737.4 -#define MOON_RADIUS_SCALED (MOON_RADIUS / WORLD_SCALING) - NightSky::NightSky(SoftwareRenderer *renderer) : renderer(renderer) { } @@ -58,10 +52,11 @@ const Color NightSky::getColor(double altitude, const Vector3 &direction) { } // Get moon - Vector3 moon_direction = atmosphere->childMoon()->getDirection(); - Vector3 moon_position = moon_direction.scale(MOON_DISTANCE_SCALED); + Vector3 moon_position = atmosphere->childMoon()->getLocation(); + Vector3 moon_direction = moon_position.sub(renderer->getCameraLocation()).normalize(); if (moon_direction.dotProduct(direction) >= 0) { - double moon_radius = MOON_RADIUS_SCALED * 5.0 * atmosphere->childMoon()->propRadius()->getValue(); + // TODO Why need the multiplier ? + double moon_radius = atmosphere->childMoon()->propRadius()->getValue() * 5.0; Vector3 hit1, hit2; int hits = Geometry::rayIntersectSphere(location, direction, moon_position, moon_radius, &hit1, &hit2); if (hits > 1) { @@ -84,13 +79,13 @@ const Color NightSky::getColor(double altitude, const Vector3 &direction) { return result; } -bool NightSky::getLightsAt(vector &result, const Vector3 &) const { +bool NightSky::getLightsAt(vector &result, const Vector3 &loc) const { LightComponent moon, sky; AtmosphereDefinition *atmosphere = renderer->getScenery()->getAtmosphere(); moon.color = Color(0.03, 0.03, 0.03); // TODO take moon phase into account - moon.direction = atmosphere->childMoon()->getDirection().scale(-1.0); + moon.direction = loc.sub(atmosphere->childMoon()->getLocation()).normalize(); moon.reflection = 0.2; moon.altered = 1; diff --git a/src/render/software/SkyRasterizer.cpp b/src/render/software/SkyRasterizer.cpp index 0c3244d..edfa443 100644 --- a/src/render/software/SkyRasterizer.cpp +++ b/src/render/software/SkyRasterizer.cpp @@ -33,7 +33,7 @@ void SkyRasterizer::rasterizeToCanvas(CanvasPortion *canvas) { step_i = Maths::PI * 2.0 / to_double(res_i); step_j = Maths::PI / to_double(res_j); - camera_location = renderer->getCameraLocation(VECTOR_ZERO); + camera_location = renderer->getCameraLocation(); for (j = 0; j < res_j; j++) { if (interrupted) { @@ -77,7 +77,7 @@ Color SkyRasterizer::shadeFragment(const CanvasFragment &fragment, const CanvasF Vector3 camera_location, direction; Color result; - camera_location = renderer->getCameraLocation(location); + camera_location = renderer->getCameraLocation(); direction = location.sub(camera_location); // TODO Don't compute sky color if it's fully covered by clouds diff --git a/src/render/software/SoftwareRenderer.cpp b/src/render/software/SoftwareRenderer.cpp index 10615ad..48be00d 100644 --- a/src/render/software/SoftwareRenderer.cpp +++ b/src/render/software/SoftwareRenderer.cpp @@ -107,12 +107,12 @@ void SoftwareRenderer::setQuality(double quality) { Color SoftwareRenderer::applyLightingToSurface(const Vector3 &location, const Vector3 &normal, const SurfaceMaterial &material) { - return lighting->apply(getCameraLocation(location), location, normal, material); + return lighting->apply(getCameraLocation(), location, normal, material); } Color SoftwareRenderer::applyMediumTraversal(const Vector3 &location, const Color &color) { Color result = atmosphere_renderer->applyAerialPerspective(location, color).final; - result = clouds_renderer->getColor(getCameraLocation(location), location, result); + result = clouds_renderer->getColor(getCameraLocation(), location, result); return result; } @@ -132,11 +132,11 @@ RayCastingResult SoftwareRenderer::rayWalking(const Vector3 &location, const Vec return result; } -Vector3 SoftwareRenderer::getCameraLocation(const Vector3 &) { +Vector3 SoftwareRenderer::getCameraLocation() { return render_camera->getLocation(); } -Vector3 SoftwareRenderer::getCameraDirection(const Vector3 &) { +Vector3 SoftwareRenderer::getCameraDirection() { return render_camera->getDirectionNormalized(); } diff --git a/src/render/software/SoftwareRenderer.h b/src/render/software/SoftwareRenderer.h index 77609f5..0175576 100644 --- a/src/render/software/SoftwareRenderer.h +++ b/src/render/software/SoftwareRenderer.h @@ -19,8 +19,8 @@ class SOFTWARESHARED_EXPORT SoftwareRenderer { int render_quality; CameraDefinition *render_camera; - virtual Vector3 getCameraLocation(const Vector3 &target); - virtual Vector3 getCameraDirection(const Vector3 &target); + virtual Vector3 getCameraLocation(); + virtual Vector3 getCameraDirection(); virtual double getPrecision(const Vector3 &location); virtual Vector3 projectPoint(const Vector3 &point); virtual Vector3 unprojectPoint(const Vector3 &point); diff --git a/src/render/software/TerrainRasterizer.cpp b/src/render/software/TerrainRasterizer.cpp index b602fb4..f8b27fa 100644 --- a/src/render/software/TerrainRasterizer.cpp +++ b/src/render/software/TerrainRasterizer.cpp @@ -135,7 +135,7 @@ void TerrainRasterizer::getChunk(SoftwareRenderer *renderer, TerrainRasterizer:: int TerrainRasterizer::performTessellation(CanvasPortion *canvas) { TerrainChunkInfo chunk; int chunk_factor, chunk_count, i, result; - Vector3 cam = renderer->getCameraLocation(VECTOR_ZERO); + Vector3 cam = renderer->getCameraLocation(); double radius_int, radius_ext; double chunk_size; diff --git a/src/render/software/TerrainRenderer.cpp b/src/render/software/TerrainRenderer.cpp index 5bb0ecd..af55972 100644 --- a/src/render/software/TerrainRenderer.cpp +++ b/src/render/software/TerrainRenderer.cpp @@ -122,9 +122,9 @@ Color TerrainRenderer::getFinalColor(double x, double z, double precision) { i++; } - auto color = textures_renderer->getFinalComposition(textures_definition, parent->getLightingManager(), - current.first, current.second, normal, precision, - parent->getCameraLocation(top_location)); + auto color = + textures_renderer->getFinalComposition(textures_definition, parent->getLightingManager(), current.first, + current.second, normal, precision, parent->getCameraLocation()); return parent->applyMediumTraversal(top_location, color); } diff --git a/src/render/software/WaterRasterizer.cpp b/src/render/software/WaterRasterizer.cpp index 2869d2f..3c7c0df 100644 --- a/src/render/software/WaterRasterizer.cpp +++ b/src/render/software/WaterRasterizer.cpp @@ -53,7 +53,7 @@ void WaterRasterizer::setQuality(double factor) { int WaterRasterizer::performTessellation(CanvasPortion *canvas) { int chunk_factor, chunk_count, i, result; - Vector3 cam = renderer->getCameraLocation(VECTOR_ZERO); + Vector3 cam = renderer->getCameraLocation(); double radius_int, radius_ext, chunk_size; result = 0; diff --git a/src/render/software/WaterRenderer.cpp b/src/render/software/WaterRenderer.cpp index 8ffd701..832f8a0 100644 --- a/src/render/software/WaterRenderer.cpp +++ b/src/render/software/WaterRenderer.cpp @@ -166,7 +166,7 @@ WaterRenderer::WaterResult WaterRenderer::getResult(double x, double z) { } normal = _getNormal(definition, noise, location, detail); - look_direction = location.sub(parent->getCameraLocation(location)).normalize(); + look_direction = location.sub(parent->getCameraLocation()).normalize(); /* Reflection */ if (reflection == 0.0) {