paysages : Fixed sun drawing algorithm.

git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@510 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
Michaël Lemaire 2013-01-30 17:00:26 +00:00 committed by ThunderK
parent ed268098a1
commit 620877bf64
12 changed files with 76 additions and 33 deletions

1
TODO
View file

@ -42,7 +42,6 @@ Technlogy Preview 3 :
=> Add user markers on OSD.
=> Add areas marking.
- Add a noise automatic filler.
- Fix the distorted sun appearance.
- Lock some previews together (eg: terrain height and colored preview).
- Find a new licence.

View file

@ -82,7 +82,7 @@ FormAtmosphere::FormAtmosphere(QWidget *parent):
addInputInt(tr("Day time (hour)"), &_definition->hour, 0, 23, 1, 10);
addInputInt(tr("Day time (minute)"), &_definition->minute, 0, 59, 1, 10);
//addInputColor(tr("Sun color"), &_definition->sun_color);
addInputDouble(tr("Sun radius"), &_definition->sun_radius, 0.0, 0.1, 0.001, 0.01);
addInputDouble(tr("Sun radius"), &_definition->sun_radius, 0.0, 5.0, 0.05, 0.5);
addInputDouble(tr("Influence of skydome on lighting"), &_definition->dome_lighting, 0.0, 2.0, 0.01, 0.1);
addInputDouble(tr("Humidity"), &_definition->humidity, 0.0, 1.0, 0.01, 0.1)->setVisibilityCondition((int*)&_definition->model, 0);

View file

@ -219,7 +219,7 @@ int WidgetCurveEditor::getPointAt(int x, int y)
{
curveGetPoint(_curve, i, &point);
curveToScreen(point.position, point.value, &dx, &dy);
ndistance = toolsGetDistance2D((double)x, (double)y, (double)dx, (double)dy);
ndistance = euclidGetDistance2D((double)x, (double)y, (double)dx, (double)dy);
if (nearest < 0 || ndistance < distance)
{
distance = ndistance;

View file

@ -1,4 +1,4 @@
#include "public.h"
#include "private.h"
/*
* Atmospheric scattering, based on E. Bruneton and F.Neyret work.
@ -18,7 +18,6 @@
/*********************** Constants ***********************/
#define WORLD_SCALING 0.05
#define GROUND_OFFSET 0.5
static const double Rg = 6360.0;
static const double Rt = 6420.0;
@ -1168,7 +1167,7 @@ Color brunetonApplyAerialPerspective(Renderer* renderer, Vector3 location, Color
{
Vector3 eye = renderer->camera_location;
Vector3 direction = v3Scale(v3Sub(location, eye), WORLD_SCALING);
Vector3 sun_position = v3Scale(renderer->atmosphere->getSunDirection(renderer), 149597870.0);
Vector3 sun_position = v3Scale(renderer->atmosphere->getSunDirection(renderer), SUN_DISTANCE);
Vector3 x = {0.0, Rg + (max(eye.y, 0.0) + GROUND_OFFSET) * WORLD_SCALING, 0.0};
Vector3 v = v3Normalize(direction);
@ -1200,7 +1199,7 @@ void brunetonGetLightingStatus(Renderer* renderer, LightStatus* status, Vector3
double r0 = Rg + (max(lightingGetStatusLocation(status).y, 0.0) + GROUND_OFFSET) * WORLD_SCALING;
Vector3 up = {0.0, 1.0, 0.0};
Vector3 sun_position = v3Scale(renderer->atmosphere->getSunDirection(renderer), 149597870.0);
Vector3 sun_position = v3Scale(renderer->atmosphere->getSunDirection(renderer), SUN_DISTANCE);
Vector3 x = {0.0, r0, 0.0};
Vector3 s = v3Normalize(v3Sub(sun_position, x));

View file

@ -120,7 +120,6 @@ static Color _fakeGetSkyColor(Renderer* renderer, Vector3 direction)
static Color _getSkyColor(Renderer* renderer, Vector3 direction)
{
AtmosphereDefinition* definition;
double dist;
Vector3 sun_direction, sun_position;
Color sky_color, sun_color;
@ -128,9 +127,7 @@ static Color _getSkyColor(Renderer* renderer, Vector3 direction)
sun_direction = renderer->atmosphere->getSunDirection(renderer);
direction = v3Normalize(direction);
dist = v3Norm(v3Sub(direction, sun_direction));
sun_position = v3Scale(sun_direction, 149597870.0);
sun_position = v3Scale(sun_direction, SUN_DISTANCE_SCALED);
/* Get base scattering*/
switch (definition->model)
@ -146,19 +143,25 @@ static Color _getSkyColor(Renderer* renderer, Vector3 direction)
}
/* Get sun shape */
if (dist < definition->sun_radius)
double sun_radius = definition->sun_radius * SUN_RADIUS_SCALED;
Vector3 hit1, hit2;
int hits = euclidRayIntersectSphere(renderer->camera_location, direction, sun_position, sun_radius, &hit1, &hit2);
if (hits > 1)
{
double dist = v3Norm(v3Sub(hit2, hit1)) / sun_radius; /* distance between intersection points (relative to radius) */
sun_color = definition->sun_color;
sun_color.r *= 100.0;
sun_color.g *= 100.0;
sun_color.b *= 100.0;
if (dist <= definition->sun_radius * 0.9)
if (dist > 0.05)
{
return sun_color;
}
else
{
sun_color.a = (dist - definition->sun_radius * 0.9) / (definition->sun_radius * 0.1);
sun_color.a = 1.0 - dist / 0.05;
colorMask(&sky_color, &sun_color);
return sky_color;
}

View file

@ -10,7 +10,7 @@ void atmosphereAutoPreset(AtmosphereDefinition* definition, AtmospherePreset pre
definition->sun_color.g = 0.95;
definition->sun_color.b = 0.9;
definition->sun_color.a = 1.0;
definition->sun_radius = 0.02;
definition->sun_radius = 1.0;
definition->humidity = 0.1;
switch (preset)

View file

@ -5,6 +5,13 @@
#define SPHERE_SIZE 10000.0
/* Factor to convert software units to kilometers */
#define WORLD_SCALING 0.05
#define SUN_DISTANCE 149597870.0
#define SUN_DISTANCE_SCALED (SUN_DISTANCE / WORLD_SCALING)
#define SUN_RADIUS 6.955e5
#define SUN_RADIUS_SCALED (SUN_RADIUS / WORLD_SCALING)
Color basicApplyAerialPerspective(Renderer* renderer, Vector3 location, Color base);
void basicGetLightingStatus(Renderer* renderer, LightStatus* status, Vector3 normal, int opaque);

View file

@ -46,7 +46,7 @@ void sceneryQuit()
void sceneryAutoPreset()
{
terrainAutoPreset(_terrain, TERRAIN_PRESET_STANDARD);
atmosphereAutoPreset(_atmosphere, ATMOSPHERE_MODEL_BRUNETON);
atmosphereAutoPreset(_atmosphere, ATMOSPHERE_PRESET_CLEAR_DAY);
cloudsAutoPreset(_clouds, CLOUDS_PRESET_PARTLY_CLOUDY);
}

View file

@ -54,17 +54,3 @@ void toolsFloat2DMapCopy(double* src, double* dest, int src_xstart, int src_ysta
dest = dest_row + dest_ystep;
}
}
Vector3 toolsGetNormalFromTriangle(Vector3 center, Vector3 bottom, Vector3 right)
{
Vector3 dx = v3Sub(right, center);
Vector3 dz = v3Sub(bottom, center);
return v3Normalize(v3Cross(dz, dx));
}
double toolsGetDistance2D(double x1, double y1, double x2, double y2)
{
double dx = x2 - x1;
double dy = y2 - y1;
return sqrt(dx * dx + dy * dy);
}

View file

@ -2,7 +2,6 @@
#define _PAYSAGES_TOOLS_H_
#include "shared/types.h"
#include "tools/euclid.h"
#ifdef __cplusplus
extern "C" {
@ -14,8 +13,6 @@ double toolsRandom();
double toolsCubicInterpolate(double stencil[4], double x);
double toolsBicubicInterpolate(double stencil[16], double x, double y);
void toolsFloat2DMapCopy(double* src, double* dest, int src_xstart, int src_ystart, int dest_xstart, int dest_ystart, int xsize, int ysize, int src_xstep, int src_ystep, int dest_xstep, int dest_ystep);
Vector3 toolsGetNormalFromTriangle(Vector3 center, Vector3 bottom, Vector3 right);
double toolsGetDistance2D(double x1, double y1, double x2, double y2);
#ifdef __cplusplus
}

View file

@ -405,3 +405,51 @@ Matrix4 m4Inverse(Matrix4 m)
}
}
Vector3 euclidGetNormalFromTriangle(Vector3 center, Vector3 bottom, Vector3 right)
{
Vector3 dx = v3Sub(right, center);
Vector3 dz = v3Sub(bottom, center);
return v3Normalize(v3Cross(dz, dx));
}
double euclidGetDistance2D(double x1, double y1, double x2, double y2)
{
double dx = x2 - x1;
double dy = y2 - y1;
return sqrt(dx * dx + dy * dy);
}
int euclidRayIntersectSphere(Vector3 ray_point, Vector3 ray_direction, Vector3 sphere_center, double sphere_radius, Vector3* hit1, Vector3* hit2)
{
Vector3 ray_direction_sphere;
double a, b, c, d;
ray_direction_sphere = v3Sub(ray_point, sphere_center);
a = ray_direction.x * ray_direction.x + ray_direction.y * ray_direction.y + ray_direction.z * ray_direction.z;
b = 2 * (ray_direction.x * ray_direction_sphere.x + ray_direction.y * ray_direction_sphere.y + ray_direction.z * ray_direction_sphere.z);
c = ray_direction_sphere.x * ray_direction_sphere.x + ray_direction_sphere.y * ray_direction_sphere.y + ray_direction_sphere.z * ray_direction_sphere.z - sphere_radius * sphere_radius;
d = b * b - 4 * a * c;
if (d < 0.0)
{
return 0;
}
else if (d > 0.0)
{
if (hit1 && hit2)
{
*hit1 = v3Add(ray_point, v3Scale(ray_direction, (-b - sqrt(d)) / (2 * a)));
*hit2 = v3Add(ray_point, v3Scale(ray_direction, (-b + sqrt(d)) / (2 * a)));
}
return 2;
}
else
{
if (hit1)
{
*hit1 = v3Add(ray_point, v3Scale(ray_direction, -b / (2 * a)));
}
return 1;
}
}

View file

@ -74,6 +74,10 @@ Matrix4 m4NewPerspective(double fov_y, double aspect, double near, double far);
double m4Determinant(Matrix4 m);
Matrix4 m4Inverse(Matrix4 m);
Vector3 euclidGetNormalFromTriangle(Vector3 center, Vector3 bottom, Vector3 right);
double euclidGetDistance2D(double x1, double y1, double x2, double y2);
int euclidRayIntersectSphere(Vector3 ray_point, Vector3 ray_direction, Vector3 sphere_center, double sphere_radius, Vector3* hit1, Vector3* hit2);
#ifdef __cplusplus
}
#endif