diff --git a/gui_qt/basepreview.cpp b/gui_qt/basepreview.cpp index 9a357cb..20a10c2 100644 --- a/gui_qt/basepreview.cpp +++ b/gui_qt/basepreview.cpp @@ -5,8 +5,9 @@ #include #include #include -#include +#include #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; } diff --git a/gui_qt/formclouds.cpp b/gui_qt/formclouds.cpp index 39e0618..65cacf6 100644 --- a/gui_qt/formclouds.cpp +++ b/gui_qt/formclouds.cpp @@ -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); diff --git a/gui_qt/paysages-qt.pro b/gui_qt/paysages-qt.pro index 803005e..337f8a2 100644 --- a/gui_qt/paysages-qt.pro +++ b/gui_qt/paysages-qt.pro @@ -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) diff --git a/lib_paysages/Makefile b/lib_paysages/Makefile index 744e131..b107f59 100644 --- a/lib_paysages/Makefile +++ b/lib_paysages/Makefile @@ -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} diff --git a/lib_paysages/clouds.c b/lib_paysages/clouds.c index c89932a..d23fc39 100644 --- a/lib_paysages/clouds.c +++ b/lib_paysages/clouds.c @@ -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) { diff --git a/lib_paysages/clouds.h b/lib_paysages/clouds.h index 44c8b7f..c2af5f3 100644 --- a/lib_paysages/clouds.h +++ b/lib_paysages/clouds.h @@ -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); diff --git a/lib_paysages/noise.c b/lib_paysages/noise.c index 2096d0a..f758b0c 100644 --- a/lib_paysages/noise.c +++ b/lib_paysages/noise.c @@ -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; diff --git a/lib_paysages/noise.h b/lib_paysages/noise.h index a2d2823..1aed3a6 100644 --- a/lib_paysages/noise.h +++ b/lib_paysages/noise.h @@ -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); diff --git a/lib_paysages/pack.c b/lib_paysages/pack.c index 7ffc6b1..0250866 100644 --- a/lib_paysages/pack.c +++ b/lib_paysages/pack.c @@ -134,7 +134,7 @@ void packWriteInt(PackStream* stream, int* value) void packReadInt(PackStream* stream, int* value) { int read; - + read = fscanf(stream->fd, "%d;", value); assert(read == 1); } diff --git a/lib_paysages/scenery.c b/lib_paysages/scenery.c index 8ab70ad..a6a5abc 100644 --- a/lib_paysages/scenery.c +++ b/lib_paysages/scenery.c @@ -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) diff --git a/lib_paysages/system.c b/lib_paysages/system.c index e06b8fa..08fa8a9 100644 --- a/lib_paysages/system.c +++ b/lib_paysages/system.c @@ -1,7 +1,9 @@ #include "system.h" #include -/*#define DEBUG_ONETHREAD 1*/ +#ifndef NDEBUG +#define DEBUG_ONETHREAD 1 +#endif #ifdef WIN32 #include diff --git a/lib_paysages/system.h b/lib_paysages/system.h index 0fefec9..8fee86b 100644 --- a/lib_paysages/system.h +++ b/lib_paysages/system.h @@ -1,18 +1,20 @@ #ifndef _PAYSAGES_SYSTEM_H_ #define _PAYSAGES_SYSTEM_H_ -#include - #ifdef __cplusplus extern "C" { #endif -typedef GThread Thread; typedef void*(*ThreadFunction)(void* data); void systemInit(); int systemGetCoreCount(); +#ifdef HAVE_GLIB +#include + +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 }