paysages: Changed clouds layer definition from min-max to min-thickness + small improvements.

git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@369 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
Michaël Lemaire 2012-07-01 13:27:57 +00:00 committed by ThunderK
parent b067dbebba
commit 2579d17f4a
12 changed files with 105 additions and 101 deletions

View file

@ -5,8 +5,9 @@
#include <QPainter>
#include <QTimer>
#include <QWheelEvent>
#include <qt4/QtGui/qlabel.h>
#include <QLabel>
#include "tools.h"
#include "../lib_paysages/system.h"
/*************** PreviewChunk ***************/
class PreviewChunk
@ -132,11 +133,7 @@ void PreviewDrawingThread::run()
/*************** PreviewDrawingManager ***************/
PreviewDrawingManager::PreviewDrawingManager()
{
_thread_count = QThread::idealThreadCount();
if (_thread_count < 1)
{
_thread_count = 1;
}
_thread_count = systemGetCoreCount();
_lastRendered = NULL;
}

View file

@ -28,7 +28,7 @@ protected:
QColor getColor(double x, double y)
{
Vector3 eye, look;
Color color_layer, result;
Color color_layer;
eye.x = 0.0;
eye.y = scaling;
@ -38,10 +38,8 @@ protected:
look.z = 1.0;
look = v3Normalize(look);
result = COLOR_BLUE;
color_layer = cloudsGetLayerColor(&_preview_layer, &_renderer, eye, v3Add(eye, v3Scale(look, 1000.0)));
colorMask(&result, &color_layer);
return colorToQColor(result);
color_layer = cloudsApplyLayer(&_preview_layer, COLOR_BLUE, &_renderer, eye, v3Add(eye, v3Scale(look, 1000.0)));
return colorToQColor(color_layer);
}
void updateData()
{
@ -85,33 +83,32 @@ public:
_renderer.customData[0] = &_preview_layer;
_renderer.customData[1] = &_lighting;
configScaling(1.0, 4.0, 0.2, 2.0);
configScaling(0.5, 2.0, 0.1, 2.0);
}
protected:
QColor getColor(double x, double y)
{
Vector3 start, end;
Color color_layer, result;
Color color_layer;
start.x = x * _preview_layer.ymax;
start.y = -y * _preview_layer.ymax;
start.z = _preview_layer.ymax;
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.ymax;
end.y = -y * _preview_layer.ymax;
end.z = -_preview_layer.ymax;
end.x = x * _preview_layer.thickness * 0.5;
end.y = -y * _preview_layer.thickness * 0.5;
end.z = -_preview_layer.thickness * 0.5;
result = COLOR_BLUE;
color_layer = cloudsGetLayerColor(&_preview_layer, &_renderer, start, end);
colorMask(&result, &color_layer);
return colorToQColor(result);
color_layer = cloudsApplyLayer(&_preview_layer, COLOR_BLUE, &_renderer, start, end);
return colorToQColor(color_layer);
}
void updateData()
{
cloudsLayerCopyDefinition(&_layer, &_preview_layer);
_preview_layer.ymax = (_preview_layer.ymax - _preview_layer.ymin) / 2.0;
_preview_layer.ymin = -_preview_layer.ymin;
curveClear(_preview_layer.coverage_by_altitude);
//noiseForceValue(_preview_layer.shape_noise, 1.0);
_preview_layer.lower_altitude = -_preview_layer.thickness * 0.5;
//curveClear(_preview_layer.coverage_by_altitude);
_preview_layer.base_coverage = 1.0;
_preview_layer._custom_coverage = _coverageFunc;
}
private:
@ -121,15 +118,18 @@ private:
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->ymax)
if (dist >= layer->thickness * 0.5)
{
return 0.0;
}
else
{
return 1.0 - dist / layer->ymax;
double density = 1.0 - dist / (layer->thickness * 0.5);
return (density < coverage) ? density : coverage;
}
}
@ -152,10 +152,10 @@ FormClouds::FormClouds(QWidget *parent):
_layer = cloudsLayerCreateDefinition();
addPreview(new PreviewCloudsCoverage(parent), tr("Layer coverage (no lighting)"));
addPreview(new PreviewCloudsColor(parent), tr("Color and lighting"));
addPreview(new PreviewCloudsColor(parent), tr("Appearance"));
addInputDouble(tr("Lower altitude"), &_layer.ymin, -10.0, 50.0, 0.5, 5.0);
addInputDouble(tr("Upper altitude"), &_layer.ymax, -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("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);

View file

@ -10,6 +10,7 @@ CONFIG -= release
CONFIG += $$BUILDMODE
release:DEFINES += NDEBUG
release:QMAKE_CXXFLAGS += -Wno-unused-variable -Wno-unused-parameter -Wno-unused-but-set-variable
LIBS += -lGLU
unix:LIBS += -L$$DESTDIR -lpaysages
@ -19,5 +20,5 @@ HEADERS += $$files(*.h) $$files(../lib_paysages/*.h) $$files(../lib_paysages/sha
SOURCES += $$files(*.cpp)
TRANSLATIONS = ../i18n/paysages_fr.ts
system(lupdate paysages-qt.pro)
system(lrelease $$TRANSLATIONS)
#system(lupdate paysages-qt.pro)
#system(lrelease $$TRANSLATIONS)

View file

@ -5,7 +5,7 @@ SOURCES = $(wildcard *.c)
OBJECTS = ${SOURCES:%.c=${OBJPATH}/%.o}
HEADERS = $(wildcard shared/*.h *.h)
RESULT = ${BUILDPATH}/libpaysages.so
CC_FLAGS = -Wall -fPIC $(shell pkg-config --cflags glib-2.0 gthread-2.0)
CC_FLAGS = -Wall -fPIC $(shell pkg-config --cflags glib-2.0 gthread-2.0) -DHAVE_GLIB=1
CC_LDFLAGS = $(shell pkg-config --libs glib-2.0 gthread-2.0) -lIL -lILU
ifeq ($(BUILDMODE),debug)
@ -13,7 +13,7 @@ ifeq ($(BUILDMODE),debug)
CC_LDFLAGS += -g -pg
endif
ifeq ($(BUILDMODE),release)
CC_FLAGS += -O3 -DNDEBUG
CC_FLAGS += -O3 -DNDEBUG -Wno-unused-variable -Wno-unused-but-set-variable
endif
all:prepare ${RESULT}

View file

@ -9,6 +9,8 @@
#include "tools.h"
#include "shared/types.h"
#define MAX_SEGMENT_COUNT 30
typedef struct
{
Vector3 start;
@ -39,8 +41,8 @@ void cloudsSave(PackStream* stream, CloudsDefinition* definition)
{
layer = definition->layers + i;
packWriteDouble(stream, &layer->ymin);
packWriteDouble(stream, &layer->ymax);
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);
@ -71,8 +73,8 @@ void cloudsLoad(PackStream* stream, CloudsDefinition* definition)
{
layer = definition->layers + cloudsAddLayer(definition);
packReadDouble(stream, &layer->ymin);
packReadDouble(stream, &layer->ymax);
packReadDouble(stream, &layer->lower_altitude);
packReadDouble(stream, &layer->thickness);
curveLoad(stream, layer->coverage_by_altitude);
noiseLoadGenerator(stream, layer->shape_noise);
noiseLoadGenerator(stream, layer->edge_noise);
@ -132,13 +134,13 @@ void cloudsValidateDefinition(CloudsDefinition* definition)
static double _standardCoverageFunc(CloudsLayerDefinition* layer, Vector3 position)
{
if (position.y > layer->ymax || position.y < layer->ymin)
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->ymin) / (layer->ymax - layer->ymin));
return layer->base_coverage * curveGetValue(layer->coverage_by_altitude, (position.y - layer->lower_altitude) / layer->thickness);
}
}
@ -146,8 +148,8 @@ CloudsLayerDefinition cloudsLayerCreateDefinition()
{
CloudsLayerDefinition result;
result.ymin = 4.0;
result.ymax = 10.0;
result.lower_altitude = 4.0;
result.thickness = 6.0;
result.coverage_by_altitude = curveCreate();
curveQuickAddPoint(result.coverage_by_altitude, 0.0, 0.0);
curveQuickAddPoint(result.coverage_by_altitude, 0.3, 1.0);
@ -164,8 +166,8 @@ CloudsLayerDefinition cloudsLayerCreateDefinition()
result.lighttraversal = 7.0;
result.minimumlight = 0.4;
result.shape_scaling = 3.5;
result.edge_scaling = 0.1;
result.edge_length = 0.25;
result.edge_scaling = 0.07;
result.edge_length = 0.2;
result.base_coverage = 0.35;
result.shape_noise = noiseCreateGenerator();
noiseGenerateBaseNoise(result.shape_noise, 200000);
@ -353,48 +355,48 @@ static int _optimizeSearchLimits(CloudsLayerDefinition* layer, Vector3* start, V
{
Vector3 diff;
if (start->y > layer->ymax)
if (start->y > layer->lower_altitude + layer->thickness)
{
if (end->y >= layer->ymax)
if (end->y >= layer->lower_altitude + layer->thickness)
{
return 0;
}
else
{
diff = v3Sub(*end, *start);
*start = v3Add(*start, v3Scale(diff, (layer->ymax - start->y) / diff.y));
if (end->y < layer->ymin)
*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->ymin - end->y) / diff.y));
*end = v3Add(*end, v3Scale(diff, (layer->lower_altitude - end->y) / diff.y));
}
}
}
else if (start->y < layer->ymin)
else if (start->y < layer->lower_altitude)
{
if (end->y <= layer->ymin)
if (end->y <= layer->lower_altitude)
{
return 0;
}
else
{
diff = v3Sub(*end, *start);
*start = v3Add(*start, v3Scale(diff, (layer->ymin - start->y) / diff.y));
if (end->y > layer->ymax)
*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->ymax - end->y) / diff.y));
*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->ymax)
if (end->y > layer->thickness)
{
*end = v3Add(*start, v3Scale(diff, (layer->ymax - start->y) / diff.y));
*end = v3Add(*start, v3Scale(diff, (layer->lower_altitude + layer->thickness - start->y) / diff.y));
}
else if (end->y < layer->ymin)
else if (end->y < layer->lower_altitude)
{
*end = v3Add(*start, v3Scale(diff, (layer->ymin - start->y) / diff.y));
*end = v3Add(*start, v3Scale(diff, (layer->lower_altitude - start->y) / diff.y));
}
}
@ -460,6 +462,11 @@ static int _findSegments(CloudsLayerDefinition* definition, Renderer* renderer,
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)
@ -506,7 +513,7 @@ static int _findSegments(CloudsLayerDefinition* definition, Renderer* renderer,
step = v3Scale(direction, (noise_distance > -render_precision) ? render_precision : -noise_distance);
}
}
} while (inside || (walker.y <= definition->ymax + 0.001 && walker.y >= definition->ymin - 0.001 && current_total_length < max_total_length && current_inside_length < max_inside_length));
} 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;
@ -543,85 +550,76 @@ static Color _applyLayerLighting(CloudsLayerDefinition* definition, Renderer* re
return col1;
}
Color cloudsGetLayerColor(CloudsLayerDefinition* definition, Renderer* renderer, Vector3 start, Vector3 end)
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 result, col;
CloudSegment segments[20];
Color col;
CloudSegment segments[MAX_SEGMENT_COUNT];
if (!_optimizeSearchLimits(definition, &start, &end))
{
return COLOR_TRANSPARENT;
return base;
}
direction = v3Sub(end, start);
max_length = v3Norm(direction);
direction = v3Normalize(direction);
result = COLOR_TRANSPARENT;
detail = renderer->getPrecision(renderer, start) / definition->shape_scaling;
segment_count = _findSegments(definition, renderer, start, direction, detail, 20, definition->transparencydepth, max_length, &inside_length, &total_length, segments);
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->applyAtmosphere(renderer, start, col);
col.a = (segments[i].length >= definition->transparencydepth) ? 1.0 : (segments[i].length / definition->transparencydepth);
colorMask(&result, &col);
colorMask(&base, &col);
}
if (inside_length >= definition->transparencydepth)
{
col.a = 1.0;
}
if (result.a > 0.000001)
{
result = renderer->applyAtmosphere(renderer, start, result);
}
return result;
return base;
}
static int _cmpLayer(const void* layer1, const void* layer2)
{
return (((CloudsLayerDefinition*)layer1)->ymin > ((CloudsLayerDefinition*)layer2)->ymin) ? -1 : 1;
return (((CloudsLayerDefinition*)layer1)->lower_altitude > ((CloudsLayerDefinition*)layer2)->lower_altitude) ? -1 : 1;
}
Color cloudsGetColor(CloudsDefinition* definition, Renderer* renderer, Vector3 start, Vector3 end)
Color cloudsApply(CloudsDefinition* definition, Color base, Renderer* renderer, Vector3 start, Vector3 end)
{
int i;
Color layer_color, result;
Color layer_color;
CloudsLayerDefinition layers[CLOUDS_MAX_LAYERS];
if (definition->nblayers < 1)
{
return COLOR_TRANSPARENT;
return base;
}
result = COLOR_TRANSPARENT;
memcpy(layers, definition->layers, sizeof(CloudsLayerDefinition) * definition->nblayers);
qsort(layers, definition->nblayers, sizeof(CloudsLayerDefinition), _cmpLayer);
for (i = 0; i < definition->nblayers; i++)
{
layer_color = cloudsGetLayerColor(layers + i, renderer, start, end);
if (layer_color.a > 0.000001)
{
colorMask(&result, &layer_color);
}
base = cloudsApplyLayer(layers + i, base, renderer, start, end);
}
return result;
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[20];
CloudSegment segments[MAX_SEGMENT_COUNT];
_optimizeSearchLimits(definition, &location, &light_location);
_findSegments(definition, renderer, location, direction_to_light, 0.1, 20, definition->lighttraversal, v3Norm(v3Sub(light_location, location)), &inside_depth, &total_depth, segments);
_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)
{

View file

@ -18,8 +18,8 @@ typedef double (*CloudCoverageFunc)(CloudsLayerDefinition* definition, Vector3 p
struct CloudsLayerDefinition
{
double ymin;
double ymax;
double lower_altitude;
double thickness;
double base_coverage;
Curve* coverage_by_altitude;
NoiseGenerator* shape_noise;
@ -61,8 +61,8 @@ CloudsLayerDefinition* cloudsGetLayer(CloudsDefinition* definition, int layer);
int cloudsAddLayer(CloudsDefinition* definition);
void cloudsDeleteLayer(CloudsDefinition* definition, int layer);
Color cloudsGetLayerColor(CloudsLayerDefinition* definition, Renderer* renderer, Vector3 start, Vector3 end);
Color cloudsGetColor(CloudsDefinition* definition, Renderer* renderer, Vector3 start, Vector3 end);
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);

View file

@ -175,6 +175,13 @@ void noiseGenerateBaseNoise(NoiseGenerator* generator, int size)
generator->size3 = (int)floor(cbrt((double)size));
}
void noiseForceValue(NoiseGenerator* generator, double value)
{
noiseClearLevels(generator);
generator->height_offset = value;
noiseAddLevelSimple(generator, 1.0, 0.0); /* FIXME Should not be needed */
}
int noiseGetBaseSize(NoiseGenerator* generator)
{
return generator->size1;

View file

@ -30,6 +30,7 @@ void noiseLoadGenerator(PackStream* stream, NoiseGenerator* perlin);
void noiseCopy(NoiseGenerator* source, NoiseGenerator* destination);
void noiseValidate(NoiseGenerator* generator);
void noiseGenerateBaseNoise(NoiseGenerator* generator, int size);
void noiseForceValue(NoiseGenerator* generator, double value);
int noiseGetBaseSize(NoiseGenerator* generator);
double noiseGetMaxValue(NoiseGenerator* generator);
int noiseGetLevelCount(NoiseGenerator* generator);

View file

@ -321,12 +321,7 @@ static Color _applyAtmosphere(Renderer* renderer, Vector3 location, Color base)
static Color _applyClouds(Renderer* renderer, Color base, Vector3 start, Vector3 end)
{
Color clouds;
clouds = cloudsGetColor(&_clouds, renderer, start, end);
colorMask(&base, &clouds);
return base;
return cloudsApply(&_clouds, base, renderer, start, end);
}
static Vector3 _projectPoint(Renderer* renderer, Vector3 point)

View file

@ -1,7 +1,9 @@
#include "system.h"
#include <unistd.h>
/*#define DEBUG_ONETHREAD 1*/
#ifndef NDEBUG
#define DEBUG_ONETHREAD 1
#endif
#ifdef WIN32
#include <windows.h>

View file

@ -1,18 +1,20 @@
#ifndef _PAYSAGES_SYSTEM_H_
#define _PAYSAGES_SYSTEM_H_
#include <glib.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef GThread Thread;
typedef void*(*ThreadFunction)(void* data);
void systemInit();
int systemGetCoreCount();
#ifdef HAVE_GLIB
#include <glib.h>
typedef GThread Thread;
static inline Thread* threadCreate(ThreadFunction function, void* data)
{
GError* error;
@ -50,6 +52,7 @@ static inline void timeSleepMs(unsigned long ms)
{
g_usleep(ms * 1000);
}
#endif
#ifdef __cplusplus
}