2016-01-16 14:05:01 +00:00
|
|
|
#include "MoonRenderer.h"
|
|
|
|
|
2016-01-16 16:02:39 +00:00
|
|
|
#include <cmath>
|
2016-01-16 14:05:01 +00:00
|
|
|
#include "CelestialBodyDefinition.h"
|
|
|
|
#include "Color.h"
|
|
|
|
#include "LightingManager.h"
|
|
|
|
#include "Geometry.h"
|
|
|
|
#include "SurfaceMaterial.h"
|
|
|
|
#include "FloatNode.h"
|
2016-01-21 23:40:42 +00:00
|
|
|
#include "FractalNoise.h"
|
|
|
|
#include "NoiseNode.h"
|
2016-01-16 14:05:01 +00:00
|
|
|
|
|
|
|
class MoonRenderer::pimpl {
|
|
|
|
public:
|
2016-01-16 16:02:39 +00:00
|
|
|
pimpl() : definition(NULL, "moon") {
|
2016-01-16 14:05:01 +00:00
|
|
|
}
|
|
|
|
CelestialBodyDefinition definition;
|
|
|
|
};
|
|
|
|
|
2016-01-21 22:02:22 +00:00
|
|
|
MoonRenderer::MoonRenderer(CelestialBodyDefinition *moon_node) : DefinitionWatcher("MoonRenderer"), impl(new pimpl()) {
|
|
|
|
startWatchingPath(moon_node->getRoot(), moon_node->getPath());
|
2016-01-16 14:05:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MoonRenderer::~MoonRenderer() {
|
|
|
|
}
|
|
|
|
|
2016-01-16 15:21:02 +00:00
|
|
|
void MoonRenderer::nodeChanged(const DefinitionNode *, const DefinitionDiff *, const DefinitionNode *parent) {
|
|
|
|
if (auto moon_node = static_cast<const CelestialBodyDefinition *>(parent)) {
|
2016-01-16 14:05:01 +00:00
|
|
|
moon_node->copy(&impl->definition);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MoonRenderer::getLightsAt(vector<LightComponent> &result, const Vector3 &location) const {
|
|
|
|
LightComponent light;
|
|
|
|
|
2016-01-21 23:40:42 +00:00
|
|
|
// TODO Don't add if its contribution is negligible or below horizon
|
2016-01-16 14:05:01 +00:00
|
|
|
// TODO Take moon phase into account
|
|
|
|
|
|
|
|
light.color = Color(0.03, 0.03, 0.03);
|
|
|
|
light.direction = location.sub(impl->definition.getLocation()).normalize();
|
|
|
|
light.reflection = 0.2;
|
|
|
|
light.altered = true;
|
|
|
|
|
|
|
|
result.push_back(light);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
Color MoonRenderer::getColor(const Vector3 &eye, const Vector3 &direction, LightingManager *lighting) const {
|
|
|
|
auto moon_location = impl->definition.getLocation();
|
|
|
|
auto moon_direction = moon_location.sub(eye).normalize();
|
|
|
|
if (moon_direction.dotProduct(direction) >= 0) {
|
|
|
|
// TODO Alter radius near horizon (lens effect)
|
|
|
|
double moon_radius = impl->definition.propRadius()->getValue();
|
|
|
|
Vector3 hit1, hit2;
|
|
|
|
int hits = Geometry::rayIntersectSphere(eye, direction, moon_location, moon_radius, &hit1, &hit2);
|
|
|
|
if (hits > 1) {
|
|
|
|
// distance between intersection points (relative to radius)
|
|
|
|
double dist = hit2.sub(hit1).getNorm() / moon_radius;
|
|
|
|
auto nearest = (hit1.sub(eye).getNorm() > hit2.sub(eye).getNorm()) ? hit2 : hit1;
|
|
|
|
|
2016-01-16 16:02:39 +00:00
|
|
|
auto p1 = nearest.sub(moon_location).normalize();
|
|
|
|
auto coords = p1.toSpherical();
|
|
|
|
|
2016-01-21 23:40:42 +00:00
|
|
|
auto noise = impl->definition.propNoise()->getGenerator();
|
|
|
|
|
2016-01-16 16:02:39 +00:00
|
|
|
double precision = 0.00001;
|
|
|
|
coords.phi += precision;
|
|
|
|
auto p2 = Vector3(coords);
|
2016-01-21 23:40:42 +00:00
|
|
|
p2 = p2.scale(1.0 - precision * fabs(noise->get3d(0.01, p2.x, p2.y, p2.z)));
|
2016-01-16 16:02:39 +00:00
|
|
|
|
|
|
|
coords.phi -= precision;
|
|
|
|
coords.theta += precision;
|
|
|
|
auto p3 = Vector3(coords);
|
2016-01-21 23:40:42 +00:00
|
|
|
p3 = p3.scale(1.0 - precision * fabs(noise->get3d(0.01, p3.x, p3.y, p3.z)));
|
2016-01-16 16:02:39 +00:00
|
|
|
|
|
|
|
auto normal = p1.getNormal3(p2, p3);
|
|
|
|
|
2016-01-21 23:40:42 +00:00
|
|
|
double gradient = 2.0 + 10.0 * noise->get3d(0.01, 0.3 * p1.x + 12.0, 0.3 * p1.y - 4.8, -0.3 * p1.z + 7.4);
|
2016-01-16 16:02:39 +00:00
|
|
|
SurfaceMaterial material(Color(gradient, gradient, gradient));
|
2016-01-21 23:40:42 +00:00
|
|
|
material.hardness = 0.3;
|
2016-01-16 16:02:39 +00:00
|
|
|
|
|
|
|
auto moon_color = lighting->apply(eye, nearest, normal, material);
|
2016-01-16 14:05:01 +00:00
|
|
|
if (dist <= 0.05) {
|
|
|
|
moon_color.a *= 1.0 - dist / 0.05;
|
|
|
|
}
|
|
|
|
return moon_color;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return COLOR_TRANSPARENT;
|
|
|
|
}
|