paysages : Clouds refactoring (WIP).
git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@505 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
parent
0d3906a93e
commit
5c7ba1d4fc
27 changed files with 1007 additions and 957 deletions
|
@ -1,6 +1,5 @@
|
||||||
#include "formclouds.h"
|
#include "formclouds.h"
|
||||||
|
|
||||||
#include "../lib_paysages/clouds.h"
|
|
||||||
#include "../lib_paysages/tools/color.h"
|
#include "../lib_paysages/tools/color.h"
|
||||||
#include "../lib_paysages/tools/euclid.h"
|
#include "../lib_paysages/tools/euclid.h"
|
||||||
#include "../lib_paysages/scenery.h"
|
#include "../lib_paysages/scenery.h"
|
||||||
|
@ -13,48 +12,34 @@ class PreviewCloudsCoverage:public BasePreview
|
||||||
public:
|
public:
|
||||||
PreviewCloudsCoverage(QWidget* parent, CloudsLayerDefinition* layer):BasePreview(parent)
|
PreviewCloudsCoverage(QWidget* parent, CloudsLayerDefinition* layer):BasePreview(parent)
|
||||||
{
|
{
|
||||||
_renderer = rendererCreate();
|
_renderer = cloudsCreatePreviewCoverageRenderer();
|
||||||
_renderer->render_quality = 5;
|
|
||||||
//_renderer.applyLightStatus = _applyLightStatus;
|
|
||||||
|
|
||||||
_original_layer = layer;
|
_original_layer = layer;
|
||||||
_preview_layer = cloudsLayerCreateDefinition();
|
_preview_definition = (CloudsDefinition*)CloudsDefinitionClass.create();
|
||||||
|
|
||||||
configScaling(100.0, 1000.0, 20.0, 200.0);
|
configScaling(100.0, 1000.0, 20.0, 200.0);
|
||||||
}
|
}
|
||||||
~PreviewCloudsCoverage()
|
~PreviewCloudsCoverage()
|
||||||
{
|
{
|
||||||
cloudsLayerDeleteDefinition(_preview_layer);
|
CloudsDefinitionClass.destroy(_preview_definition);
|
||||||
rendererDelete(_renderer);
|
rendererDelete(_renderer);
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
Color getColor(double x, double y)
|
Color getColor(double x, double y)
|
||||||
{
|
{
|
||||||
Vector3 eye, look;
|
return cloudsGetPreviewCoverage(_renderer, x, y, scaling);
|
||||||
|
|
||||||
eye.x = 0.0;
|
|
||||||
eye.y = scaling;
|
|
||||||
eye.z = -10.0 * scaling;
|
|
||||||
look.x = x * 0.01 / scaling;
|
|
||||||
look.y = -y * 0.01 / scaling - 0.3;
|
|
||||||
look.z = 1.0;
|
|
||||||
look = v3Normalize(look);
|
|
||||||
|
|
||||||
return cloudsApplyLayer(_preview_layer, COLOR_BLUE, _renderer, eye, v3Add(eye, v3Scale(look, 1000.0)));
|
|
||||||
}
|
}
|
||||||
void updateData()
|
void updateData()
|
||||||
{
|
{
|
||||||
cloudsLayerCopyDefinition(_original_layer, _preview_layer);
|
layersDeleteLayer(_preview_definition->layers, 0);
|
||||||
}
|
layersAddLayer(_preview_definition->layers, _original_layer);
|
||||||
static Color _applyLightStatus(Renderer*, LightStatus*, Vector3, Vector3, SurfaceMaterial)
|
CloudsRendererClass.bind(_renderer, _preview_definition);
|
||||||
{
|
|
||||||
return COLOR_WHITE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Renderer* _renderer;
|
Renderer* _renderer;
|
||||||
CloudsLayerDefinition* _original_layer;
|
CloudsLayerDefinition* _original_layer;
|
||||||
CloudsLayerDefinition* _preview_layer;
|
CloudsDefinition* _preview_definition;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PreviewCloudsColor:public BasePreview
|
class PreviewCloudsColor:public BasePreview
|
||||||
|
@ -62,92 +47,28 @@ class PreviewCloudsColor:public BasePreview
|
||||||
public:
|
public:
|
||||||
PreviewCloudsColor(QWidget* parent, CloudsLayerDefinition* layer):BasePreview(parent)
|
PreviewCloudsColor(QWidget* parent, CloudsLayerDefinition* layer):BasePreview(parent)
|
||||||
{
|
{
|
||||||
LightDefinition light;
|
|
||||||
|
|
||||||
_original_layer = layer;
|
_original_layer = layer;
|
||||||
_preview_layer = cloudsLayerCreateDefinition();
|
_preview_definition = (CloudsDefinition*)CloudsDefinitionClass.create();
|
||||||
|
|
||||||
/*_lighting = lightingCreateDefinition();
|
_renderer = cloudsCreatePreviewColorRenderer();
|
||||||
light.color = COLOR_WHITE;
|
|
||||||
light.direction.x = -1.0;
|
|
||||||
light.direction.y = -1.0;
|
|
||||||
light.direction.z = 1.0;
|
|
||||||
light.direction = v3Normalize(light.direction);
|
|
||||||
light.filtered = 0;
|
|
||||||
light.masked = 1;
|
|
||||||
light.reflection = 1.0;
|
|
||||||
lightingAddLight(&_lighting, light);
|
|
||||||
lightingValidateDefinition(&_lighting);*/
|
|
||||||
|
|
||||||
_renderer = rendererCreate();
|
|
||||||
_renderer->render_quality = 8;
|
|
||||||
/*_renderer.alterLight = _alterLight;
|
|
||||||
_renderer.getLightStatus = _getLightStatus;*/
|
|
||||||
_renderer->customData[0] = _preview_layer;
|
|
||||||
//_renderer.customData[1] = &_lighting;
|
|
||||||
|
|
||||||
configScaling(0.5, 2.0, 0.1, 2.0);
|
configScaling(0.5, 2.0, 0.1, 2.0);
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
Color getColor(double x, double y)
|
Color getColor(double x, double y)
|
||||||
{
|
{
|
||||||
Vector3 start, end;
|
return cloudsGetPreviewColor(_renderer, x, y);
|
||||||
|
|
||||||
start.x = x * _preview_layer->thickness * 0.5;
|
|
||||||
start.y = -y * _preview_layer->thickness * 0.5;
|
|
||||||
start.z = _preview_layer->thickness * 0.5;
|
|
||||||
|
|
||||||
end.x = x * _preview_layer->thickness * 0.5;
|
|
||||||
end.y = -y * _preview_layer->thickness * 0.5;
|
|
||||||
end.z = -_preview_layer->thickness * 0.5;
|
|
||||||
|
|
||||||
return cloudsApplyLayer(_preview_layer, COLOR_BLUE, _renderer, start, end);
|
|
||||||
}
|
}
|
||||||
void updateData()
|
void updateData()
|
||||||
{
|
{
|
||||||
cloudsLayerCopyDefinition(_original_layer, _preview_layer);
|
layersDeleteLayer(_preview_definition->layers, 0);
|
||||||
//noiseForceValue(_preview_layer->shape_noise, 1.0);
|
layersAddLayer(_preview_definition->layers, _original_layer);
|
||||||
_preview_layer->lower_altitude = -_preview_layer->thickness * 0.5;
|
CloudsRendererClass.bind(_renderer, _preview_definition);
|
||||||
//curveClear(_preview_layer->coverage_by_altitude);
|
|
||||||
_preview_layer->base_coverage = 1.0;
|
|
||||||
_preview_layer->_custom_coverage = _coverageFunc;
|
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
Renderer* _renderer;
|
Renderer* _renderer;
|
||||||
CloudsLayerDefinition* _original_layer;
|
CloudsLayerDefinition* _original_layer;
|
||||||
CloudsLayerDefinition* _preview_layer;
|
CloudsDefinition* _preview_definition;
|
||||||
//LightingDefinition _lighting;
|
|
||||||
|
|
||||||
static double _coverageFunc(CloudsLayerDefinition* layer, Vector3 position)
|
|
||||||
{
|
|
||||||
double coverage = curveGetValue(layer->_coverage_by_altitude, position.y / layer->thickness + 0.5);
|
|
||||||
position.y = 0.0;
|
|
||||||
double dist = v3Norm(position);
|
|
||||||
|
|
||||||
if (dist >= layer->thickness * 0.5)
|
|
||||||
{
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
else if (dist < layer->thickness * 0.4)
|
|
||||||
{
|
|
||||||
return coverage;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
double density = 1.0 - (dist - (layer->thickness * 0.4)) / (layer->thickness * 0.1);
|
|
||||||
return (density < coverage) ? density : coverage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*static void _alterLight(Renderer* renderer, LightDefinition* light, Vector3 location)
|
|
||||||
{
|
|
||||||
light->color = cloudsLayerFilterLight((CloudsLayerDefinition*)renderer->customData[0], renderer, light->color, location, v3Scale(light->direction, -1000.0), v3Scale(light->direction, -1.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _getLightStatus(Renderer* renderer, LightStatus* status, Vector3 location)
|
|
||||||
{
|
|
||||||
lightingGetStatus((LightingDefinition*)renderer->customData[1], renderer, location, status);
|
|
||||||
}*/
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**************** Form ****************/
|
/**************** Form ****************/
|
||||||
|
@ -159,8 +80,8 @@ FormClouds::FormClouds(QWidget *parent):
|
||||||
addAutoPreset(tr("Stratocumulus"));
|
addAutoPreset(tr("Stratocumulus"));
|
||||||
addAutoPreset(tr("Stratus"));
|
addAutoPreset(tr("Stratus"));
|
||||||
|
|
||||||
_definition = cloudsCreateDefinition();
|
_definition = (CloudsDefinition*)CloudsDefinitionClass.create();
|
||||||
_layer = cloudsLayerCreateDefinition();
|
_layer = (CloudsLayerDefinition*)cloudsGetLayerType().callback_create();
|
||||||
|
|
||||||
_previewCoverage = new PreviewCloudsCoverage(parent, _layer);
|
_previewCoverage = new PreviewCloudsCoverage(parent, _layer);
|
||||||
_previewColor = new PreviewCloudsColor(parent, _layer);
|
_previewColor = new PreviewCloudsColor(parent, _layer);
|
||||||
|
@ -171,10 +92,7 @@ FormClouds::FormClouds(QWidget *parent):
|
||||||
addInputDouble(tr("Lower altitude"), &_layer->lower_altitude, -10.0, 50.0, 0.5, 5.0);
|
addInputDouble(tr("Lower altitude"), &_layer->lower_altitude, -10.0, 50.0, 0.5, 5.0);
|
||||||
addInputDouble(tr("Layer thickness"), &_layer->thickness, 0.0, 20.0, 0.1, 1.0);
|
addInputDouble(tr("Layer thickness"), &_layer->thickness, 0.0, 20.0, 0.1, 1.0);
|
||||||
addInputDouble(tr("Max coverage"), &_layer->base_coverage, 0.0, 1.0, 0.01, 0.1);
|
addInputDouble(tr("Max coverage"), &_layer->base_coverage, 0.0, 1.0, 0.01, 0.1);
|
||||||
// addInputCurve(tr("Coverage by altitude"), _layer->_coverage_by_altitude, 0.0, 1.0, 0.0, 1.0, tr("Altitude in cloud layer"), tr("Coverage value"));
|
|
||||||
// addInputNoise(tr("Shape noise"), _layer->_shape_noise);
|
|
||||||
addInputDouble(tr("Shape scaling"), &_layer->shape_scaling, 3.0, 30.0, 0.3, 3.0);
|
addInputDouble(tr("Shape scaling"), &_layer->shape_scaling, 3.0, 30.0, 0.3, 3.0);
|
||||||
// addInputNoise(tr("Edge noise"), _layer->_edge_noise);
|
|
||||||
addInputDouble(tr("Edge scaling"), &_layer->edge_scaling, 0.5, 5.0, 0.05, 0.5);
|
addInputDouble(tr("Edge scaling"), &_layer->edge_scaling, 0.5, 5.0, 0.05, 0.5);
|
||||||
addInputDouble(tr("Edge length"), &_layer->edge_length, 0.0, 1.0, 0.01, 0.1);
|
addInputDouble(tr("Edge length"), &_layer->edge_length, 0.0, 1.0, 0.01, 0.1);
|
||||||
addInputMaterial(tr("Material"), &_layer->material);
|
addInputMaterial(tr("Material"), &_layer->material);
|
||||||
|
@ -183,40 +101,34 @@ FormClouds::FormClouds(QWidget *parent):
|
||||||
addInputDouble(tr("Light traversal depth"), &_layer->lighttraversal, 0.0, 10.0, 0.1, 1.0);
|
addInputDouble(tr("Light traversal depth"), &_layer->lighttraversal, 0.0, 10.0, 0.1, 1.0);
|
||||||
addInputDouble(tr("Minimum lighting"), &_layer->minimumlight, 0.0, 1.0, 0.01, 0.1);
|
addInputDouble(tr("Minimum lighting"), &_layer->minimumlight, 0.0, 1.0, 0.01, 0.1);
|
||||||
|
|
||||||
setLayers(_definition.layers);
|
setLayers(_definition->layers);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FormClouds::revertConfig()
|
void FormClouds::revertConfig()
|
||||||
{
|
{
|
||||||
sceneryGetClouds(&_definition);
|
sceneryGetClouds(_definition);
|
||||||
BaseFormLayer::revertConfig();
|
BaseFormLayer::revertConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FormClouds::applyConfig()
|
void FormClouds::applyConfig()
|
||||||
{
|
{
|
||||||
BaseFormLayer::applyConfig();
|
BaseFormLayer::applyConfig();
|
||||||
scenerySetClouds(&_definition);
|
scenerySetClouds(_definition);
|
||||||
}
|
|
||||||
|
|
||||||
void FormClouds::configChangeEvent()
|
|
||||||
{
|
|
||||||
cloudsLayerValidateDefinition(_layer);
|
|
||||||
BaseFormLayer::configChangeEvent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FormClouds::layerReadCurrentFrom(void* layer_definition)
|
void FormClouds::layerReadCurrentFrom(void* layer_definition)
|
||||||
{
|
{
|
||||||
cloudsLayerCopyDefinition((CloudsLayerDefinition*)layer_definition, _layer);
|
cloudsGetLayerType().callback_copy((CloudsLayerDefinition*)layer_definition, _layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FormClouds::layerWriteCurrentTo(void* layer_definition)
|
void FormClouds::layerWriteCurrentTo(void* layer_definition)
|
||||||
{
|
{
|
||||||
cloudsLayerCopyDefinition(_layer, (CloudsLayerDefinition*)layer_definition);
|
cloudsGetLayerType().callback_copy(_layer, (CloudsLayerDefinition*)layer_definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FormClouds::autoPresetSelected(int preset)
|
void FormClouds::autoPresetSelected(int preset)
|
||||||
{
|
{
|
||||||
cloudsLayerAutoPreset(_layer, (CloudsPreset)preset);
|
cloudsAutoPreset(_layer, (CloudsPreset)preset);
|
||||||
BaseForm::autoPresetSelected(preset);
|
BaseForm::autoPresetSelected(preset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include "basepreview.h"
|
#include "basepreview.h"
|
||||||
#include "baseformlayer.h"
|
#include "baseformlayer.h"
|
||||||
#include "../lib_paysages/clouds.h"
|
#include "../lib_paysages/clouds/public.h"
|
||||||
|
|
||||||
class FormClouds : public BaseFormLayer
|
class FormClouds : public BaseFormLayer
|
||||||
{
|
{
|
||||||
|
@ -22,11 +22,8 @@ protected:
|
||||||
virtual void layerWriteCurrentTo(void* layer_definition);
|
virtual void layerWriteCurrentTo(void* layer_definition);
|
||||||
virtual void autoPresetSelected(int preset);
|
virtual void autoPresetSelected(int preset);
|
||||||
|
|
||||||
protected slots:
|
|
||||||
virtual void configChangeEvent();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CloudsDefinition _definition;
|
CloudsDefinition* _definition;
|
||||||
CloudsLayerDefinition* _layer;
|
CloudsLayerDefinition* _layer;
|
||||||
BasePreview* _previewCoverage;
|
BasePreview* _previewCoverage;
|
||||||
BasePreview* _previewColor;
|
BasePreview* _previewColor;
|
||||||
|
|
|
@ -65,26 +65,11 @@ class PreviewTexturesColor:public BasePreview
|
||||||
public:
|
public:
|
||||||
PreviewTexturesColor(QWidget* parent, TextureLayerDefinition* layer):BasePreview(parent)
|
PreviewTexturesColor(QWidget* parent, TextureLayerDefinition* layer):BasePreview(parent)
|
||||||
{
|
{
|
||||||
LightDefinition light;
|
|
||||||
|
|
||||||
_original_layer = layer;
|
_original_layer = layer;
|
||||||
_preview_layer = texturesLayerCreateDefinition();
|
_preview_layer = texturesLayerCreateDefinition();
|
||||||
|
|
||||||
/*_lighting = lightingCreateDefinition();
|
|
||||||
light.color = COLOR_WHITE;
|
|
||||||
light.direction.x = 0.0;
|
|
||||||
light.direction.y = -0.4794;
|
|
||||||
light.direction.z = 0.8776;
|
|
||||||
light.filtered = 0;
|
|
||||||
light.masked = 0;
|
|
||||||
light.reflection = 1.0;
|
|
||||||
lightingAddLight(&_lighting, light);
|
|
||||||
lightingValidateDefinition(&_lighting);*/
|
|
||||||
|
|
||||||
_renderer = rendererCreate();
|
_renderer = rendererCreate();
|
||||||
_renderer->render_quality = 3;
|
_renderer->render_quality = 3;
|
||||||
/*_renderer->getLightStatus = _getLightStatus;
|
|
||||||
_renderer->customData[0] = &_lighting;*/
|
|
||||||
_renderer->camera_location.x = 0.0;
|
_renderer->camera_location.x = 0.0;
|
||||||
_renderer->camera_location.y = 20.0;
|
_renderer->camera_location.y = 20.0;
|
||||||
_renderer->camera_location.z = 0.0;
|
_renderer->camera_location.z = 0.0;
|
||||||
|
@ -117,12 +102,6 @@ private:
|
||||||
Renderer* _renderer;
|
Renderer* _renderer;
|
||||||
TextureLayerDefinition* _original_layer;
|
TextureLayerDefinition* _original_layer;
|
||||||
TextureLayerDefinition* _preview_layer;
|
TextureLayerDefinition* _preview_layer;
|
||||||
//LightingDefinition _lighting;
|
|
||||||
|
|
||||||
/*static void _getLightStatus(Renderer* renderer, LightStatus* status, Vector3 location)
|
|
||||||
{
|
|
||||||
lightingGetStatus((LightingDefinition*)renderer->customData[0], renderer, location, status);
|
|
||||||
}*/
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**************** Form ****************/
|
/**************** Form ****************/
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
BUILDMODE = debug
|
BUILDMODE = debug
|
||||||
BUILDPATH = ../build/${BUILDMODE}
|
BUILDPATH = ../build/${BUILDMODE}
|
||||||
OBJPATH = ./obj/${BUILDMODE}
|
OBJPATH = ./obj/${BUILDMODE}
|
||||||
SOURCES = $(wildcard *.c atmosphere/*.c terrain/*.c tools/*.c)
|
SOURCES = $(wildcard *.c atmosphere/*.c clouds/*.c terrain/*.c tools/*.c)
|
||||||
OBJECTS = ${SOURCES:%.c=${OBJPATH}/%.o}
|
OBJECTS = ${SOURCES:%.c=${OBJPATH}/%.o}
|
||||||
HEADERS = $(wildcard *.h atmosphere/*.h terrain/*.h tools/*.h shared/*.h)
|
HEADERS = $(wildcard *.h atmosphere/*.h clouds/*.h terrain/*.h tools/*.h shared/*.h)
|
||||||
RESULT = ${BUILDPATH}/libpaysages.so
|
RESULT = ${BUILDPATH}/libpaysages.so
|
||||||
LIBS = glib-2.0 gthread-2.0 IL ILU
|
LIBS = glib-2.0 gthread-2.0 IL ILU
|
||||||
CC_FLAGS = -Wall -fPIC -DHAVE_GLIB=1
|
CC_FLAGS = -Wall -fPIC -DHAVE_GLIB=1
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
/*********************** Constants ***********************/
|
/*********************** Constants ***********************/
|
||||||
|
|
||||||
#define WORLD_SCALING 0.05
|
#define WORLD_SCALING 0.05
|
||||||
#define GROUND_OFFSET 10.0
|
#define GROUND_OFFSET 0.5
|
||||||
static const double Rg = 6360.0;
|
static const double Rg = 6360.0;
|
||||||
static const double Rt = 6420.0;
|
static const double Rt = 6420.0;
|
||||||
static const double RL = 6421.0;
|
static const double RL = 6421.0;
|
||||||
|
@ -27,7 +27,7 @@ static const double exposure = 0.4;
|
||||||
static const double ISun = 100.0;
|
static const double ISun = 100.0;
|
||||||
static const double AVERAGE_GROUND_REFLECTANCE = 0.1;
|
static const double AVERAGE_GROUND_REFLECTANCE = 0.1;
|
||||||
|
|
||||||
#if 0
|
#if 1
|
||||||
#define RES_MU 128
|
#define RES_MU 128
|
||||||
#define RES_MU_S 32
|
#define RES_MU_S 32
|
||||||
#define RES_R 32
|
#define RES_R 32
|
||||||
|
@ -825,6 +825,7 @@ static Color _getInscatterColor(Vector3* _x, double* _t, Vector3 v, Vector3 s, d
|
||||||
double r = v3Norm(*_x);
|
double r = v3Norm(*_x);
|
||||||
double mu = v3Dot(*_x, v) / r;
|
double mu = v3Dot(*_x, v) / r;
|
||||||
double d = -r * mu - sqrt(r * r * (mu * mu - 1.0) + Rt * Rt);
|
double d = -r * mu - sqrt(r * r * (mu * mu - 1.0) + Rt * Rt);
|
||||||
|
attenuation->x = attenuation->y = attenuation->z = 0.0;
|
||||||
if (d > 0.0)
|
if (d > 0.0)
|
||||||
{
|
{
|
||||||
/* if x in space and ray intersects atmosphere
|
/* if x in space and ray intersects atmosphere
|
||||||
|
@ -1218,7 +1219,7 @@ void brunetonGetLightingStatus(Renderer* renderer, LightStatus* status, Vector3
|
||||||
/*irradiance.color.r *= 100.0;
|
/*irradiance.color.r *= 100.0;
|
||||||
irradiance.color.g *= 100.0;
|
irradiance.color.g *= 100.0;
|
||||||
irradiance.color.b *= 100.0;*/
|
irradiance.color.b *= 100.0;*/
|
||||||
irradiance.direction = v3Scale(normal, -1.0);
|
irradiance.direction = VECTOR_DOWN;
|
||||||
irradiance.reflection = 0.0;
|
irradiance.reflection = 0.0;
|
||||||
irradiance.altered = 0;
|
irradiance.altered = 0;
|
||||||
|
|
||||||
|
|
|
@ -116,13 +116,6 @@ static Color _fakeGetSkyColor(Renderer* renderer, Vector3 direction)
|
||||||
UNUSED(direction);
|
UNUSED(direction);
|
||||||
return COLOR_WHITE;
|
return COLOR_WHITE;
|
||||||
}
|
}
|
||||||
static int _fakeGetSkydomeLights(Renderer* renderer, LightDefinition* lights, int max_lights)
|
|
||||||
{
|
|
||||||
UNUSED(renderer);
|
|
||||||
UNUSED(lights);
|
|
||||||
UNUSED(max_lights);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Color _getSkyColor(Renderer* renderer, Vector3 direction)
|
static Color _getSkyColor(Renderer* renderer, Vector3 direction)
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,7 +17,7 @@ static Color _postProcessFragment(Renderer* renderer, Vector3 location, void* da
|
||||||
|
|
||||||
/* TODO Don't compute result->color if it's fully covered by clouds */
|
/* TODO Don't compute result->color if it's fully covered by clouds */
|
||||||
result = renderer->atmosphere->getSkyColor(renderer, v3Normalize(direction));
|
result = renderer->atmosphere->getSkyColor(renderer, v3Normalize(direction));
|
||||||
result = renderer->applyClouds(renderer, result, renderer->camera_location, v3Add(renderer->camera_location, v3Scale(direction, 10.0)));
|
result = renderer->clouds->getColor(renderer, result, renderer->camera_location, v3Add(renderer->camera_location, v3Scale(direction, 10.0)));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include "clouds.h"
|
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "textures.h"
|
#include "textures.h"
|
||||||
#include "scenery.h"
|
#include "scenery.h"
|
||||||
|
@ -15,7 +14,6 @@
|
||||||
void autoGenRealisticLandscape(int seed)
|
void autoGenRealisticLandscape(int seed)
|
||||||
{
|
{
|
||||||
WaterDefinition water;
|
WaterDefinition water;
|
||||||
CloudsDefinition clouds;
|
|
||||||
TexturesDefinition textures;
|
TexturesDefinition textures;
|
||||||
TextureLayerDefinition* texture;
|
TextureLayerDefinition* texture;
|
||||||
int layer;
|
int layer;
|
||||||
|
@ -27,10 +25,10 @@ void autoGenRealisticLandscape(int seed)
|
||||||
srand(seed);
|
srand(seed);
|
||||||
|
|
||||||
/* Cloud layer */
|
/* Cloud layer */
|
||||||
clouds = cloudsCreateDefinition();
|
CloudsDefinition* clouds = CloudsDefinitionClass.create();
|
||||||
layersAddLayer(clouds.layers, NULL);
|
layer = layersAddLayer(clouds->layers, NULL);
|
||||||
scenerySetClouds(&clouds);
|
scenerySetClouds(clouds);
|
||||||
cloudsDeleteDefinition(&clouds);
|
CloudsDefinitionClass.destroy(clouds);
|
||||||
|
|
||||||
/* Water */
|
/* Water */
|
||||||
water = waterCreateDefinition();
|
water = waterCreateDefinition();
|
||||||
|
|
|
@ -49,6 +49,7 @@ CameraDefinition cameraCreateDefinition()
|
||||||
|
|
||||||
void cameraDeleteDefinition(CameraDefinition* definition)
|
void cameraDeleteDefinition(CameraDefinition* definition)
|
||||||
{
|
{
|
||||||
|
UNUSED(definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cameraCopyDefinition(CameraDefinition* source, CameraDefinition* destination)
|
void cameraCopyDefinition(CameraDefinition* source, CameraDefinition* destination)
|
||||||
|
|
|
@ -1,685 +0,0 @@
|
||||||
#include "clouds.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include "tools/color.h"
|
|
||||||
#include "tools/euclid.h"
|
|
||||||
#include "tools.h"
|
|
||||||
|
|
||||||
#define CLOUDS_MAX_LAYERS 6
|
|
||||||
#define MAX_SEGMENT_COUNT 30
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
Vector3 start;
|
|
||||||
Vector3 end;
|
|
||||||
double length;
|
|
||||||
} CloudSegment;
|
|
||||||
|
|
||||||
CloudsDefinition cloudsCreateDefinition()
|
|
||||||
{
|
|
||||||
CloudsDefinition result;
|
|
||||||
|
|
||||||
result.layers = layersCreate(cloudsGetLayerType(), CLOUDS_MAX_LAYERS);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cloudsDeleteDefinition(CloudsDefinition* definition)
|
|
||||||
{
|
|
||||||
layersDelete(definition->layers);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cloudsCopyDefinition(CloudsDefinition* source, CloudsDefinition* destination)
|
|
||||||
{
|
|
||||||
layersCopy(source->layers, destination->layers);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cloudsValidateDefinition(CloudsDefinition* definition)
|
|
||||||
{
|
|
||||||
layersValidate(definition->layers);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cloudsSave(PackStream* stream, CloudsDefinition* definition)
|
|
||||||
{
|
|
||||||
layersSave(stream, definition->layers);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cloudsLoad(PackStream* stream, CloudsDefinition* definition)
|
|
||||||
{
|
|
||||||
layersLoad(stream, definition->layers);
|
|
||||||
}
|
|
||||||
|
|
||||||
static double _standardCoverageFunc(CloudsLayerDefinition* layer, Vector3 position)
|
|
||||||
{
|
|
||||||
if (position.y < layer->lower_altitude || position.y >= layer->lower_altitude + layer->thickness)
|
|
||||||
{
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return layer->base_coverage * curveGetValue(layer->_coverage_by_altitude, (position.y - layer->lower_altitude) / layer->thickness);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CloudsLayerDefinition* cloudsLayerCreateDefinition()
|
|
||||||
{
|
|
||||||
CloudsLayerDefinition* result;
|
|
||||||
|
|
||||||
result = malloc(sizeof(CloudsLayerDefinition));
|
|
||||||
result->_coverage_by_altitude = curveCreate();
|
|
||||||
result->_shape_noise = noiseCreateGenerator();
|
|
||||||
result->_edge_noise = noiseCreateGenerator();
|
|
||||||
|
|
||||||
result->_custom_coverage = _standardCoverageFunc;
|
|
||||||
|
|
||||||
cloudsLayerAutoPreset(result, CLOUDS_PRESET_CIRRUS);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cloudsLayerDeleteDefinition(CloudsLayerDefinition* definition)
|
|
||||||
{
|
|
||||||
curveDelete(definition->_coverage_by_altitude);
|
|
||||||
noiseDeleteGenerator(definition->_shape_noise);
|
|
||||||
noiseDeleteGenerator(definition->_edge_noise);
|
|
||||||
free(definition);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cloudsLayerAutoPreset(CloudsLayerDefinition* definition, CloudsPreset preset)
|
|
||||||
{
|
|
||||||
definition->material.base.r = 0.7;
|
|
||||||
definition->material.base.g = 0.7;
|
|
||||||
definition->material.base.b = 0.7;
|
|
||||||
definition->material.base.a = 1.0;
|
|
||||||
|
|
||||||
switch (preset)
|
|
||||||
{
|
|
||||||
case CLOUDS_PRESET_CIRRUS:
|
|
||||||
definition->type = CLOUDS_TYPE_CIRRUS;
|
|
||||||
definition->lower_altitude = 25.0;
|
|
||||||
definition->thickness = 2.0;
|
|
||||||
definition->material.reflection = 0.4;
|
|
||||||
definition->material.shininess = 0.5;
|
|
||||||
definition->hardness = 0.0;
|
|
||||||
definition->transparencydepth = 3.0;
|
|
||||||
definition->lighttraversal = 10.0;
|
|
||||||
definition->minimumlight = 0.6;
|
|
||||||
definition->shape_scaling = 8.0;
|
|
||||||
definition->edge_scaling = 2.0;
|
|
||||||
definition->edge_length = 0.8;
|
|
||||||
definition->base_coverage = 0.6;
|
|
||||||
break;
|
|
||||||
case CLOUDS_PRESET_CUMULUS:
|
|
||||||
definition->type = CLOUDS_TYPE_CUMULUS;
|
|
||||||
definition->lower_altitude = 15.0;
|
|
||||||
definition->thickness = 15.0;
|
|
||||||
definition->material.reflection = 0.5;
|
|
||||||
definition->material.shininess = 1.2;
|
|
||||||
definition->hardness = 0.25;
|
|
||||||
definition->transparencydepth = 1.5;
|
|
||||||
definition->lighttraversal = 8.0;
|
|
||||||
definition->minimumlight = 0.4;
|
|
||||||
definition->shape_scaling = 20.0;
|
|
||||||
definition->edge_scaling = 2.0;
|
|
||||||
definition->edge_length = 0.0;
|
|
||||||
definition->base_coverage = 0.7;
|
|
||||||
break;
|
|
||||||
case CLOUDS_PRESET_STRATOCUMULUS:
|
|
||||||
definition->type = CLOUDS_TYPE_STRATOCUMULUS;
|
|
||||||
definition->lower_altitude = 5.0;
|
|
||||||
definition->thickness = 6.0;
|
|
||||||
definition->material.reflection = 0.3;
|
|
||||||
definition->material.shininess = 0.8;
|
|
||||||
definition->hardness = 0.25;
|
|
||||||
definition->transparencydepth = 1.5;
|
|
||||||
definition->lighttraversal = 7.0;
|
|
||||||
definition->minimumlight = 0.4;
|
|
||||||
definition->shape_scaling = 10.0;
|
|
||||||
definition->edge_scaling = 0.8;
|
|
||||||
definition->edge_length = 0.3;
|
|
||||||
definition->base_coverage = 0.4;
|
|
||||||
break;
|
|
||||||
case CLOUDS_PRESET_STRATUS:
|
|
||||||
definition->type = CLOUDS_TYPE_STRATUS;
|
|
||||||
definition->lower_altitude = 3.0;
|
|
||||||
definition->thickness = 4.0;
|
|
||||||
definition->material.reflection = 0.1;
|
|
||||||
definition->material.shininess = 0.8;
|
|
||||||
definition->hardness = 0.1;
|
|
||||||
definition->transparencydepth = 3.0;
|
|
||||||
definition->lighttraversal = 10.0;
|
|
||||||
definition->minimumlight = 0.6;
|
|
||||||
definition->shape_scaling = 8.0;
|
|
||||||
definition->edge_scaling = 2.0;
|
|
||||||
definition->edge_length = 1.0;
|
|
||||||
definition->base_coverage = 0.4;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
cloudsLayerValidateDefinition(definition);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cloudsLayerCopyDefinition(CloudsLayerDefinition* source, CloudsLayerDefinition* destination)
|
|
||||||
{
|
|
||||||
CloudsLayerDefinition temp;
|
|
||||||
|
|
||||||
temp = *destination;
|
|
||||||
*destination = *source;
|
|
||||||
|
|
||||||
destination->_shape_noise = temp._shape_noise;
|
|
||||||
noiseCopy(source->_shape_noise, destination->_shape_noise);
|
|
||||||
|
|
||||||
destination->_edge_noise = temp._edge_noise;
|
|
||||||
noiseCopy(source->_edge_noise, destination->_edge_noise);
|
|
||||||
|
|
||||||
destination->_coverage_by_altitude = temp._coverage_by_altitude;
|
|
||||||
curveCopy(source->_coverage_by_altitude, destination->_coverage_by_altitude);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cloudsLayerValidateDefinition(CloudsLayerDefinition* definition)
|
|
||||||
{
|
|
||||||
if (definition->shape_scaling < 0.0001)
|
|
||||||
{
|
|
||||||
definition->shape_scaling = 0.00001;
|
|
||||||
}
|
|
||||||
if (definition->edge_scaling < 0.0001)
|
|
||||||
{
|
|
||||||
definition->edge_scaling = 0.00001;
|
|
||||||
}
|
|
||||||
if (definition->_custom_coverage == NULL)
|
|
||||||
{
|
|
||||||
definition->_custom_coverage = _standardCoverageFunc;
|
|
||||||
}
|
|
||||||
|
|
||||||
curveClear(definition->_coverage_by_altitude);
|
|
||||||
noiseClearLevels(definition->_shape_noise);
|
|
||||||
noiseClearLevels(definition->_edge_noise);
|
|
||||||
|
|
||||||
switch (definition->type)
|
|
||||||
{
|
|
||||||
case CLOUDS_TYPE_CIRRUS:
|
|
||||||
curveQuickAddPoint(definition->_coverage_by_altitude, 0.0, 0.0);
|
|
||||||
curveQuickAddPoint(definition->_coverage_by_altitude, 0.5, 1.0);
|
|
||||||
curveQuickAddPoint(definition->_coverage_by_altitude, 1.0, 0.0);
|
|
||||||
noiseAddLevelsSimple(definition->_shape_noise, 3, 1.0, 1.0);
|
|
||||||
noiseSetFunctionParams(definition->_shape_noise, NOISE_FUNCTION_SIMPLEX, 0.0);
|
|
||||||
noiseAddLevelsSimple(definition->_edge_noise, 4, 1.0, 1.0);
|
|
||||||
noiseSetFunctionParams(definition->_edge_noise, NOISE_FUNCTION_SIMPLEX, -0.2);
|
|
||||||
break;
|
|
||||||
case CLOUDS_TYPE_CUMULUS:
|
|
||||||
curveQuickAddPoint(definition->_coverage_by_altitude, 0.0, 0.0);
|
|
||||||
curveQuickAddPoint(definition->_coverage_by_altitude, 0.1, 1.0);
|
|
||||||
curveQuickAddPoint(definition->_coverage_by_altitude, 0.4, 0.8);
|
|
||||||
curveQuickAddPoint(definition->_coverage_by_altitude, 0.7, 1.0);
|
|
||||||
curveQuickAddPoint(definition->_coverage_by_altitude, 1.0, 0.0);
|
|
||||||
noiseAddLevelsSimple(definition->_shape_noise, 7, 1.0, 1.0);
|
|
||||||
noiseSetFunctionParams(definition->_shape_noise, NOISE_FUNCTION_SIMPLEX, 0.4);
|
|
||||||
break;
|
|
||||||
case CLOUDS_TYPE_STRATOCUMULUS:
|
|
||||||
curveQuickAddPoint(definition->_coverage_by_altitude, 0.0, 0.0);
|
|
||||||
curveQuickAddPoint(definition->_coverage_by_altitude, 0.2, 1.0);
|
|
||||||
curveQuickAddPoint(definition->_coverage_by_altitude, 0.5, 1.0);
|
|
||||||
curveQuickAddPoint(definition->_coverage_by_altitude, 1.0, 0.0);
|
|
||||||
noiseAddLevelsSimple(definition->_shape_noise, 2, 1.0, 1.0);
|
|
||||||
noiseSetFunctionParams(definition->_shape_noise, NOISE_FUNCTION_SIMPLEX, 0.3);
|
|
||||||
noiseAddLevelsSimple(definition->_edge_noise, 8, 1.0, 1.0);
|
|
||||||
noiseSetFunctionParams(definition->_edge_noise, NOISE_FUNCTION_SIMPLEX, 0.5);
|
|
||||||
break;
|
|
||||||
case CLOUDS_TYPE_STRATUS:
|
|
||||||
curveQuickAddPoint(definition->_coverage_by_altitude, 0.0, 0.0);
|
|
||||||
curveQuickAddPoint(definition->_coverage_by_altitude, 0.2, 1.0);
|
|
||||||
curveQuickAddPoint(definition->_coverage_by_altitude, 0.8, 1.0);
|
|
||||||
curveQuickAddPoint(definition->_coverage_by_altitude, 1.0, 0.0);
|
|
||||||
noiseAddLevelsSimple(definition->_shape_noise, 3, 1.0, 1.0);
|
|
||||||
noiseSetFunctionParams(definition->_shape_noise, NOISE_FUNCTION_SIMPLEX, -0.3);
|
|
||||||
noiseAddLevelsSimple(definition->_edge_noise, 4, 1.0, 1.0);
|
|
||||||
noiseSetFunctionParams(definition->_edge_noise, NOISE_FUNCTION_SIMPLEX, -0.5);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _cloudsLayerSave(PackStream* stream, CloudsLayerDefinition* layer)
|
|
||||||
{
|
|
||||||
int clouds_type = (int)layer->type;
|
|
||||||
|
|
||||||
packWriteInt(stream, &clouds_type);
|
|
||||||
packWriteDouble(stream, &layer->lower_altitude);
|
|
||||||
packWriteDouble(stream, &layer->thickness);
|
|
||||||
curveSave(stream, layer->_coverage_by_altitude);
|
|
||||||
noiseSaveGenerator(stream, layer->_shape_noise);
|
|
||||||
noiseSaveGenerator(stream, layer->_edge_noise);
|
|
||||||
materialSave(stream, &layer->material);
|
|
||||||
packWriteDouble(stream, &layer->hardness);
|
|
||||||
packWriteDouble(stream, &layer->transparencydepth);
|
|
||||||
packWriteDouble(stream, &layer->lighttraversal);
|
|
||||||
packWriteDouble(stream, &layer->minimumlight);
|
|
||||||
packWriteDouble(stream, &layer->shape_scaling);
|
|
||||||
packWriteDouble(stream, &layer->edge_scaling);
|
|
||||||
packWriteDouble(stream, &layer->edge_length);
|
|
||||||
packWriteDouble(stream, &layer->base_coverage);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _cloudsLayerLoad(PackStream* stream, CloudsLayerDefinition* layer)
|
|
||||||
{
|
|
||||||
int clouds_type;
|
|
||||||
|
|
||||||
packReadInt(stream, &clouds_type);
|
|
||||||
layer->type = (CloudsType)clouds_type;
|
|
||||||
packReadDouble(stream, &layer->lower_altitude);
|
|
||||||
packReadDouble(stream, &layer->thickness);
|
|
||||||
materialLoad(stream, &layer->material);
|
|
||||||
packReadDouble(stream, &layer->hardness);
|
|
||||||
packReadDouble(stream, &layer->transparencydepth);
|
|
||||||
packReadDouble(stream, &layer->lighttraversal);
|
|
||||||
packReadDouble(stream, &layer->minimumlight);
|
|
||||||
packReadDouble(stream, &layer->shape_scaling);
|
|
||||||
packReadDouble(stream, &layer->edge_scaling);
|
|
||||||
packReadDouble(stream, &layer->edge_length);
|
|
||||||
packReadDouble(stream, &layer->base_coverage);
|
|
||||||
|
|
||||||
cloudsLayerValidateDefinition(layer);
|
|
||||||
}
|
|
||||||
|
|
||||||
LayerType cloudsGetLayerType()
|
|
||||||
{
|
|
||||||
LayerType result;
|
|
||||||
|
|
||||||
result.callback_create = (LayerCallbackCreate)cloudsLayerCreateDefinition;
|
|
||||||
result.callback_delete = (LayerCallbackDelete)cloudsLayerDeleteDefinition;
|
|
||||||
result.callback_copy = (LayerCallbackCopy)cloudsLayerCopyDefinition;
|
|
||||||
result.callback_validate = (LayerCallbackValidate)cloudsLayerValidateDefinition;
|
|
||||||
result.callback_save = (LayerCallbackSave)_cloudsLayerSave;
|
|
||||||
result.callback_load = (LayerCallbackLoad)_cloudsLayerLoad;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline double _getDistanceToBorder(CloudsLayerDefinition* layer, Vector3 position)
|
|
||||||
{
|
|
||||||
double density, coverage, val;
|
|
||||||
|
|
||||||
val = noiseGet3DTotal(layer->_shape_noise, position.x / layer->shape_scaling, position.y / layer->shape_scaling, position.z / layer->shape_scaling) / noiseGetMaxValue(layer->_shape_noise);
|
|
||||||
coverage = layer->_custom_coverage(layer, position);
|
|
||||||
density = 0.5 * val - 0.5 + coverage;
|
|
||||||
|
|
||||||
if (density <= 0.0)
|
|
||||||
{
|
|
||||||
/* outside the main shape */
|
|
||||||
return density * layer->shape_scaling;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* inside the main shape, using edge noise */
|
|
||||||
density /= coverage;
|
|
||||||
if (density < layer->edge_length)
|
|
||||||
{
|
|
||||||
density /= layer->edge_length;
|
|
||||||
|
|
||||||
val = 0.5 * noiseGet3DTotal(layer->_edge_noise, position.x / layer->edge_scaling, position.y / layer->edge_scaling, position.z / layer->edge_scaling) / noiseGetMaxValue(layer->_edge_noise);
|
|
||||||
val = val - 0.5 + density;
|
|
||||||
|
|
||||||
return val * (density * coverage * layer->shape_scaling + (1.0 - density) * layer->edge_scaling);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return density * coverage * layer->shape_scaling;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline Vector3 _getNormal(CloudsLayerDefinition* layer, Vector3 position, double detail)
|
|
||||||
{
|
|
||||||
Vector3 result = {0.0, 0.0, 0.0};
|
|
||||||
Vector3 dposition;
|
|
||||||
double val, dval;
|
|
||||||
|
|
||||||
val = _getDistanceToBorder(layer, position);
|
|
||||||
|
|
||||||
dposition.x = position.x + detail;
|
|
||||||
dposition.y = position.y;
|
|
||||||
dposition.z = position.z;
|
|
||||||
dval = val - _getDistanceToBorder(layer, dposition);
|
|
||||||
result.x += dval;
|
|
||||||
|
|
||||||
dposition.x = position.x - detail;
|
|
||||||
dval = val - _getDistanceToBorder(layer, dposition);
|
|
||||||
result.x -= dval;
|
|
||||||
|
|
||||||
dposition.x = position.x;
|
|
||||||
dposition.y = position.y + detail;
|
|
||||||
dval = val - _getDistanceToBorder(layer, dposition);
|
|
||||||
result.y += dval;
|
|
||||||
|
|
||||||
dposition.y = position.y - detail;
|
|
||||||
dval = val - _getDistanceToBorder(layer, dposition);
|
|
||||||
result.y -= dval;
|
|
||||||
|
|
||||||
dposition.y = position.y;
|
|
||||||
dposition.z = position.z + detail;
|
|
||||||
dval = val - _getDistanceToBorder(layer, dposition);
|
|
||||||
result.z += dval;
|
|
||||||
|
|
||||||
dposition.z = position.z - detail;
|
|
||||||
dval = val - _getDistanceToBorder(layer, dposition);
|
|
||||||
result.z -= dval;
|
|
||||||
|
|
||||||
return v3Normalize(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Optimize the search limits in a layer.
|
|
||||||
*
|
|
||||||
* @param layer The cloud layer
|
|
||||||
* @param start Start of the search to optimize
|
|
||||||
* @param end End of the search to optimize
|
|
||||||
* @return 0 if the search is useless
|
|
||||||
*/
|
|
||||||
static int _optimizeSearchLimits(CloudsLayerDefinition* layer, Vector3* start, Vector3* end)
|
|
||||||
{
|
|
||||||
Vector3 diff;
|
|
||||||
|
|
||||||
if (start->y > layer->lower_altitude + layer->thickness)
|
|
||||||
{
|
|
||||||
if (end->y >= layer->lower_altitude + layer->thickness)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
diff = v3Sub(*end, *start);
|
|
||||||
*start = v3Add(*start, v3Scale(diff, (layer->lower_altitude + layer->thickness - start->y) / diff.y));
|
|
||||||
if (end->y < layer->lower_altitude)
|
|
||||||
{
|
|
||||||
*end = v3Add(*end, v3Scale(diff, (layer->lower_altitude - end->y) / diff.y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (start->y < layer->lower_altitude)
|
|
||||||
{
|
|
||||||
if (end->y <= layer->lower_altitude)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
diff = v3Sub(*end, *start);
|
|
||||||
*start = v3Add(*start, v3Scale(diff, (layer->lower_altitude - start->y) / diff.y));
|
|
||||||
if (end->y >= layer->lower_altitude + layer->thickness)
|
|
||||||
{
|
|
||||||
*end = v3Add(*end, v3Scale(diff, (layer->lower_altitude + layer->thickness - end->y) / diff.y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else /* start is inside layer */
|
|
||||||
{
|
|
||||||
diff = v3Sub(*end, *start);
|
|
||||||
if (end->y > layer->lower_altitude + layer->thickness)
|
|
||||||
{
|
|
||||||
*end = v3Add(*start, v3Scale(diff, (layer->lower_altitude + layer->thickness - start->y) / diff.y));
|
|
||||||
}
|
|
||||||
else if (end->y < layer->lower_altitude)
|
|
||||||
{
|
|
||||||
*end = v3Add(*start, v3Scale(diff, (layer->lower_altitude - start->y) / diff.y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO Limit the search length */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Go through the cloud layer to find segments (parts of the lookup that are inside the cloud).
|
|
||||||
*
|
|
||||||
* @param definition The cloud layer
|
|
||||||
* @param renderer The renderer environment
|
|
||||||
* @param start Start position of the lookup (already optimized)
|
|
||||||
* @param direction Normalized direction of the lookup
|
|
||||||
* @param detail Level of noise detail required
|
|
||||||
* @param max_segments Maximum number of segments to collect
|
|
||||||
* @param max_inside_length Maximum length to spend inside the cloud
|
|
||||||
* @param max_total_length Maximum lookup length
|
|
||||||
* @param inside_length Resulting length inside cloud (sum of all segments length)
|
|
||||||
* @param total_length Resulting lookup length
|
|
||||||
* @param out_segments Allocated space to fill found segments
|
|
||||||
* @return Number of segments found
|
|
||||||
*/
|
|
||||||
static int _findSegments(CloudsLayerDefinition* definition, Renderer* renderer, Vector3 start, Vector3 direction, double detail, int max_segments, double max_inside_length, double max_total_length, double* inside_length, double* total_length, CloudSegment* out_segments)
|
|
||||||
{
|
|
||||||
int inside, segment_count;
|
|
||||||
double current_total_length, current_inside_length;
|
|
||||||
double step_length, segment_length, remaining_length;
|
|
||||||
double noise_distance, last_noise_distance;
|
|
||||||
Vector3 walker, step, segment_start;
|
|
||||||
double render_precision;
|
|
||||||
|
|
||||||
if (max_segments <= 0)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
render_precision = 1.005 - 0.01 * (double)(renderer->render_quality * renderer->render_quality);
|
|
||||||
if (render_precision > max_total_length / 10.0)
|
|
||||||
{
|
|
||||||
render_precision = max_total_length / 10.0;
|
|
||||||
}
|
|
||||||
else if (render_precision < max_total_length / 10000.0)
|
|
||||||
{
|
|
||||||
render_precision = max_total_length / 10000.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
segment_count = 0;
|
|
||||||
current_total_length = 0.0;
|
|
||||||
current_inside_length = 0.0;
|
|
||||||
segment_length = 0.0;
|
|
||||||
walker = start;
|
|
||||||
noise_distance = _getDistanceToBorder(definition, start) * render_precision;
|
|
||||||
inside = (noise_distance > 0.0) ? 1 : 0;
|
|
||||||
step = v3Scale(direction, render_precision);
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
walker = v3Add(walker, step);
|
|
||||||
step_length = v3Norm(step);
|
|
||||||
last_noise_distance = noise_distance;
|
|
||||||
noise_distance = _getDistanceToBorder(definition, walker) * render_precision;
|
|
||||||
current_total_length += step_length;
|
|
||||||
|
|
||||||
if (current_total_length >= max_total_length || current_inside_length > max_inside_length)
|
|
||||||
{
|
|
||||||
noise_distance = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (noise_distance > 0.0)
|
|
||||||
{
|
|
||||||
if (inside)
|
|
||||||
{
|
|
||||||
// inside the cloud
|
|
||||||
segment_length += step_length;
|
|
||||||
current_inside_length += step_length;
|
|
||||||
step = v3Scale(direction, (noise_distance < render_precision) ? render_precision : noise_distance);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// entering the cloud
|
|
||||||
inside = 1;
|
|
||||||
segment_length = step_length * noise_distance / (noise_distance - last_noise_distance);
|
|
||||||
segment_start = v3Add(walker, v3Scale(direction, -segment_length));
|
|
||||||
current_inside_length += segment_length;
|
|
||||||
step = v3Scale(direction, render_precision);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (inside)
|
|
||||||
{
|
|
||||||
// exiting the cloud
|
|
||||||
remaining_length = step_length * last_noise_distance / (last_noise_distance - noise_distance);
|
|
||||||
segment_length += remaining_length;
|
|
||||||
current_inside_length += remaining_length;
|
|
||||||
|
|
||||||
out_segments->start = segment_start;
|
|
||||||
out_segments->end = v3Add(walker, v3Scale(direction, remaining_length - step_length));
|
|
||||||
out_segments->length = segment_length;
|
|
||||||
out_segments++;
|
|
||||||
if (++segment_count >= max_segments)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
inside = 0;
|
|
||||||
step = v3Scale(direction, render_precision);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// searching for a cloud
|
|
||||||
step = v3Scale(direction, (noise_distance > -render_precision) ? render_precision : -noise_distance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (inside || (walker.y <= definition->lower_altitude + definition->thickness + 0.001 && walker.y >= definition->lower_altitude - 0.001 && current_total_length < max_total_length && current_inside_length < max_inside_length));
|
|
||||||
|
|
||||||
*total_length = current_total_length;
|
|
||||||
*inside_length = current_inside_length;
|
|
||||||
return segment_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Color _applyLayerLighting(CloudsLayerDefinition* definition, Renderer* renderer, Vector3 position, double detail)
|
|
||||||
{
|
|
||||||
Vector3 normal;
|
|
||||||
Color col1, col2;
|
|
||||||
LightStatus* lighting;
|
|
||||||
|
|
||||||
normal = _getNormal(definition, position, 3.0);
|
|
||||||
if (renderer->render_quality > 5)
|
|
||||||
{
|
|
||||||
normal = v3Add(normal, _getNormal(definition, position, 2.0));
|
|
||||||
normal = v3Add(normal, _getNormal(definition, position, 1.0));
|
|
||||||
}
|
|
||||||
if (renderer->render_quality > 5)
|
|
||||||
{
|
|
||||||
normal = v3Add(normal, _getNormal(definition, position, 0.5));
|
|
||||||
}
|
|
||||||
normal = v3Scale(v3Normalize(normal), definition->hardness);
|
|
||||||
|
|
||||||
lighting = lightingCreateStatus(renderer->lighting, position, renderer->camera_location);
|
|
||||||
renderer->atmosphere->getLightingStatus(renderer, lighting, normal, 0);
|
|
||||||
col1 = lightingApplyStatus(lighting, normal, &definition->material);
|
|
||||||
col2 = lightingApplyStatus(lighting, v3Scale(normal, -1.0), &definition->material);
|
|
||||||
lightingDeleteStatus(lighting);
|
|
||||||
|
|
||||||
col1.r = (col1.r + col2.r) / 2.0;
|
|
||||||
col1.g = (col1.g + col2.g) / 2.0;
|
|
||||||
col1.b = (col1.b + col2.b) / 2.0;
|
|
||||||
col1.a = (col1.a + col2.a) / 2.0;
|
|
||||||
|
|
||||||
return col1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Color cloudsApplyLayer(CloudsLayerDefinition* definition, Color base, Renderer* renderer, Vector3 start, Vector3 end)
|
|
||||||
{
|
|
||||||
int i, segment_count;
|
|
||||||
double max_length, detail, total_length, inside_length;
|
|
||||||
Vector3 direction;
|
|
||||||
Color col;
|
|
||||||
CloudSegment segments[MAX_SEGMENT_COUNT];
|
|
||||||
|
|
||||||
if (!_optimizeSearchLimits(definition, &start, &end))
|
|
||||||
{
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
|
|
||||||
direction = v3Sub(end, start);
|
|
||||||
max_length = v3Norm(direction);
|
|
||||||
direction = v3Normalize(direction);
|
|
||||||
|
|
||||||
detail = renderer->getPrecision(renderer, start) / definition->shape_scaling;
|
|
||||||
|
|
||||||
segment_count = _findSegments(definition, renderer, start, direction, detail, MAX_SEGMENT_COUNT, definition->transparencydepth * (double)renderer->render_quality, max_length, &inside_length, &total_length, segments);
|
|
||||||
for (i = segment_count - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
col = _applyLayerLighting(definition, renderer, segments[i].start, detail);
|
|
||||||
col.a = 1.0;
|
|
||||||
col = renderer->atmosphere->applyAerialPerspective(renderer, start, col);
|
|
||||||
col.a = (segments[i].length >= definition->transparencydepth) ? 1.0 : (segments[i].length / definition->transparencydepth);
|
|
||||||
colorMask(&base, &col);
|
|
||||||
}
|
|
||||||
if (inside_length >= definition->transparencydepth)
|
|
||||||
{
|
|
||||||
col.a = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*static int _cmpLayer(const void* layer1, const void* layer2)
|
|
||||||
{
|
|
||||||
return (((CloudsLayerDefinition*)layer1)->lower_altitude > ((CloudsLayerDefinition*)layer2)->lower_altitude) ? -1 : 1;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
Color cloudsApply(CloudsDefinition* definition, Color base, Renderer* renderer, Vector3 start, Vector3 end)
|
|
||||||
{
|
|
||||||
int i, n;
|
|
||||||
|
|
||||||
n = layersCount(definition->layers);
|
|
||||||
if (n < 1)
|
|
||||||
{
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO Iter layers in sorted order */
|
|
||||||
for (i = 0; i < n; i++)
|
|
||||||
{
|
|
||||||
base = cloudsApplyLayer(layersGetLayer(definition->layers, i), base, renderer, start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
|
|
||||||
Color cloudsLayerFilterLight(CloudsLayerDefinition* definition, Renderer* renderer, Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light)
|
|
||||||
{
|
|
||||||
double inside_depth, total_depth, factor;
|
|
||||||
CloudSegment segments[MAX_SEGMENT_COUNT];
|
|
||||||
|
|
||||||
_optimizeSearchLimits(definition, &location, &light_location);
|
|
||||||
|
|
||||||
_findSegments(definition, renderer, location, direction_to_light, 0.1, MAX_SEGMENT_COUNT, definition->lighttraversal, v3Norm(v3Sub(light_location, location)), &inside_depth, &total_depth, segments);
|
|
||||||
|
|
||||||
if (definition->lighttraversal < 0.0001)
|
|
||||||
{
|
|
||||||
factor = 0.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
factor = inside_depth / definition->lighttraversal;
|
|
||||||
if (factor > 1.0)
|
|
||||||
{
|
|
||||||
factor = 1.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
factor = 1.0 - (1.0 - definition->minimumlight) * factor;
|
|
||||||
|
|
||||||
light.r = light.r * factor;
|
|
||||||
light.g = light.g * factor;
|
|
||||||
light.b = light.b * factor;
|
|
||||||
|
|
||||||
return light;
|
|
||||||
}
|
|
||||||
|
|
||||||
Color cloudsFilterLight(CloudsDefinition* definition, Renderer* renderer, Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light)
|
|
||||||
{
|
|
||||||
int i, n;
|
|
||||||
|
|
||||||
/* TODO Iter layers in sorted order */
|
|
||||||
n = layersCount(definition->layers);
|
|
||||||
for (i = 0; i < n; i++)
|
|
||||||
{
|
|
||||||
light = cloudsLayerFilterLight(layersGetLayer(definition->layers, i), renderer, light, location, light_location, direction_to_light);
|
|
||||||
}
|
|
||||||
return light;
|
|
||||||
}
|
|
|
@ -1,83 +0,0 @@
|
||||||
#ifndef _PAYSAGES_CLOUDS_H_
|
|
||||||
#define _PAYSAGES_CLOUDS_H_
|
|
||||||
|
|
||||||
#include "shared/types.h"
|
|
||||||
#include "layers.h"
|
|
||||||
#include "noise.h"
|
|
||||||
#include "renderer.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
CLOUDS_TYPE_CIRRUS,
|
|
||||||
CLOUDS_TYPE_CUMULUS,
|
|
||||||
CLOUDS_TYPE_STRATOCUMULUS,
|
|
||||||
CLOUDS_TYPE_STRATUS
|
|
||||||
} CloudsType;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
CLOUDS_PRESET_CIRRUS,
|
|
||||||
CLOUDS_PRESET_CUMULUS,
|
|
||||||
CLOUDS_PRESET_STRATOCUMULUS,
|
|
||||||
CLOUDS_PRESET_STRATUS
|
|
||||||
} CloudsPreset;
|
|
||||||
|
|
||||||
typedef struct CloudsLayerDefinition CloudsLayerDefinition;
|
|
||||||
|
|
||||||
typedef double (*CloudCoverageFunc)(CloudsLayerDefinition* definition, Vector3 position);
|
|
||||||
|
|
||||||
struct CloudsLayerDefinition
|
|
||||||
{
|
|
||||||
CloudsType type;
|
|
||||||
double lower_altitude;
|
|
||||||
double thickness;
|
|
||||||
double base_coverage;
|
|
||||||
double shape_scaling;
|
|
||||||
double edge_scaling;
|
|
||||||
double edge_length;
|
|
||||||
SurfaceMaterial material;
|
|
||||||
double hardness;
|
|
||||||
double transparencydepth;
|
|
||||||
double lighttraversal;
|
|
||||||
double minimumlight;
|
|
||||||
|
|
||||||
CloudCoverageFunc _custom_coverage;
|
|
||||||
Curve* _coverage_by_altitude;
|
|
||||||
NoiseGenerator* _shape_noise;
|
|
||||||
NoiseGenerator* _edge_noise;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
Layers* layers;
|
|
||||||
} CloudsDefinition;
|
|
||||||
|
|
||||||
CloudsDefinition cloudsCreateDefinition();
|
|
||||||
void cloudsDeleteDefinition(CloudsDefinition* definition);
|
|
||||||
void cloudsCopyDefinition(CloudsDefinition* source, CloudsDefinition* destination);
|
|
||||||
void cloudsValidateDefinition(CloudsDefinition* definition);
|
|
||||||
void cloudsSave(PackStream* stream, CloudsDefinition* definition);
|
|
||||||
void cloudsLoad(PackStream* stream, CloudsDefinition* definition);
|
|
||||||
|
|
||||||
CloudsLayerDefinition* cloudsLayerCreateDefinition();
|
|
||||||
void cloudsLayerDeleteDefinition(CloudsLayerDefinition* definition);
|
|
||||||
void cloudsLayerAutoPreset(CloudsLayerDefinition* definition, CloudsPreset preset);
|
|
||||||
void cloudsLayerCopyDefinition(CloudsLayerDefinition* source, CloudsLayerDefinition* destination);
|
|
||||||
void cloudsLayerValidateDefinition(CloudsLayerDefinition* definition);
|
|
||||||
void cloudsLayerSetName(CloudsLayerDefinition* definition, const char* name);
|
|
||||||
LayerType cloudsGetLayerType();
|
|
||||||
|
|
||||||
Color cloudsApplyLayer(CloudsLayerDefinition* definition, Color base, Renderer* renderer, Vector3 start, Vector3 end);
|
|
||||||
Color cloudsApply(CloudsDefinition* definition, Color base, Renderer* renderer, Vector3 start, Vector3 end);
|
|
||||||
Color cloudsLayerFilterLight(CloudsLayerDefinition* definition, Renderer* renderer, Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light);
|
|
||||||
Color cloudsFilterLight(CloudsDefinition* definition, Renderer* renderer, Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
205
lib_paysages/clouds/definition.c
Normal file
205
lib_paysages/clouds/definition.c
Normal file
|
@ -0,0 +1,205 @@
|
||||||
|
#include "private.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/******************** Global definition ********************/
|
||||||
|
static void _validateDefinition(CloudsDefinition* definition)
|
||||||
|
{
|
||||||
|
layersValidate(definition->layers);
|
||||||
|
}
|
||||||
|
|
||||||
|
static CloudsDefinition* _createDefinition()
|
||||||
|
{
|
||||||
|
CloudsDefinition* definition = malloc(sizeof(CloudsDefinition));
|
||||||
|
|
||||||
|
definition->layers = layersCreate(cloudsGetLayerType(), CLOUDS_MAX_LAYERS);
|
||||||
|
|
||||||
|
return definition;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _deleteDefinition(CloudsDefinition* definition)
|
||||||
|
{
|
||||||
|
layersDelete(definition->layers);
|
||||||
|
free(definition);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _copyDefinition(CloudsDefinition* source, CloudsDefinition* destination)
|
||||||
|
{
|
||||||
|
layersCopy(source->layers, destination->layers);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _saveDefinition(PackStream* stream, CloudsDefinition* definition)
|
||||||
|
{
|
||||||
|
layersSave(stream, definition->layers);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _loadDefinition(PackStream* stream, CloudsDefinition* definition)
|
||||||
|
{
|
||||||
|
layersLoad(stream, definition->layers);
|
||||||
|
}
|
||||||
|
|
||||||
|
StandardDefinition CloudsDefinitionClass = {
|
||||||
|
(FuncObjectCreate)_createDefinition,
|
||||||
|
(FuncObjectDelete)_deleteDefinition,
|
||||||
|
(FuncObjectCopy)_copyDefinition,
|
||||||
|
(FuncObjectValidate)_validateDefinition,
|
||||||
|
(FuncObjectSave)_saveDefinition,
|
||||||
|
(FuncObjectLoad)_loadDefinition
|
||||||
|
};
|
||||||
|
|
||||||
|
/*** Layer definition ***/
|
||||||
|
|
||||||
|
void cloudsLayerValidateDefinition(CloudsLayerDefinition* definition)
|
||||||
|
{
|
||||||
|
if (definition->shape_scaling < 0.0001)
|
||||||
|
{
|
||||||
|
definition->shape_scaling = 0.00001;
|
||||||
|
}
|
||||||
|
if (definition->edge_scaling < 0.0001)
|
||||||
|
{
|
||||||
|
definition->edge_scaling = 0.00001;
|
||||||
|
}
|
||||||
|
|
||||||
|
curveClear(definition->_coverage_by_altitude);
|
||||||
|
noiseClearLevels(definition->_shape_noise);
|
||||||
|
noiseClearLevels(definition->_edge_noise);
|
||||||
|
|
||||||
|
switch (definition->type)
|
||||||
|
{
|
||||||
|
case CLOUDS_TYPE_CIRRUS:
|
||||||
|
curveQuickAddPoint(definition->_coverage_by_altitude, 0.0, 0.0);
|
||||||
|
curveQuickAddPoint(definition->_coverage_by_altitude, 0.5, 1.0);
|
||||||
|
curveQuickAddPoint(definition->_coverage_by_altitude, 1.0, 0.0);
|
||||||
|
noiseAddLevelsSimple(definition->_shape_noise, 3, 1.0, 1.0);
|
||||||
|
noiseSetFunctionParams(definition->_shape_noise, NOISE_FUNCTION_SIMPLEX, 0.0);
|
||||||
|
noiseAddLevelsSimple(definition->_edge_noise, 4, 1.0, 1.0);
|
||||||
|
noiseSetFunctionParams(definition->_edge_noise, NOISE_FUNCTION_SIMPLEX, -0.2);
|
||||||
|
break;
|
||||||
|
case CLOUDS_TYPE_CUMULUS:
|
||||||
|
curveQuickAddPoint(definition->_coverage_by_altitude, 0.0, 0.0);
|
||||||
|
curveQuickAddPoint(definition->_coverage_by_altitude, 0.1, 1.0);
|
||||||
|
curveQuickAddPoint(definition->_coverage_by_altitude, 0.4, 0.8);
|
||||||
|
curveQuickAddPoint(definition->_coverage_by_altitude, 0.7, 1.0);
|
||||||
|
curveQuickAddPoint(definition->_coverage_by_altitude, 1.0, 0.0);
|
||||||
|
noiseAddLevelsSimple(definition->_shape_noise, 7, 1.0, 1.0);
|
||||||
|
noiseSetFunctionParams(definition->_shape_noise, NOISE_FUNCTION_SIMPLEX, 0.4);
|
||||||
|
break;
|
||||||
|
case CLOUDS_TYPE_STRATOCUMULUS:
|
||||||
|
curveQuickAddPoint(definition->_coverage_by_altitude, 0.0, 0.0);
|
||||||
|
curveQuickAddPoint(definition->_coverage_by_altitude, 0.2, 1.0);
|
||||||
|
curveQuickAddPoint(definition->_coverage_by_altitude, 0.5, 1.0);
|
||||||
|
curveQuickAddPoint(definition->_coverage_by_altitude, 1.0, 0.0);
|
||||||
|
noiseAddLevelsSimple(definition->_shape_noise, 2, 1.0, 1.0);
|
||||||
|
noiseSetFunctionParams(definition->_shape_noise, NOISE_FUNCTION_SIMPLEX, 0.3);
|
||||||
|
noiseAddLevelsSimple(definition->_edge_noise, 8, 1.0, 1.0);
|
||||||
|
noiseSetFunctionParams(definition->_edge_noise, NOISE_FUNCTION_SIMPLEX, 0.5);
|
||||||
|
break;
|
||||||
|
case CLOUDS_TYPE_STRATUS:
|
||||||
|
curveQuickAddPoint(definition->_coverage_by_altitude, 0.0, 0.0);
|
||||||
|
curveQuickAddPoint(definition->_coverage_by_altitude, 0.2, 1.0);
|
||||||
|
curveQuickAddPoint(definition->_coverage_by_altitude, 0.8, 1.0);
|
||||||
|
curveQuickAddPoint(definition->_coverage_by_altitude, 1.0, 0.0);
|
||||||
|
noiseAddLevelsSimple(definition->_shape_noise, 3, 1.0, 1.0);
|
||||||
|
noiseSetFunctionParams(definition->_shape_noise, NOISE_FUNCTION_SIMPLEX, -0.3);
|
||||||
|
noiseAddLevelsSimple(definition->_edge_noise, 4, 1.0, 1.0);
|
||||||
|
noiseSetFunctionParams(definition->_edge_noise, NOISE_FUNCTION_SIMPLEX, -0.5);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CloudsLayerDefinition* cloudsLayerCreateDefinition()
|
||||||
|
{
|
||||||
|
CloudsLayerDefinition* result;
|
||||||
|
|
||||||
|
result = malloc(sizeof(CloudsLayerDefinition));
|
||||||
|
result->_coverage_by_altitude = curveCreate();
|
||||||
|
result->_shape_noise = noiseCreateGenerator();
|
||||||
|
result->_edge_noise = noiseCreateGenerator();
|
||||||
|
|
||||||
|
cloudsAutoPreset(result, CLOUDS_PRESET_CIRRUS);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cloudsLayerDeleteDefinition(CloudsLayerDefinition* definition)
|
||||||
|
{
|
||||||
|
curveDelete(definition->_coverage_by_altitude);
|
||||||
|
noiseDeleteGenerator(definition->_shape_noise);
|
||||||
|
noiseDeleteGenerator(definition->_edge_noise);
|
||||||
|
free(definition);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cloudsLayerCopyDefinition(CloudsLayerDefinition* source, CloudsLayerDefinition* destination)
|
||||||
|
{
|
||||||
|
CloudsLayerDefinition temp;
|
||||||
|
|
||||||
|
temp = *destination;
|
||||||
|
*destination = *source;
|
||||||
|
|
||||||
|
destination->_shape_noise = temp._shape_noise;
|
||||||
|
noiseCopy(source->_shape_noise, destination->_shape_noise);
|
||||||
|
|
||||||
|
destination->_edge_noise = temp._edge_noise;
|
||||||
|
noiseCopy(source->_edge_noise, destination->_edge_noise);
|
||||||
|
|
||||||
|
destination->_coverage_by_altitude = temp._coverage_by_altitude;
|
||||||
|
curveCopy(source->_coverage_by_altitude, destination->_coverage_by_altitude);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _cloudsLayerSave(PackStream* stream, CloudsLayerDefinition* layer)
|
||||||
|
{
|
||||||
|
int clouds_type = (int)layer->type;
|
||||||
|
|
||||||
|
packWriteInt(stream, &clouds_type);
|
||||||
|
packWriteDouble(stream, &layer->lower_altitude);
|
||||||
|
packWriteDouble(stream, &layer->thickness);
|
||||||
|
curveSave(stream, layer->_coverage_by_altitude);
|
||||||
|
noiseSaveGenerator(stream, layer->_shape_noise);
|
||||||
|
noiseSaveGenerator(stream, layer->_edge_noise);
|
||||||
|
materialSave(stream, &layer->material);
|
||||||
|
packWriteDouble(stream, &layer->hardness);
|
||||||
|
packWriteDouble(stream, &layer->transparencydepth);
|
||||||
|
packWriteDouble(stream, &layer->lighttraversal);
|
||||||
|
packWriteDouble(stream, &layer->minimumlight);
|
||||||
|
packWriteDouble(stream, &layer->shape_scaling);
|
||||||
|
packWriteDouble(stream, &layer->edge_scaling);
|
||||||
|
packWriteDouble(stream, &layer->edge_length);
|
||||||
|
packWriteDouble(stream, &layer->base_coverage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _cloudsLayerLoad(PackStream* stream, CloudsLayerDefinition* layer)
|
||||||
|
{
|
||||||
|
int clouds_type;
|
||||||
|
|
||||||
|
packReadInt(stream, &clouds_type);
|
||||||
|
layer->type = (CloudsType)clouds_type;
|
||||||
|
packReadDouble(stream, &layer->lower_altitude);
|
||||||
|
packReadDouble(stream, &layer->thickness);
|
||||||
|
materialLoad(stream, &layer->material);
|
||||||
|
packReadDouble(stream, &layer->hardness);
|
||||||
|
packReadDouble(stream, &layer->transparencydepth);
|
||||||
|
packReadDouble(stream, &layer->lighttraversal);
|
||||||
|
packReadDouble(stream, &layer->minimumlight);
|
||||||
|
packReadDouble(stream, &layer->shape_scaling);
|
||||||
|
packReadDouble(stream, &layer->edge_scaling);
|
||||||
|
packReadDouble(stream, &layer->edge_length);
|
||||||
|
packReadDouble(stream, &layer->base_coverage);
|
||||||
|
|
||||||
|
cloudsLayerValidateDefinition(layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
LayerType cloudsGetLayerType()
|
||||||
|
{
|
||||||
|
LayerType result;
|
||||||
|
|
||||||
|
result.callback_create = (LayerCallbackCreate)cloudsLayerCreateDefinition;
|
||||||
|
result.callback_delete = (LayerCallbackDelete)cloudsLayerDeleteDefinition;
|
||||||
|
result.callback_copy = (LayerCallbackCopy)cloudsLayerCopyDefinition;
|
||||||
|
result.callback_validate = (LayerCallbackValidate)cloudsLayerValidateDefinition;
|
||||||
|
result.callback_save = (LayerCallbackSave)_cloudsLayerSave;
|
||||||
|
result.callback_load = (LayerCallbackLoad)_cloudsLayerLoad;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
83
lib_paysages/clouds/presets.c
Normal file
83
lib_paysages/clouds/presets.c
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
#include "private.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clouds presets.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void cloudsAutoPreset(CloudsLayerDefinition* definition, CloudsPreset preset)
|
||||||
|
{
|
||||||
|
definition->material.base.r = 0.7;
|
||||||
|
definition->material.base.g = 0.7;
|
||||||
|
definition->material.base.b = 0.7;
|
||||||
|
definition->material.base.a = 1.0;
|
||||||
|
|
||||||
|
switch (preset)
|
||||||
|
{
|
||||||
|
case CLOUDS_PRESET_CIRRUS:
|
||||||
|
definition->type = CLOUDS_TYPE_CIRRUS;
|
||||||
|
definition->lower_altitude = 25.0;
|
||||||
|
definition->thickness = 2.0;
|
||||||
|
definition->material.reflection = 0.4;
|
||||||
|
definition->material.shininess = 0.5;
|
||||||
|
definition->hardness = 0.0;
|
||||||
|
definition->transparencydepth = 3.0;
|
||||||
|
definition->lighttraversal = 10.0;
|
||||||
|
definition->minimumlight = 0.6;
|
||||||
|
definition->shape_scaling = 8.0;
|
||||||
|
definition->edge_scaling = 2.0;
|
||||||
|
definition->edge_length = 0.8;
|
||||||
|
definition->base_coverage = 0.6;
|
||||||
|
break;
|
||||||
|
case CLOUDS_PRESET_CUMULUS:
|
||||||
|
definition->type = CLOUDS_TYPE_CUMULUS;
|
||||||
|
definition->lower_altitude = 15.0;
|
||||||
|
definition->thickness = 15.0;
|
||||||
|
definition->material.reflection = 0.5;
|
||||||
|
definition->material.shininess = 1.2;
|
||||||
|
definition->hardness = 0.25;
|
||||||
|
definition->transparencydepth = 1.5;
|
||||||
|
definition->lighttraversal = 8.0;
|
||||||
|
definition->minimumlight = 0.4;
|
||||||
|
definition->shape_scaling = 20.0;
|
||||||
|
definition->edge_scaling = 2.0;
|
||||||
|
definition->edge_length = 0.0;
|
||||||
|
definition->base_coverage = 0.7;
|
||||||
|
break;
|
||||||
|
case CLOUDS_PRESET_STRATOCUMULUS:
|
||||||
|
definition->type = CLOUDS_TYPE_STRATOCUMULUS;
|
||||||
|
definition->lower_altitude = 5.0;
|
||||||
|
definition->thickness = 6.0;
|
||||||
|
definition->material.reflection = 0.3;
|
||||||
|
definition->material.shininess = 0.8;
|
||||||
|
definition->hardness = 0.25;
|
||||||
|
definition->transparencydepth = 1.5;
|
||||||
|
definition->lighttraversal = 7.0;
|
||||||
|
definition->minimumlight = 0.4;
|
||||||
|
definition->shape_scaling = 10.0;
|
||||||
|
definition->edge_scaling = 0.8;
|
||||||
|
definition->edge_length = 0.3;
|
||||||
|
definition->base_coverage = 0.4;
|
||||||
|
break;
|
||||||
|
case CLOUDS_PRESET_STRATUS:
|
||||||
|
definition->type = CLOUDS_TYPE_STRATUS;
|
||||||
|
definition->lower_altitude = 3.0;
|
||||||
|
definition->thickness = 4.0;
|
||||||
|
definition->material.reflection = 0.1;
|
||||||
|
definition->material.shininess = 0.8;
|
||||||
|
definition->hardness = 0.1;
|
||||||
|
definition->transparencydepth = 3.0;
|
||||||
|
definition->lighttraversal = 10.0;
|
||||||
|
definition->minimumlight = 0.6;
|
||||||
|
definition->shape_scaling = 8.0;
|
||||||
|
definition->edge_scaling = 2.0;
|
||||||
|
definition->edge_length = 1.0;
|
||||||
|
definition->base_coverage = 0.4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cloudsLayerValidateDefinition(definition);
|
||||||
|
}
|
65
lib_paysages/clouds/preview.c
Normal file
65
lib_paysages/clouds/preview.c
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
#include "private.h"
|
||||||
|
|
||||||
|
#include "../tools/euclid.h"
|
||||||
|
#include "../renderer.h"
|
||||||
|
#include "../tools.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clouds previews.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Color _fakeApplyLightingToSurface(Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial* material)
|
||||||
|
{
|
||||||
|
UNUSED(renderer);
|
||||||
|
UNUSED(location);
|
||||||
|
UNUSED(normal);
|
||||||
|
UNUSED(material);
|
||||||
|
|
||||||
|
return COLOR_WHITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer* cloudsCreatePreviewCoverageRenderer()
|
||||||
|
{
|
||||||
|
Renderer* result = rendererCreate();
|
||||||
|
result->render_quality = 5;
|
||||||
|
result->applyLightingToSurface = _fakeApplyLightingToSurface;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color cloudsGetPreviewCoverage(Renderer* renderer, double x, double y, double scaling)
|
||||||
|
{
|
||||||
|
Vector3 eye, look;
|
||||||
|
|
||||||
|
eye.x = 0.0;
|
||||||
|
eye.y = scaling;
|
||||||
|
eye.z = -10.0 * scaling;
|
||||||
|
look.x = x * 0.01 / scaling;
|
||||||
|
look.y = -y * 0.01 / scaling - 0.3;
|
||||||
|
look.z = 1.0;
|
||||||
|
look = v3Normalize(look);
|
||||||
|
|
||||||
|
return renderer->clouds->getColor(renderer, COLOR_BLUE, eye, v3Add(eye, v3Scale(look, 1000.0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer* cloudsCreatePreviewColorRenderer()
|
||||||
|
{
|
||||||
|
Renderer* result = rendererCreate();
|
||||||
|
result->render_quality = 8;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color cloudsGetPreviewColor(Renderer* renderer, double x, double y)
|
||||||
|
{
|
||||||
|
Vector3 start, end;
|
||||||
|
double thickness = 0.5;
|
||||||
|
|
||||||
|
start.x = x * thickness * 0.5;
|
||||||
|
start.y = -y * thickness * 0.5;
|
||||||
|
start.z = thickness * 0.5;
|
||||||
|
|
||||||
|
end.x = start.x;
|
||||||
|
end.y = start.y;
|
||||||
|
end.z = -start.z;
|
||||||
|
|
||||||
|
return renderer->clouds->getColor(renderer, COLOR_BLUE, start, end);
|
||||||
|
}
|
21
lib_paysages/clouds/private.h
Normal file
21
lib_paysages/clouds/private.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef _PAYSAGES_CLOUDS_PRIVATE_H_
|
||||||
|
#define _PAYSAGES_CLOUDS_PRIVATE_H_
|
||||||
|
|
||||||
|
#include "public.h"
|
||||||
|
|
||||||
|
#define CLOUDS_MAX_LAYERS 6
|
||||||
|
#define MAX_SEGMENT_COUNT 30
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Vector3 start;
|
||||||
|
Vector3 end;
|
||||||
|
double length;
|
||||||
|
} CloudSegment;
|
||||||
|
|
||||||
|
void cloudsLayerValidateDefinition(CloudsLayerDefinition* definition);
|
||||||
|
|
||||||
|
Color cloudsLayerFilterLight(CloudsLayerDefinition* definition, Renderer* renderer, Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light);
|
||||||
|
Color cloudsApplyLayer(CloudsLayerDefinition* definition, Color base, Renderer* renderer, Vector3 start, Vector3 end);
|
||||||
|
|
||||||
|
#endif
|
85
lib_paysages/clouds/public.h
Normal file
85
lib_paysages/clouds/public.h
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
#ifndef _PAYSAGES_CLOUDS_PUBLIC_H_
|
||||||
|
#define _PAYSAGES_CLOUDS_PUBLIC_H_
|
||||||
|
|
||||||
|
#include "../shared/types.h"
|
||||||
|
#include "../tools/lighting.h"
|
||||||
|
#include "../tools/curve.h"
|
||||||
|
#include "../tools/euclid.h"
|
||||||
|
#include "../noise.h"
|
||||||
|
#include "../layers.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CLOUDS_TYPE_CIRRUS,
|
||||||
|
CLOUDS_TYPE_CUMULUS,
|
||||||
|
CLOUDS_TYPE_STRATOCUMULUS,
|
||||||
|
CLOUDS_TYPE_STRATUS
|
||||||
|
} CloudsType;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CLOUDS_PRESET_CIRRUS,
|
||||||
|
CLOUDS_PRESET_CUMULUS,
|
||||||
|
CLOUDS_PRESET_STRATOCUMULUS,
|
||||||
|
CLOUDS_PRESET_STRATUS
|
||||||
|
} CloudsPreset;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CloudsType type;
|
||||||
|
double lower_altitude;
|
||||||
|
double thickness;
|
||||||
|
double base_coverage;
|
||||||
|
double shape_scaling;
|
||||||
|
double edge_scaling;
|
||||||
|
double edge_length;
|
||||||
|
SurfaceMaterial material;
|
||||||
|
double hardness;
|
||||||
|
double transparencydepth;
|
||||||
|
double lighttraversal;
|
||||||
|
double minimumlight;
|
||||||
|
|
||||||
|
Curve* _coverage_by_altitude;
|
||||||
|
NoiseGenerator* _shape_noise;
|
||||||
|
NoiseGenerator* _edge_noise;
|
||||||
|
} CloudsLayerDefinition;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Layers* layers;
|
||||||
|
} CloudsDefinition;
|
||||||
|
|
||||||
|
|
||||||
|
typedef Color (*FuncCloudsGetColor)(Renderer* renderer, Color base, Vector3 start, Vector3 end);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CloudsDefinition* definition;
|
||||||
|
|
||||||
|
FuncCloudsGetColor getColor;
|
||||||
|
FuncLightingAlterLight alterLight;
|
||||||
|
} CloudsRenderer;
|
||||||
|
|
||||||
|
|
||||||
|
extern StandardDefinition CloudsDefinitionClass;
|
||||||
|
extern StandardRenderer CloudsRendererClass;
|
||||||
|
|
||||||
|
|
||||||
|
LayerType cloudsGetLayerType();
|
||||||
|
void cloudsAutoPreset(CloudsLayerDefinition* definition, CloudsPreset preset);
|
||||||
|
|
||||||
|
Renderer* cloudsCreatePreviewCoverageRenderer();
|
||||||
|
Color cloudsGetPreviewCoverage(Renderer* renderer, double x, double y, double scaling);
|
||||||
|
|
||||||
|
Renderer* cloudsCreatePreviewColorRenderer();
|
||||||
|
Color cloudsGetPreviewColor(Renderer* renderer, double x, double y);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
100
lib_paysages/clouds/rendering.c
Normal file
100
lib_paysages/clouds/rendering.c
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
#include "private.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "../tools.h"
|
||||||
|
#include "../renderer.h"
|
||||||
|
|
||||||
|
/******************** Fake ********************/
|
||||||
|
static int _fakeAlterLight(Renderer* renderer, LightDefinition* light, Vector3 location)
|
||||||
|
{
|
||||||
|
UNUSED(renderer);
|
||||||
|
UNUSED(light);
|
||||||
|
UNUSED(location);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Color _fakeGetColor(Renderer* renderer, Color base, Vector3 start, Vector3 end)
|
||||||
|
{
|
||||||
|
UNUSED(renderer);
|
||||||
|
UNUSED(start);
|
||||||
|
UNUSED(end);
|
||||||
|
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************** Real ********************/
|
||||||
|
/*static int _cmpLayer(const void* layer1, const void* layer2)
|
||||||
|
{
|
||||||
|
return (((CloudsLayerDefinition*)layer1)->lower_altitude > ((CloudsLayerDefinition*)layer2)->lower_altitude) ? -1 : 1;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
static int _alterLight(Renderer* renderer, LightDefinition* light, Vector3 location)
|
||||||
|
{
|
||||||
|
CloudsDefinition* definition = renderer->clouds->definition;
|
||||||
|
int i, n;
|
||||||
|
|
||||||
|
/* TODO Iter layers in sorted order */
|
||||||
|
n = layersCount(definition->layers);
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
light->color = cloudsLayerFilterLight(layersGetLayer(definition->layers, i), renderer, light->color, location, v3Add(location, v3Scale(light->direction, -10000.0)), v3Scale(light->direction, -1.0));
|
||||||
|
}
|
||||||
|
return n > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Color _getColor(Renderer* renderer, Color base, Vector3 start, Vector3 end)
|
||||||
|
{
|
||||||
|
CloudsDefinition* definition = renderer->clouds->definition;
|
||||||
|
int i, n;
|
||||||
|
|
||||||
|
n = layersCount(definition->layers);
|
||||||
|
if (n < 1)
|
||||||
|
{
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO Iter layers in sorted order */
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
base = cloudsApplyLayer(layersGetLayer(definition->layers, i), base, renderer, start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************** Renderer ********************/
|
||||||
|
static CloudsRenderer* _createRenderer()
|
||||||
|
{
|
||||||
|
CloudsRenderer* result;
|
||||||
|
|
||||||
|
result = malloc(sizeof(CloudsRenderer));
|
||||||
|
result->definition = CloudsDefinitionClass.create();
|
||||||
|
|
||||||
|
result->getColor = _fakeGetColor;
|
||||||
|
result->alterLight = (FuncLightingAlterLight)_fakeAlterLight;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _deleteRenderer(CloudsRenderer* renderer)
|
||||||
|
{
|
||||||
|
CloudsDefinitionClass.destroy(renderer->definition);
|
||||||
|
free(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _bindRenderer(Renderer* renderer, CloudsDefinition* definition)
|
||||||
|
{
|
||||||
|
CloudsDefinitionClass.copy(definition, renderer->clouds->definition);
|
||||||
|
|
||||||
|
renderer->clouds->getColor = _getColor;
|
||||||
|
renderer->clouds->alterLight = (FuncLightingAlterLight)_alterLight;
|
||||||
|
|
||||||
|
lightingManagerRegisterFilter(renderer->lighting, (FuncLightingAlterLight)_alterLight, renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
StandardRenderer CloudsRendererClass = {
|
||||||
|
(FuncObjectCreate)_createRenderer,
|
||||||
|
(FuncObjectDelete)_deleteRenderer,
|
||||||
|
(FuncObjectBind)_bindRenderer
|
||||||
|
};
|
374
lib_paysages/clouds/tools.c
Normal file
374
lib_paysages/clouds/tools.c
Normal file
|
@ -0,0 +1,374 @@
|
||||||
|
#include "private.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clouds tools.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../renderer.h"
|
||||||
|
|
||||||
|
static double _standardCoverageFunc(CloudsLayerDefinition* layer, Vector3 position)
|
||||||
|
{
|
||||||
|
if (position.y < layer->lower_altitude || position.y >= layer->lower_altitude + layer->thickness)
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return layer->base_coverage * curveGetValue(layer->_coverage_by_altitude, (position.y - layer->lower_altitude) / layer->thickness);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline double _getDistanceToBorder(CloudsLayerDefinition* layer, Vector3 position)
|
||||||
|
{
|
||||||
|
double density, coverage, val;
|
||||||
|
|
||||||
|
val = noiseGet3DTotal(layer->_shape_noise, position.x / layer->shape_scaling, position.y / layer->shape_scaling, position.z / layer->shape_scaling) / noiseGetMaxValue(layer->_shape_noise);
|
||||||
|
coverage = _standardCoverageFunc(layer, position);
|
||||||
|
density = 0.5 * val - 0.5 + coverage;
|
||||||
|
|
||||||
|
if (density <= 0.0)
|
||||||
|
{
|
||||||
|
/* outside the main shape */
|
||||||
|
return density * layer->shape_scaling;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* inside the main shape, using edge noise */
|
||||||
|
density /= coverage;
|
||||||
|
if (density < layer->edge_length)
|
||||||
|
{
|
||||||
|
density /= layer->edge_length;
|
||||||
|
|
||||||
|
val = 0.5 * noiseGet3DTotal(layer->_edge_noise, position.x / layer->edge_scaling, position.y / layer->edge_scaling, position.z / layer->edge_scaling) / noiseGetMaxValue(layer->_edge_noise);
|
||||||
|
val = val - 0.5 + density;
|
||||||
|
|
||||||
|
return val * (density * coverage * layer->shape_scaling + (1.0 - density) * layer->edge_scaling);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return density * coverage * layer->shape_scaling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Vector3 _getNormal(CloudsLayerDefinition* layer, Vector3 position, double detail)
|
||||||
|
{
|
||||||
|
Vector3 result = {0.0, 0.0, 0.0};
|
||||||
|
Vector3 dposition;
|
||||||
|
double val, dval;
|
||||||
|
|
||||||
|
val = _getDistanceToBorder(layer, position);
|
||||||
|
|
||||||
|
dposition.x = position.x + detail;
|
||||||
|
dposition.y = position.y;
|
||||||
|
dposition.z = position.z;
|
||||||
|
dval = val - _getDistanceToBorder(layer, dposition);
|
||||||
|
result.x += dval;
|
||||||
|
|
||||||
|
dposition.x = position.x - detail;
|
||||||
|
dval = val - _getDistanceToBorder(layer, dposition);
|
||||||
|
result.x -= dval;
|
||||||
|
|
||||||
|
dposition.x = position.x;
|
||||||
|
dposition.y = position.y + detail;
|
||||||
|
dval = val - _getDistanceToBorder(layer, dposition);
|
||||||
|
result.y += dval;
|
||||||
|
|
||||||
|
dposition.y = position.y - detail;
|
||||||
|
dval = val - _getDistanceToBorder(layer, dposition);
|
||||||
|
result.y -= dval;
|
||||||
|
|
||||||
|
dposition.y = position.y;
|
||||||
|
dposition.z = position.z + detail;
|
||||||
|
dval = val - _getDistanceToBorder(layer, dposition);
|
||||||
|
result.z += dval;
|
||||||
|
|
||||||
|
dposition.z = position.z - detail;
|
||||||
|
dval = val - _getDistanceToBorder(layer, dposition);
|
||||||
|
result.z -= dval;
|
||||||
|
|
||||||
|
return v3Normalize(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optimize the search limits in a layer.
|
||||||
|
*
|
||||||
|
* @param layer The cloud layer
|
||||||
|
* @param start Start of the search to optimize
|
||||||
|
* @param end End of the search to optimize
|
||||||
|
* @return 0 if the search is useless
|
||||||
|
*/
|
||||||
|
static int _optimizeSearchLimits(CloudsLayerDefinition* layer, Vector3* start, Vector3* end)
|
||||||
|
{
|
||||||
|
Vector3 diff;
|
||||||
|
|
||||||
|
if (start->y > layer->lower_altitude + layer->thickness)
|
||||||
|
{
|
||||||
|
if (end->y >= layer->lower_altitude + layer->thickness)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diff = v3Sub(*end, *start);
|
||||||
|
*start = v3Add(*start, v3Scale(diff, (layer->lower_altitude + layer->thickness - start->y) / diff.y));
|
||||||
|
if (end->y < layer->lower_altitude)
|
||||||
|
{
|
||||||
|
*end = v3Add(*end, v3Scale(diff, (layer->lower_altitude - end->y) / diff.y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (start->y < layer->lower_altitude)
|
||||||
|
{
|
||||||
|
if (end->y <= layer->lower_altitude)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diff = v3Sub(*end, *start);
|
||||||
|
*start = v3Add(*start, v3Scale(diff, (layer->lower_altitude - start->y) / diff.y));
|
||||||
|
if (end->y >= layer->lower_altitude + layer->thickness)
|
||||||
|
{
|
||||||
|
*end = v3Add(*end, v3Scale(diff, (layer->lower_altitude + layer->thickness - end->y) / diff.y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* start is inside layer */
|
||||||
|
{
|
||||||
|
diff = v3Sub(*end, *start);
|
||||||
|
if (end->y > layer->lower_altitude + layer->thickness)
|
||||||
|
{
|
||||||
|
*end = v3Add(*start, v3Scale(diff, (layer->lower_altitude + layer->thickness - start->y) / diff.y));
|
||||||
|
}
|
||||||
|
else if (end->y < layer->lower_altitude)
|
||||||
|
{
|
||||||
|
*end = v3Add(*start, v3Scale(diff, (layer->lower_altitude - start->y) / diff.y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO Limit the search length */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Go through the cloud layer to find segments (parts of the lookup that are inside the cloud).
|
||||||
|
*
|
||||||
|
* @param definition The cloud layer
|
||||||
|
* @param renderer The renderer environment
|
||||||
|
* @param start Start position of the lookup (already optimized)
|
||||||
|
* @param direction Normalized direction of the lookup
|
||||||
|
* @param detail Level of noise detail required
|
||||||
|
* @param max_segments Maximum number of segments to collect
|
||||||
|
* @param max_inside_length Maximum length to spend inside the cloud
|
||||||
|
* @param max_total_length Maximum lookup length
|
||||||
|
* @param inside_length Resulting length inside cloud (sum of all segments length)
|
||||||
|
* @param total_length Resulting lookup length
|
||||||
|
* @param out_segments Allocated space to fill found segments
|
||||||
|
* @return Number of segments found
|
||||||
|
*/
|
||||||
|
static int _findSegments(CloudsLayerDefinition* definition, Renderer* renderer, Vector3 start, Vector3 direction, double detail, int max_segments, double max_inside_length, double max_total_length, double* inside_length, double* total_length, CloudSegment* out_segments)
|
||||||
|
{
|
||||||
|
int inside, segment_count;
|
||||||
|
double current_total_length, current_inside_length;
|
||||||
|
double step_length, segment_length, remaining_length;
|
||||||
|
double noise_distance, last_noise_distance;
|
||||||
|
Vector3 walker, step, segment_start;
|
||||||
|
double render_precision;
|
||||||
|
|
||||||
|
if (max_segments <= 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
render_precision = 1.005 - 0.01 * (double)(renderer->render_quality * renderer->render_quality);
|
||||||
|
if (render_precision > max_total_length / 10.0)
|
||||||
|
{
|
||||||
|
render_precision = max_total_length / 10.0;
|
||||||
|
}
|
||||||
|
else if (render_precision < max_total_length / 10000.0)
|
||||||
|
{
|
||||||
|
render_precision = max_total_length / 10000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
segment_count = 0;
|
||||||
|
current_total_length = 0.0;
|
||||||
|
current_inside_length = 0.0;
|
||||||
|
segment_length = 0.0;
|
||||||
|
walker = start;
|
||||||
|
noise_distance = _getDistanceToBorder(definition, start) * render_precision;
|
||||||
|
inside = (noise_distance > 0.0) ? 1 : 0;
|
||||||
|
step = v3Scale(direction, render_precision);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
walker = v3Add(walker, step);
|
||||||
|
step_length = v3Norm(step);
|
||||||
|
last_noise_distance = noise_distance;
|
||||||
|
noise_distance = _getDistanceToBorder(definition, walker) * render_precision;
|
||||||
|
current_total_length += step_length;
|
||||||
|
|
||||||
|
if (current_total_length >= max_total_length || current_inside_length > max_inside_length)
|
||||||
|
{
|
||||||
|
noise_distance = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (noise_distance > 0.0)
|
||||||
|
{
|
||||||
|
if (inside)
|
||||||
|
{
|
||||||
|
// inside the cloud
|
||||||
|
segment_length += step_length;
|
||||||
|
current_inside_length += step_length;
|
||||||
|
step = v3Scale(direction, (noise_distance < render_precision) ? render_precision : noise_distance);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// entering the cloud
|
||||||
|
inside = 1;
|
||||||
|
segment_length = step_length * noise_distance / (noise_distance - last_noise_distance);
|
||||||
|
segment_start = v3Add(walker, v3Scale(direction, -segment_length));
|
||||||
|
current_inside_length += segment_length;
|
||||||
|
step = v3Scale(direction, render_precision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (inside)
|
||||||
|
{
|
||||||
|
// exiting the cloud
|
||||||
|
remaining_length = step_length * last_noise_distance / (last_noise_distance - noise_distance);
|
||||||
|
segment_length += remaining_length;
|
||||||
|
current_inside_length += remaining_length;
|
||||||
|
|
||||||
|
out_segments->start = segment_start;
|
||||||
|
out_segments->end = v3Add(walker, v3Scale(direction, remaining_length - step_length));
|
||||||
|
out_segments->length = segment_length;
|
||||||
|
out_segments++;
|
||||||
|
if (++segment_count >= max_segments)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
inside = 0;
|
||||||
|
step = v3Scale(direction, render_precision);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// searching for a cloud
|
||||||
|
step = v3Scale(direction, (noise_distance > -render_precision) ? render_precision : -noise_distance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (inside || (walker.y <= definition->lower_altitude + definition->thickness + 0.001 && walker.y >= definition->lower_altitude - 0.001 && current_total_length < max_total_length && current_inside_length < max_inside_length));
|
||||||
|
|
||||||
|
*total_length = current_total_length;
|
||||||
|
*inside_length = current_inside_length;
|
||||||
|
return segment_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Color _applyLayerLighting(CloudsLayerDefinition* definition, Renderer* renderer, Vector3 location, double detail)
|
||||||
|
{
|
||||||
|
Vector3 normal;
|
||||||
|
Color col1, col2;
|
||||||
|
LightStatus* lighting;
|
||||||
|
|
||||||
|
normal = _getNormal(definition, location, 3.0);
|
||||||
|
if (renderer->render_quality > 3)
|
||||||
|
{
|
||||||
|
normal = v3Add(normal, _getNormal(definition, location, 2.0));
|
||||||
|
normal = v3Add(normal, _getNormal(definition, location, 1.0));
|
||||||
|
}
|
||||||
|
if (renderer->render_quality > 5)
|
||||||
|
{
|
||||||
|
normal = v3Add(normal, _getNormal(definition, location, 0.5));
|
||||||
|
}
|
||||||
|
if (renderer->render_quality > 8)
|
||||||
|
{
|
||||||
|
normal = v3Add(normal, _getNormal(definition, location, 0.75));
|
||||||
|
normal = v3Add(normal, _getNormal(definition, location, 1.25));
|
||||||
|
normal = v3Add(normal, _getNormal(definition, location, 2.5));
|
||||||
|
}
|
||||||
|
normal = v3Scale(v3Normalize(normal), definition->hardness);
|
||||||
|
|
||||||
|
return renderer->applyLightingToSurface(renderer, location, normal, &definition->material);
|
||||||
|
|
||||||
|
lighting = lightingCreateStatus(renderer->lighting, location, renderer->camera_location);
|
||||||
|
renderer->atmosphere->getLightingStatus(renderer, lighting, normal, 0);
|
||||||
|
col1 = lightingApplyStatus(lighting, normal, &definition->material);
|
||||||
|
col2 = lightingApplyStatus(lighting, v3Scale(normal, -1.0), &definition->material);
|
||||||
|
lightingDeleteStatus(lighting);
|
||||||
|
|
||||||
|
col1.r = (col1.r + col2.r) / 2.0;
|
||||||
|
col1.g = (col1.g + col2.g) / 2.0;
|
||||||
|
col1.b = (col1.b + col2.b) / 2.0;
|
||||||
|
col1.a = (col1.a + col2.a) / 2.0;
|
||||||
|
|
||||||
|
return col1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color cloudsApplyLayer(CloudsLayerDefinition* definition, Color base, Renderer* renderer, Vector3 start, Vector3 end)
|
||||||
|
{
|
||||||
|
int i, segment_count;
|
||||||
|
double max_length, detail, total_length, inside_length;
|
||||||
|
Vector3 direction;
|
||||||
|
Color col;
|
||||||
|
CloudSegment segments[MAX_SEGMENT_COUNT];
|
||||||
|
|
||||||
|
if (!_optimizeSearchLimits(definition, &start, &end))
|
||||||
|
{
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
direction = v3Sub(end, start);
|
||||||
|
max_length = v3Norm(direction);
|
||||||
|
direction = v3Normalize(direction);
|
||||||
|
|
||||||
|
detail = renderer->getPrecision(renderer, start) / definition->shape_scaling;
|
||||||
|
|
||||||
|
segment_count = _findSegments(definition, renderer, start, direction, detail, MAX_SEGMENT_COUNT, definition->transparencydepth * (double)renderer->render_quality, max_length, &inside_length, &total_length, segments);
|
||||||
|
for (i = segment_count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
col = _applyLayerLighting(definition, renderer, segments[i].start, detail);
|
||||||
|
col.a = 1.0;
|
||||||
|
col = renderer->atmosphere->applyAerialPerspective(renderer, start, col);
|
||||||
|
col.a = (segments[i].length >= definition->transparencydepth) ? 1.0 : (segments[i].length / definition->transparencydepth);
|
||||||
|
colorMask(&base, &col);
|
||||||
|
}
|
||||||
|
if (inside_length >= definition->transparencydepth)
|
||||||
|
{
|
||||||
|
col.a = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color cloudsLayerFilterLight(CloudsLayerDefinition* definition, Renderer* renderer, Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light)
|
||||||
|
{
|
||||||
|
double inside_depth, total_depth, factor;
|
||||||
|
CloudSegment segments[MAX_SEGMENT_COUNT];
|
||||||
|
|
||||||
|
_optimizeSearchLimits(definition, &location, &light_location);
|
||||||
|
|
||||||
|
_findSegments(definition, renderer, location, direction_to_light, 0.1, MAX_SEGMENT_COUNT, definition->lighttraversal, v3Norm(v3Sub(light_location, location)), &inside_depth, &total_depth, segments);
|
||||||
|
|
||||||
|
if (definition->lighttraversal < 0.0001)
|
||||||
|
{
|
||||||
|
factor = 0.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
factor = inside_depth / definition->lighttraversal;
|
||||||
|
if (factor > 1.0)
|
||||||
|
{
|
||||||
|
factor = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
factor = 1.0 - (1.0 - definition->minimumlight) * factor;
|
||||||
|
|
||||||
|
light.r = light.r * factor;
|
||||||
|
light.g = light.g * factor;
|
||||||
|
light.b = light.b * factor;
|
||||||
|
|
||||||
|
return light;
|
||||||
|
}
|
|
@ -69,11 +69,6 @@ static Color _applyTextures(Renderer* renderer, Vector3 location, double precisi
|
||||||
return COLOR_TRANSPARENT;
|
return COLOR_TRANSPARENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Color _applyClouds(Renderer* renderer, Color base, Vector3 start, Vector3 end)
|
|
||||||
{
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
|
|
||||||
Color _applyLightingToSurface(Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial* material)
|
Color _applyLightingToSurface(Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial* material)
|
||||||
{
|
{
|
||||||
LightStatus* light = lightingCreateStatus(renderer->lighting, location, renderer->camera_location);
|
LightStatus* light = lightingCreateStatus(renderer->lighting, location, renderer->camera_location);
|
||||||
|
@ -110,13 +105,13 @@ Renderer* rendererCreate()
|
||||||
result->rayWalking = _rayWalking;
|
result->rayWalking = _rayWalking;
|
||||||
result->getWaterHeightInfo = _getWaterHeightInfo;
|
result->getWaterHeightInfo = _getWaterHeightInfo;
|
||||||
result->applyTextures = _applyTextures;
|
result->applyTextures = _applyTextures;
|
||||||
result->applyClouds = _applyClouds;
|
|
||||||
|
|
||||||
result->applyLightingToSurface = _applyLightingToSurface;
|
result->applyLightingToSurface = _applyLightingToSurface;
|
||||||
|
|
||||||
result->lighting = lightingManagerCreate();
|
result->lighting = lightingManagerCreate();
|
||||||
|
|
||||||
result->atmosphere = AtmosphereRendererClass.create();
|
result->atmosphere = AtmosphereRendererClass.create();
|
||||||
|
result->clouds = CloudsRendererClass.create();
|
||||||
result->terrain = TerrainRendererClass.create();
|
result->terrain = TerrainRendererClass.create();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -127,6 +122,7 @@ void rendererDelete(Renderer* renderer)
|
||||||
lightingManagerDelete(renderer->lighting);
|
lightingManagerDelete(renderer->lighting);
|
||||||
|
|
||||||
AtmosphereRendererClass.destroy(renderer->atmosphere);
|
AtmosphereRendererClass.destroy(renderer->atmosphere);
|
||||||
|
CloudsRendererClass.destroy(renderer->clouds);
|
||||||
TerrainRendererClass.destroy(renderer->terrain);
|
TerrainRendererClass.destroy(renderer->terrain);
|
||||||
|
|
||||||
renderDeleteArea(renderer->render_area);
|
renderDeleteArea(renderer->render_area);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "shared/types.h"
|
#include "shared/types.h"
|
||||||
#include "atmosphere/public.h"
|
#include "atmosphere/public.h"
|
||||||
|
#include "clouds/public.h"
|
||||||
#include "terrain/public.h"
|
#include "terrain/public.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
|
||||||
|
@ -38,7 +39,6 @@ struct Renderer
|
||||||
RayCastingResult (*rayWalking)(Renderer* renderer, Vector3 location, Vector3 direction, int terrain, int water, int sky, int clouds);
|
RayCastingResult (*rayWalking)(Renderer* renderer, Vector3 location, Vector3 direction, int terrain, int water, int sky, int clouds);
|
||||||
HeightInfo (*getWaterHeightInfo)(Renderer* renderer);
|
HeightInfo (*getWaterHeightInfo)(Renderer* renderer);
|
||||||
Color (*applyTextures)(Renderer* renderer, Vector3 location, double precision);
|
Color (*applyTextures)(Renderer* renderer, Vector3 location, double precision);
|
||||||
Color (*applyClouds)(Renderer* renderer, Color base, Vector3 start, Vector3 end);
|
|
||||||
|
|
||||||
/* Autonomous tools */
|
/* Autonomous tools */
|
||||||
LightingManager* lighting;
|
LightingManager* lighting;
|
||||||
|
@ -46,6 +46,7 @@ struct Renderer
|
||||||
/* Autonomous sub-renderers */
|
/* Autonomous sub-renderers */
|
||||||
AtmosphereRenderer* atmosphere;
|
AtmosphereRenderer* atmosphere;
|
||||||
TerrainRenderer* terrain;
|
TerrainRenderer* terrain;
|
||||||
|
CloudsRenderer* clouds;
|
||||||
|
|
||||||
/* Custom data */
|
/* Custom data */
|
||||||
void* customData[10];
|
void* customData[10];
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
static AtmosphereDefinition* _atmosphere;
|
static AtmosphereDefinition* _atmosphere;
|
||||||
static CameraDefinition _camera;
|
static CameraDefinition _camera;
|
||||||
static CloudsDefinition _clouds;
|
static CloudsDefinition* _clouds;
|
||||||
static TerrainDefinition* _terrain;
|
static TerrainDefinition* _terrain;
|
||||||
static TexturesDefinition _textures;
|
static TexturesDefinition _textures;
|
||||||
static WaterDefinition _water;
|
static WaterDefinition _water;
|
||||||
|
@ -22,7 +22,7 @@ void sceneryInit()
|
||||||
|
|
||||||
_atmosphere = AtmosphereDefinitionClass.create();
|
_atmosphere = AtmosphereDefinitionClass.create();
|
||||||
_camera = cameraCreateDefinition();
|
_camera = cameraCreateDefinition();
|
||||||
_clouds = cloudsCreateDefinition();
|
_clouds = CloudsDefinitionClass.create();
|
||||||
_terrain = TerrainDefinitionClass.create();
|
_terrain = TerrainDefinitionClass.create();
|
||||||
_textures = texturesCreateDefinition();
|
_textures = texturesCreateDefinition();
|
||||||
_water = waterCreateDefinition();
|
_water = waterCreateDefinition();
|
||||||
|
@ -35,7 +35,7 @@ void sceneryQuit()
|
||||||
{
|
{
|
||||||
AtmosphereDefinitionClass.destroy(_atmosphere);
|
AtmosphereDefinitionClass.destroy(_atmosphere);
|
||||||
cameraDeleteDefinition(&_camera);
|
cameraDeleteDefinition(&_camera);
|
||||||
cloudsDeleteDefinition(&_clouds);
|
CloudsDefinitionClass.destroy(_clouds);
|
||||||
TerrainDefinitionClass.destroy(_terrain);
|
TerrainDefinitionClass.destroy(_terrain);
|
||||||
texturesDeleteDefinition(&_textures);
|
texturesDeleteDefinition(&_textures);
|
||||||
waterDeleteDefinition(&_water);
|
waterDeleteDefinition(&_water);
|
||||||
|
@ -55,7 +55,7 @@ void scenerySave(PackStream* stream)
|
||||||
noiseSave(stream);
|
noiseSave(stream);
|
||||||
AtmosphereDefinitionClass.save(stream, _atmosphere);
|
AtmosphereDefinitionClass.save(stream, _atmosphere);
|
||||||
cameraSave(stream, &_camera);
|
cameraSave(stream, &_camera);
|
||||||
cloudsSave(stream, &_clouds);
|
CloudsDefinitionClass.save(stream, _clouds);
|
||||||
TerrainDefinitionClass.save(stream, _terrain);
|
TerrainDefinitionClass.save(stream, _terrain);
|
||||||
texturesSave(stream, &_textures);
|
texturesSave(stream, &_textures);
|
||||||
waterSave(stream, &_water);
|
waterSave(stream, &_water);
|
||||||
|
@ -73,13 +73,12 @@ void sceneryLoad(PackStream* stream)
|
||||||
noiseLoad(stream);
|
noiseLoad(stream);
|
||||||
AtmosphereDefinitionClass.load(stream, _atmosphere);
|
AtmosphereDefinitionClass.load(stream, _atmosphere);
|
||||||
cameraLoad(stream, &_camera);
|
cameraLoad(stream, &_camera);
|
||||||
cloudsLoad(stream, &_clouds);
|
CloudsDefinitionClass.load(stream, _clouds);
|
||||||
TerrainDefinitionClass.load(stream, _terrain);
|
TerrainDefinitionClass.load(stream, _terrain);
|
||||||
texturesLoad(stream, &_textures);
|
texturesLoad(stream, &_textures);
|
||||||
waterLoad(stream, &_water);
|
waterLoad(stream, &_water);
|
||||||
|
|
||||||
cameraValidateDefinition(&_camera, 0);
|
cameraValidateDefinition(&_camera, 0);
|
||||||
cloudsValidateDefinition(&_clouds);
|
|
||||||
texturesValidateDefinition(&_textures);
|
texturesValidateDefinition(&_textures);
|
||||||
waterValidateDefinition(&_water);
|
waterValidateDefinition(&_water);
|
||||||
|
|
||||||
|
@ -112,13 +111,12 @@ void sceneryGetCamera(CameraDefinition* camera)
|
||||||
|
|
||||||
void scenerySetClouds(CloudsDefinition* clouds)
|
void scenerySetClouds(CloudsDefinition* clouds)
|
||||||
{
|
{
|
||||||
cloudsCopyDefinition(clouds, &_clouds);
|
CloudsDefinitionClass.copy(clouds, _clouds);
|
||||||
cloudsValidateDefinition(&_clouds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sceneryGetClouds(CloudsDefinition* clouds)
|
void sceneryGetClouds(CloudsDefinition* clouds)
|
||||||
{
|
{
|
||||||
cloudsCopyDefinition(&_clouds, clouds);
|
CloudsDefinitionClass.copy(_clouds, clouds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scenerySetTerrain(TerrainDefinition* terrain)
|
void scenerySetTerrain(TerrainDefinition* terrain)
|
||||||
|
@ -182,7 +180,7 @@ static RayCastingResult _rayWalking(Renderer* renderer, Vector3 location, Vector
|
||||||
|
|
||||||
result.hit = 1;
|
result.hit = 1;
|
||||||
result.hit_location = v3Add(location, v3Scale(direction, 1000.0));
|
result.hit_location = v3Add(location, v3Scale(direction, 1000.0));
|
||||||
result.hit_color = renderer->applyClouds(renderer, sky_color, location, result.hit_location);
|
result.hit_color = renderer->clouds->getColor(renderer, sky_color, location, result.hit_location);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -198,11 +196,6 @@ static Color _applyTextures(Renderer* renderer, Vector3 location, double precisi
|
||||||
return texturesGetColor(&_textures, renderer, location.x, location.z, precision);
|
return texturesGetColor(&_textures, renderer, location.x, location.z, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Color _applyClouds(Renderer* renderer, Color base, Vector3 start, Vector3 end)
|
|
||||||
{
|
|
||||||
return cloudsApply(&_clouds, base, renderer, start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Vector3 _projectPoint(Renderer* renderer, Vector3 point)
|
static Vector3 _projectPoint(Renderer* renderer, Vector3 point)
|
||||||
{
|
{
|
||||||
return cameraProject(&renderer->render_camera, renderer, point);
|
return cameraProject(&renderer->render_camera, renderer, point);
|
||||||
|
@ -236,13 +229,13 @@ Renderer* sceneryCreateStandardRenderer()
|
||||||
result->rayWalking = _rayWalking;
|
result->rayWalking = _rayWalking;
|
||||||
result->getWaterHeightInfo = _getWaterHeightInfo;
|
result->getWaterHeightInfo = _getWaterHeightInfo;
|
||||||
result->applyTextures = _applyTextures;
|
result->applyTextures = _applyTextures;
|
||||||
result->applyClouds = _applyClouds;
|
|
||||||
result->projectPoint = _projectPoint;
|
result->projectPoint = _projectPoint;
|
||||||
result->unprojectPoint = _unprojectPoint;
|
result->unprojectPoint = _unprojectPoint;
|
||||||
result->getPrecision = _getPrecision;
|
result->getPrecision = _getPrecision;
|
||||||
|
|
||||||
AtmosphereRendererClass.bind(result, _atmosphere);
|
AtmosphereRendererClass.bind(result, _atmosphere);
|
||||||
TerrainRendererClass.bind(result, _terrain);
|
TerrainRendererClass.bind(result, _terrain);
|
||||||
|
CloudsRendererClass.bind(result, _clouds);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
|
|
||||||
#include "tools/pack.h"
|
#include "tools/pack.h"
|
||||||
#include "atmosphere/public.h"
|
#include "atmosphere/public.h"
|
||||||
|
#include "clouds/public.h"
|
||||||
#include "terrain/public.h"
|
#include "terrain/public.h"
|
||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
#include "clouds.h"
|
|
||||||
#include "textures.h"
|
#include "textures.h"
|
||||||
#include "water.h"
|
#include "water.h"
|
||||||
#include "renderer.h"
|
#include "renderer.h"
|
||||||
|
|
|
@ -120,7 +120,7 @@ static Color _getFinalColor(Renderer* renderer, Vector3 location, double precisi
|
||||||
|
|
||||||
/* TODO Factorize this in scenery renderer */
|
/* TODO Factorize this in scenery renderer */
|
||||||
color = renderer->atmosphere->applyAerialPerspective(renderer, location, color);
|
color = renderer->atmosphere->applyAerialPerspective(renderer, location, color);
|
||||||
color = renderer->applyClouds(renderer, color, renderer->camera_location, location);
|
color = renderer->clouds->getColor(renderer, color, renderer->camera_location, location);
|
||||||
|
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
@ -193,7 +193,7 @@ static RayCastingResult _castRay(Renderer* renderer, Vector3 start, Vector3 dire
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _alterLight(LightDefinition* light, Vector3 location, Renderer* renderer)
|
static int _alterLight(Renderer* renderer, LightDefinition* light, Vector3 location)
|
||||||
{
|
{
|
||||||
TerrainDefinition* definition = renderer->terrain->definition;
|
TerrainDefinition* definition = renderer->terrain->definition;
|
||||||
Vector3 inc_vector, direction_to_light;
|
Vector3 inc_vector, direction_to_light;
|
||||||
|
|
|
@ -120,6 +120,23 @@ void colorMask(Color* base, Color* mask)
|
||||||
|
|
||||||
double colorNormalize(Color* col)
|
double colorNormalize(Color* col)
|
||||||
{
|
{
|
||||||
|
assert(col->r >= 0.0);
|
||||||
|
assert(col->g >= 0.0);
|
||||||
|
assert(col->b >= 0.0);
|
||||||
|
assert(col->a >= 0.0);
|
||||||
|
#ifdef isnan
|
||||||
|
assert(!isnan(col->r));
|
||||||
|
assert(!isnan(col->g));
|
||||||
|
assert(!isnan(col->b));
|
||||||
|
assert(!isnan(col->a));
|
||||||
|
#endif
|
||||||
|
#ifdef isfinite
|
||||||
|
assert(isfinite(col->r));
|
||||||
|
assert(isfinite(col->g));
|
||||||
|
assert(isfinite(col->b));
|
||||||
|
assert(isfinite(col->a));
|
||||||
|
#endif
|
||||||
|
|
||||||
if (col->r > 1.0)
|
if (col->r > 1.0)
|
||||||
{
|
{
|
||||||
col->r = 1.0;
|
col->r = 1.0;
|
||||||
|
@ -136,10 +153,6 @@ double colorNormalize(Color* col)
|
||||||
/*double max = colorGetValue(col);
|
/*double max = colorGetValue(col);
|
||||||
|
|
||||||
assert(max >= 0.0);
|
assert(max >= 0.0);
|
||||||
assert(col->r >= 0.0);
|
|
||||||
assert(col->g >= 0.0);
|
|
||||||
assert(col->b >= 0.0);
|
|
||||||
assert(col->a >= 0.0);
|
|
||||||
|
|
||||||
if (max > 1.0)
|
if (max > 1.0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -97,7 +97,7 @@ void lightingPushLight(LightStatus* status, LightDefinition* light)
|
||||||
{
|
{
|
||||||
LightFilterCallback callback = manager->callbacks[i];
|
LightFilterCallback callback = manager->callbacks[i];
|
||||||
LightDefinition temp = final;
|
LightDefinition temp = final;
|
||||||
if (callback.filter(&temp, status->location, callback.data))
|
if (callback.filter(callback.data, &temp, status->location))
|
||||||
{
|
{
|
||||||
final = temp;
|
final = temp;
|
||||||
}
|
}
|
||||||
|
@ -147,6 +147,7 @@ Color lightingApplyOneLight(LightDefinition* light, Vector3 eye, Vector3 locatio
|
||||||
|
|
||||||
/* diffused light */
|
/* diffused light */
|
||||||
double diffuse = v3Dot(direction_inv, normal);
|
double diffuse = v3Dot(direction_inv, normal);
|
||||||
|
diffuse = (diffuse + (1.0 - normal_norm)) / (1.0 + (1.0 - normal_norm));
|
||||||
if (diffuse > 0.0)
|
if (diffuse > 0.0)
|
||||||
{
|
{
|
||||||
result.r += diffuse * material->base.r * light_color.r;
|
result.r += diffuse * material->base.r * light_color.r;
|
||||||
|
|
|
@ -24,7 +24,7 @@ typedef struct
|
||||||
int altered; /* Should the light be filtered or masked (by atmosphere, water, ground, clouds...) */
|
int altered; /* Should the light be filtered or masked (by atmosphere, water, ground, clouds...) */
|
||||||
} LightDefinition;
|
} LightDefinition;
|
||||||
|
|
||||||
typedef int (*FuncLightingAlterLight)(LightDefinition* light, Vector3 at, void* data);
|
typedef int (*FuncLightingAlterLight)(void* data, LightDefinition* light, Vector3 at);
|
||||||
|
|
||||||
typedef struct LightingManager LightingManager;
|
typedef struct LightingManager LightingManager;
|
||||||
typedef struct LightStatus LightStatus;
|
typedef struct LightStatus LightStatus;
|
||||||
|
|
|
@ -352,7 +352,7 @@ WaterResult waterGetColorDetail(WaterDefinition* definition, Renderer* renderer,
|
||||||
|
|
||||||
color = renderer->applyLightingToSurface(renderer, location, normal, &material);
|
color = renderer->applyLightingToSurface(renderer, location, normal, &material);
|
||||||
color = renderer->atmosphere->applyAerialPerspective(renderer, location, color);
|
color = renderer->atmosphere->applyAerialPerspective(renderer, location, color);
|
||||||
color = renderer->applyClouds(renderer, color, renderer->camera_location, location);
|
color = renderer->clouds->getColor(renderer, color, renderer->camera_location, location);
|
||||||
|
|
||||||
result.base = definition->material.base;
|
result.base = definition->material.base;
|
||||||
result.final = color;
|
result.final = color;
|
||||||
|
|
Loading…
Reference in a new issue