diff --git a/ChangeLog b/ChangeLog index 5d20049..27d4fc1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ Global : * Version handling in saved files. * Replaced old noise algorithm with Simplex Noise (up to 4 times faster). + * New noise settings for better shape control. Terrain : * Added canvases to paint the shape directly. @@ -16,9 +17,11 @@ Textures : Water : * Added foam. -Sky : +Atmosphere : + * Merged with sky module. * New sky model (based on Preetham's work). * Added sun halo control. + * Better previews. Clouds : * Added clouds hardness to light. diff --git a/gui_qt/formatmosphere.cpp b/gui_qt/formatmosphere.cpp index 926f3d4..709c9b5 100644 --- a/gui_qt/formatmosphere.cpp +++ b/gui_qt/formatmosphere.cpp @@ -26,21 +26,7 @@ public: protected: QColor getColor(double x, double y) { - y -= 100.0 * scaling; - if (y > 0.0) - { - return QColor(0, 0, 0); - } - else - { - Vector3 look; - - look.x = 1.0; - look.y = -y; - look.z = x; - - return colorToQColor(_renderer.atmosphere->getSkyColor(&_renderer, look)); - } + return colorToQColor(atmosphereGetPreview(&_renderer, x, -y, M_PI_2)); } void updateData() { @@ -63,21 +49,7 @@ public: protected: QColor getColor(double x, double y) { - y -= 100.0 * scaling; - if (y > 0.0) - { - return QColor(0, 0, 0); - } - else - { - Vector3 look; - - look.x = -1.0; - look.y = -y; - look.z = -x; - - return colorToQColor(_renderer.atmosphere->getSkyColor(&_renderer, look)); - } + return colorToQColor(atmosphereGetPreview(&_renderer, x, -y, -M_PI_2)); } void updateData() { @@ -91,8 +63,6 @@ private: FormAtmosphere::FormAtmosphere(QWidget *parent): BaseForm(parent) { - BaseInput* input; - _definition = (AtmosphereDefinition*)AtmosphereDefinitionClass.create(); previewWest = new PreviewSkyWest(this); diff --git a/lib_paysages/atmosphere/preview.c b/lib_paysages/atmosphere/preview.c new file mode 100644 index 0000000..5cd3fbc --- /dev/null +++ b/lib_paysages/atmosphere/preview.c @@ -0,0 +1,151 @@ +#include "public.h" + +#include "../renderer.h" +#include "../lighting.h" + +/* + * Atmosphere previews. + */ + +typedef struct +{ + Vector3 location; + double size; +} Mount; + +#define MOUNTS_COUNT 11 +static Mount MOUNTS[MOUNTS_COUNT] = { + {{2.0, 0.0, -4.0}, 4.0}, + {{-1.0, 0.0, -6.0}, 4.0}, + {{3.0, 0.0, -10.0}, 6.0}, + {{-8.0, 0.0, -15.0}, 6.0}, + {{10.0, 0.0, -20.0}, 6.0}, + {{-6.0, 0.0, -30.0}, 8.0}, + {{15.0, 0.0, -40.0}, 8.0}, + {{-20.0, 0.0, -50.0}, 8.0}, + {{10.0, 0.0, -60.0}, 10.0}, + {{-5.0, 0.0, -80.0}, 10.0}, + {{30.0, 0.0, -100.0}, 10.0}, +}; + +static SurfaceMaterial MOUNT_MATERIAL = {{0.0, 0.0, 0.0, 1.0}, 0.0, 0.0}; + +static inline int _rayIntersectsTriangle(Vector3 p, Vector3 d, Vector3 v0, Vector3 v1, Vector3 v2, Vector3* hit) +{ + Vector3 e1, e2, h, s, q; + double a, f, u, v, t; + + e1 = v3Sub(v1, v0); + e2 = v3Sub(v2, v0); + + h = v3Cross(d, e2); + a = v3Dot(e1, h); + + if (a > -0.00001 && a < 0.00001) + { + return 0; + } + + f = 1.0 / a; + s = v3Sub(p, v0); + u = f * v3Dot(s, h); + + if (u < 0.0 || u > 1.0) + { + return 0; + } + + q = v3Cross(s, e1); + v = f * v3Dot(d, q); + + if (v < 0.0 || u + v > 1.0) + { + return 0; + } + + t = f * v3Dot(e2, q); + + if (t > 0.00001) + { + *hit = v3Add(p, v3Scale(d, t)); + return 1; + } + else + { + return 0; + } +} + +static inline int _checkHitMountain(Vector3 eye, Vector3 direction, Mount mount, Vector3* hit) +{ + Vector3 v0 = mount.location; + Vector3 v1 = mount.location; + Vector3 v2 = mount.location; + v0.x -= mount.size; + v1.x += mount.size; + v2.y += mount.size; + return _rayIntersectsTriangle(eye, direction, v0, v1, v2, hit); +} + +static inline int _checkHitGround(Vector3 eye, Vector3 direction, Vector3* hit) +{ + if (direction.y > -0.0001) + { + return 0; + } + else + { + hit->x = eye.x - direction.x * eye.y / direction.y; + hit->y = 0.0; + hit->z = eye.z - direction.z * eye.y / direction.y; + return 1; + } +} + +static inline int _checkHit(Vector3 eye, Vector3 direction, Vector3* hit, Vector3* normal) +{ + int i; + for (i = 0; i < MOUNTS_COUNT; i++) + { + if (_checkHitMountain(eye, direction, MOUNTS[i], hit)) + { + *normal = VECTOR_SOUTH; + return 1; + } + } + + *normal = VECTOR_UP; + return _checkHitGround(eye, direction, hit); +} + +Color atmosphereGetPreview(Renderer* renderer, double x, double y, double heading) +{ + Vector3 eye = {0.0, 8.0, 0.0}; + Vector3 direction = {x, y, -1.0}; + Vector3 hit, normal; + Matrix4 rotation; + + rotation = m4NewRotateY(heading); + + if (_checkHit(eye, direction, &hit, &normal)) + { + Color color; + LightStatus light; + + normal = m4Transform(rotation, normal); + hit = m4Transform(rotation, hit); + + /* TODO Refactor lighting module for this to work */ + renderer->getLightStatus(renderer, &light, hit); + color = renderer->applyLightStatus(renderer, &light, hit, normal, MOUNT_MATERIAL); + color = COLOR_BLACK; + + return renderer->atmosphere->applyAerialPerspective(renderer, hit, color); + } + else + { + direction = m4Transform(rotation, direction); + + return renderer->atmosphere->getSkyColor(renderer, direction); + } +} diff --git a/lib_paysages/atmosphere/public.h b/lib_paysages/atmosphere/public.h index 294fb48..623c213 100644 --- a/lib_paysages/atmosphere/public.h +++ b/lib_paysages/atmosphere/public.h @@ -75,6 +75,7 @@ extern StandardDefinition AtmosphereDefinitionClass; extern StandardRenderer AtmosphereRendererClass; void atmosphereRenderSkydome(Renderer* renderer); +Color atmosphereGetPreview(Renderer* renderer, double x, double y, double heading); #ifdef __cplusplus }