From b15b6c7d807063949b677754faf780066789cbbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Mon, 2 Jul 2012 15:35:10 +0000 Subject: [PATCH] paysages : Texture ranges replaced with curves. git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@370 b1fd45b6-86a6-48da-8261-f70d1f35bdcc --- ChangeLog | 1 + TODO | 1 - gui_qt/formtextures.cpp | 78 +++---------- gui_qt/formtextures.h | 1 + lib_paysages/auto.c | 2 - lib_paysages/curve.c | 11 +- lib_paysages/curve.h | 1 + lib_paysages/zone.c | 250 +++++++--------------------------------- lib_paysages/zone.h | 26 ++--- 9 files changed, 82 insertions(+), 289 deletions(-) diff --git a/ChangeLog b/ChangeLog index 49fc2bb..08855fe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15,6 +15,7 @@ Scenery : * New cloud model with 2 noises : one for the global shape and one for edges. * Terrain shadows have been improved and are now configurable. * New sky model (based on Preetham's work). + * Textures ranges are now using curves. Rendering : * New texture model (perpendicular displacement and thickness). diff --git a/TODO b/TODO index 56fb8e7..e2fbca3 100644 --- a/TODO +++ b/TODO @@ -6,7 +6,6 @@ Technology Preview 2 : - InputInt doesn't honor small_step. - Keep skydome lights in cache for a render. - Add buttons to restore "auto" default values in tabs and dialogs. -- Replace zone ranges with curves (with curve input and curve dialog). - Interface for textures thickness, slope_range and thickness_transparency (and correct slider ranges). - Add "hardness to light" and shadow control ("minimum lighting") to material. - Add layer sorting/naming. diff --git a/gui_qt/formtextures.cpp b/gui_qt/formtextures.cpp index c3ecab2..1df5a48 100644 --- a/gui_qt/formtextures.cpp +++ b/gui_qt/formtextures.cpp @@ -9,14 +9,8 @@ static TextureLayerDefinition _layer; typedef struct { - double height_soft_min; - double height_hard_min; - double height_hard_max; - double height_soft_max; - double slope_soft_min; - double slope_hard_min; - double slope_hard_max; - double slope_soft_max; + Curve* height_curve; + Curve* slope_curve; } TextureSupp; static TextureSupp _supp; @@ -133,6 +127,8 @@ FormTextures::FormTextures(QWidget *parent): { _definition = texturesCreateDefinition(); _layer = texturesLayerCreateDefinition(); + _supp.height_curve = curveCreate(); + _supp.slope_curve = curveCreate(); previewCoverage = new PreviewTexturesCoverage(this); previewColor = new PreviewTexturesColor(this); @@ -143,19 +139,20 @@ FormTextures::FormTextures(QWidget *parent): addInputDouble(tr("Surface noise height"), &_layer.bump_height, 0.0, 0.5, 0.001, 0.05); addInputDouble(tr("Surface noise scaling"), &_layer.bump_scaling, 0.01, 1.0, 0.01, 0.1); addInputMaterial(tr("Material"), &_layer.material); - - addInputDouble(tr("Hard minimal height"), &_supp.height_hard_min, -20.0, 20.0, 0.1, 1.0); - addInputDouble(tr("Soft minimal height"), &_supp.height_soft_min, -20.0, 20.0, 0.1, 1.0); - addInputDouble(tr("Soft maximal height"), &_supp.height_soft_max, -20.0, 20.0, 0.1, 1.0); - addInputDouble(tr("Hard maximal height"), &_supp.height_hard_max, -20.0, 20.0, 0.1, 1.0); - addInputDouble(tr("Hard minimal slope"), &_supp.slope_hard_min, 0.0, 5.0, 0.05, 0.5); - addInputDouble(tr("Soft minimal slope"), &_supp.slope_soft_min, 0.0, 5.0, 0.05, 0.5); - addInputDouble(tr("Soft maximal slope"), &_supp.slope_soft_max, 0.0, 5.0, 0.05, 0.5); - addInputDouble(tr("Hard maximal slope"), &_supp.slope_hard_max, 0.0, 5.0, 0.05, 0.5); + addInputCurve(tr("Coverage by altitude"), _supp.height_curve, -20.0, 20.0, 0.0, 1.0, tr("Terrain altitude"), tr("Texture coverage")); + addInputCurve(tr("Coverage by slope"), _supp.slope_curve, 0.0, 5.0, 0.0, 1.0, tr("Terrain slope"), tr("Texture coverage")); revertConfig(); } +FormTextures::~FormTextures() +{ + texturesDeleteDefinition(&_definition); + texturesLayerDeleteDefinition(&_layer); + curveDelete(_supp.height_curve); + curveDelete(_supp.slope_curve); +} + void FormTextures::revertConfig() { sceneryGetTextures(&_definition); @@ -171,29 +168,11 @@ void FormTextures::applyConfig() void FormTextures::configChangeEvent() { - ZoneRangeCondition range; - texturesLayerCopyDefinition(&_layer, texturesGetLayer(&_definition, currentLayer())); - if (zoneGetHeightRangeCount(_layer.zone) > 0) - { - range.value = 1.0; - range.softmin = _supp.height_soft_min; - range.hardmin = _supp.height_hard_min; - range.hardmax = _supp.height_hard_max; - range.softmax = _supp.height_soft_max; - zoneSetHeightRange(_layer.zone, 0, &range); - } - if (zoneGetSlopeRangeCount(_layer.zone) > 0) - { - range.value = 1.0; - range.softmin = _supp.slope_soft_min; - range.hardmin = _supp.slope_hard_min; - range.hardmax = _supp.slope_hard_max; - range.softmax = _supp.slope_soft_max; - zoneSetSlopeRange(_layer.zone, 0, &range); - } - + zoneSetHeightCurve(_layer.zone, _supp.height_curve); + zoneSetSlopeCurve(_layer.zone, _supp.slope_curve); + texturesValidateDefinition(&_definition); BaseForm::configChangeEvent(); } @@ -215,29 +194,10 @@ void FormTextures::layerDeletedEvent(int layer) void FormTextures::layerSelectedEvent(int layer) { - ZoneRangeCondition range; - texturesLayerCopyDefinition(texturesGetLayer(&_definition, layer), &_layer); - if (zoneGetHeightRangeCount(_layer.zone) == 0) - { - zoneAddHeightRange(_layer.zone); - } - zoneGetHeightRange(_layer.zone, 0, &range); - _supp.height_soft_min = range.softmin; - _supp.height_hard_min = range.hardmin; - _supp.height_hard_max = range.hardmax; - _supp.height_soft_max = range.softmax; - - if (zoneGetSlopeRangeCount(_layer.zone) == 0) - { - zoneAddSlopeRange(_layer.zone); - } - zoneGetSlopeRange(_layer.zone, 0, &range); - _supp.slope_soft_min = range.softmin; - _supp.slope_hard_min = range.hardmin; - _supp.slope_hard_max = range.hardmax; - _supp.slope_soft_max = range.softmax; + zoneGetHeightCurve(_layer.zone, _supp.height_curve); + zoneGetSlopeCurve(_layer.zone, _supp.slope_curve); BaseForm::layerSelectedEvent(layer); } diff --git a/gui_qt/formtextures.h b/gui_qt/formtextures.h index 28822f0..f5beb39 100644 --- a/gui_qt/formtextures.h +++ b/gui_qt/formtextures.h @@ -11,6 +11,7 @@ class FormTextures : public BaseForm public: explicit FormTextures(QWidget *parent = 0); + ~FormTextures(); protected: virtual void layerAddedEvent(); diff --git a/lib_paysages/auto.c b/lib_paysages/auto.c index 43996ce..e5fcfab 100644 --- a/lib_paysages/auto.c +++ b/lib_paysages/auto.c @@ -147,8 +147,6 @@ void autoGenRealisticLandscape(int seed) /* Textures */ textures = texturesCreateDefinition(); texture = texturesGetLayer(&textures, texturesAddLayer(&textures)); - zoneAddHeightRangeQuick(texture->zone, 1.0, -20.0, -20.0, 20.0, 20.0); - zoneAddSlopeRangeQuick(texture->zone, 1.0, 0.0, 0.0, 5.0, 5.0); noiseGenerateBaseNoise(texture->bump_noise, 102400); noiseClearLevels(texture->bump_noise); noiseAddLevelsSimple(texture->bump_noise, 8, 1.0, 1.0); diff --git a/lib_paysages/curve.c b/lib_paysages/curve.c index c719531..c03bc8c 100644 --- a/lib_paysages/curve.c +++ b/lib_paysages/curve.c @@ -8,6 +8,7 @@ struct Curve { + double default_value; int nbpoints; CurvePoint points[MAX_NB_POINTS]; }; @@ -18,6 +19,7 @@ Curve* curveCreate() result = malloc(sizeof(Curve)); result->nbpoints = 0; + result->default_value = 0.0; return result; } @@ -36,6 +38,7 @@ void curveSave(PackStream* stream, Curve* curve) { int i; + packWriteDouble(stream, &curve->default_value); packWriteInt(stream, &curve->nbpoints); for (i = 0; i < curve->nbpoints; i++) { @@ -48,6 +51,7 @@ void curveLoad(PackStream* stream, Curve* curve) { int i; + packReadDouble(stream, &curve->default_value); packReadInt(stream, &curve->nbpoints); for (i = 0; i < curve->nbpoints; i++) { @@ -61,6 +65,11 @@ void curveClear(Curve* curve) curve->nbpoints = 0; } +void curveSetDefault(Curve* curve, double value) +{ + curve->default_value = value; +} + int curveAddPoint(Curve* curve, CurvePoint* point) { if (curve->nbpoints < MAX_NB_POINTS) @@ -144,7 +153,7 @@ double curveGetValue(Curve* curve, double position) if (curve->nbpoints == 0) { - return 0.0; + return curve->default_value; } else if (curve->nbpoints == 1 || position <= curve->points[0].position) { diff --git a/lib_paysages/curve.h b/lib_paysages/curve.h index b5fd38d..b0aea0d 100644 --- a/lib_paysages/curve.h +++ b/lib_paysages/curve.h @@ -21,6 +21,7 @@ void curveSave(PackStream* stream, Curve* curve); void curveLoad(PackStream* stream, Curve* curve); void curveClear(Curve* curve); +void curveSetDefault(Curve* curve, double value); int curveAddPoint(Curve* curve, CurvePoint* point); int curveQuickAddPoint(Curve* curve, double position, double value); int curveGetPointCount(Curve* curve); diff --git a/lib_paysages/zone.c b/lib_paysages/zone.c index 9f30f6f..2175f04 100644 --- a/lib_paysages/zone.c +++ b/lib_paysages/zone.c @@ -1,10 +1,12 @@ #include "zone.h" + +#include + #include #include #include "tools.h" -#define MAX_RANGES 20 #define MAX_CIRCLES 20 typedef struct @@ -17,11 +19,8 @@ typedef struct } Circle; struct Zone { - ZoneRangeCondition height_ranges[MAX_RANGES]; - int height_ranges_count; - - ZoneRangeCondition slope_ranges[MAX_RANGES]; - int slope_ranges_count; + Curve* value_by_height; + Curve* value_by_slope; Circle circles_included[MAX_CIRCLES]; int circles_included_count; @@ -35,8 +34,10 @@ Zone* zoneCreate() Zone* result; result = (Zone*)malloc(sizeof(Zone)); - result->height_ranges_count = 0; - result->slope_ranges_count = 0; + result->value_by_height = curveCreate(); + curveSetDefault(result->value_by_height, 1.0); + result->value_by_slope = curveCreate(); + curveSetDefault(result->value_by_slope, 1.0); result->circles_included_count = 0; result->circles_excluded_count = 0; @@ -45,6 +46,8 @@ Zone* zoneCreate() void zoneDelete(Zone* zone) { + curveDelete(zone->value_by_height); + curveDelete(zone->value_by_slope); free(zone); } @@ -52,25 +55,8 @@ void zoneSave(PackStream* stream, Zone* zone) { int i; - packWriteInt(stream, &zone->height_ranges_count); - for (i = 0; i < zone->height_ranges_count; i++) - { - packWriteDouble(stream, &zone->height_ranges[i].value); - packWriteDouble(stream, &zone->height_ranges[i].hardmin); - packWriteDouble(stream, &zone->height_ranges[i].softmin); - packWriteDouble(stream, &zone->height_ranges[i].softmax); - packWriteDouble(stream, &zone->height_ranges[i].hardmax); - } - - packWriteInt(stream, &zone->slope_ranges_count); - for (i = 0; i < zone->slope_ranges_count; i++) - { - packWriteDouble(stream, &zone->slope_ranges[i].value); - packWriteDouble(stream, &zone->slope_ranges[i].hardmin); - packWriteDouble(stream, &zone->slope_ranges[i].softmin); - packWriteDouble(stream, &zone->slope_ranges[i].softmax); - packWriteDouble(stream, &zone->slope_ranges[i].hardmax); - } + curveSave(stream, zone->value_by_height); + curveSave(stream, zone->value_by_slope); packWriteInt(stream, &zone->circles_included_count); for (i = 0; i < zone->circles_included_count; i++) @@ -97,25 +83,8 @@ void zoneLoad(PackStream* stream, Zone* zone) { int i; - packReadInt(stream, &zone->height_ranges_count); - for (i = 0; i < zone->height_ranges_count; i++) - { - packReadDouble(stream, &zone->height_ranges[i].value); - packReadDouble(stream, &zone->height_ranges[i].hardmin); - packReadDouble(stream, &zone->height_ranges[i].softmin); - packReadDouble(stream, &zone->height_ranges[i].softmax); - packReadDouble(stream, &zone->height_ranges[i].hardmax); - } - - packReadInt(stream, &zone->slope_ranges_count); - for (i = 0; i < zone->slope_ranges_count; i++) - { - packReadDouble(stream, &zone->slope_ranges[i].value); - packReadDouble(stream, &zone->slope_ranges[i].hardmin); - packReadDouble(stream, &zone->slope_ranges[i].softmin); - packReadDouble(stream, &zone->slope_ranges[i].softmax); - packReadDouble(stream, &zone->slope_ranges[i].hardmax); - } + curveLoad(stream, zone->value_by_height); + curveLoad(stream, zone->value_by_slope); packReadInt(stream, &zone->circles_included_count); for (i = 0; i < zone->circles_included_count; i++) @@ -140,7 +109,14 @@ void zoneLoad(PackStream* stream, Zone* zone) void zoneCopy(Zone* source, Zone* destination) { - *destination = *source; + curveCopy(source->value_by_height, destination->value_by_height); + curveCopy(source->value_by_slope, destination->value_by_slope); + + memcpy(destination->circles_included, source->circles_included, sizeof(Circle) * source->circles_included_count); + destination->circles_included_count = source->circles_included_count; + + memcpy(destination->circles_excluded, source->circles_excluded, sizeof(Circle) * source->circles_excluded_count); + destination->circles_excluded_count = source->circles_excluded_count; } void zoneIncludeCircleArea(Zone* zone, double value, double centerx, double centerz, double softradius, double hardradius) @@ -158,149 +134,40 @@ void zoneExcludeCircleArea(Zone* zone, double centerx, double centerz, double so /* TODO */ } -int zoneAddHeightRange(Zone* zone) +void zoneGetHeightCurve(Zone* zone, Curve* curve) { - if (zone->height_ranges_count < MAX_RANGES) - { - zone->height_ranges[zone->height_ranges_count].value = 0.0; - zone->height_ranges[zone->height_ranges_count].softmin = 0.0; - zone->height_ranges[zone->height_ranges_count].hardmin = 0.0; - zone->height_ranges[zone->height_ranges_count].hardmax = 0.0; - zone->height_ranges[zone->height_ranges_count].softmax = 0.0; - return zone->height_ranges_count++; - } - else - { - return -1; - } + curveCopy(zone->value_by_height, curve); } -int zoneGetHeightRangeCount(Zone* zone) +void zoneSetHeightCurve(Zone* zone, Curve* curve) { - return zone->height_ranges_count; + curveCopy(curve, zone->value_by_height); } -int zoneGetHeightRange(Zone* zone, int position, ZoneRangeCondition* range) +void zoneAddHeightRangeQuick(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax) { - if (position >= 0 && position < zone->height_ranges_count) - { - *range = zone->height_ranges[position]; - return 1; - } - else - { - return 0; - } + curveQuickAddPoint(zone->value_by_height, hardmin, 0.0); + curveQuickAddPoint(zone->value_by_height, softmin, value); + curveQuickAddPoint(zone->value_by_height, softmax, value); + curveQuickAddPoint(zone->value_by_height, hardmax, 0.0); } -int zoneSetHeightRange(Zone* zone, int position, ZoneRangeCondition* range) +void zoneGetSlopeCurve(Zone* zone, Curve* curve) { - if (position >= 0 && position < zone->height_ranges_count) - { - zone->height_ranges[position] = *range; - return 1; - } - else - { - return 0; - } + curveCopy(zone->value_by_slope, curve); } -int zoneAddHeightRangeQuick(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax) +void zoneSetSlopeCurve(Zone* zone, Curve* curve) { - ZoneRangeCondition range = {value, hardmin, softmin, softmax, hardmax}; - int position; - - position = zoneAddHeightRange(zone); - if (position >= 0) - { - zoneSetHeightRange(zone, position, &range); - } - return position; + curveCopy(curve, zone->value_by_slope); } -int zoneAddSlopeRange(Zone* zone) +void zoneAddSlopeRangeQuick(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax) { - if (zone->slope_ranges_count < MAX_RANGES) - { - zone->slope_ranges[zone->slope_ranges_count].value = 0.0; - zone->slope_ranges[zone->slope_ranges_count].softmin = 0.0; - zone->slope_ranges[zone->slope_ranges_count].hardmin = 0.0; - zone->slope_ranges[zone->slope_ranges_count].hardmax = 0.0; - zone->slope_ranges[zone->slope_ranges_count].softmax = 0.0; - return zone->slope_ranges_count++; - } - else - { - return -1; - } -} - -int zoneGetSlopeRangeCount(Zone* zone) -{ - return zone->slope_ranges_count; -} - -int zoneGetSlopeRange(Zone* zone, int position, ZoneRangeCondition* range) -{ - if (position >= 0 && position < zone->slope_ranges_count) - { - *range = zone->slope_ranges[position]; - return 1; - } - else - { - return 0; - } -} - -int zoneSetSlopeRange(Zone* zone, int position, ZoneRangeCondition* range) -{ - if (position >= 0 && position < zone->slope_ranges_count) - { - zone->slope_ranges[position] = *range; - return 1; - } - else - { - return 0; - } -} - -int zoneAddSlopeRangeQuick(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax) -{ - ZoneRangeCondition range = {value, hardmin, softmin, softmax, hardmax}; - int position; - - position = zoneAddSlopeRange(zone); - if (position >= 0) - { - zoneSetSlopeRange(zone, position, &range); - } - return position; -} - -static inline double _getRangeInfluence(ZoneRangeCondition range, double position) -{ - if (position >= range.hardmin && position <= range.hardmax) - { - if (position < range.softmin) - { - return range.value * (position - range.hardmin) / (range.softmin - range.hardmin); - } - else if (position > range.softmax) - { - return range.value * (range.hardmax - position) / (range.hardmax - range.softmax); - } - else - { - return range.value; - } - } - else - { - return 0.0; - } + curveQuickAddPoint(zone->value_by_slope, hardmin, 0.0); + curveQuickAddPoint(zone->value_by_slope, softmin, value); + curveQuickAddPoint(zone->value_by_slope, softmax, value); + curveQuickAddPoint(zone->value_by_slope, hardmax, 0.0); } static inline double _getCircleInfluence(Circle circle, Vector3 position) @@ -347,39 +214,8 @@ double zoneGetValue(Zone* zone, Vector3 location, Vector3 normal) value_circle = 1.0; } - if (zone->height_ranges_count > 0) - { - value_height = 0.0; - for (i = 0; i < zone->height_ranges_count; i++) - { - value = _getRangeInfluence(zone->height_ranges[i], location.y); - if (value > value_height) - { - value_height = value; - } - } - } - else - { - value_height = 1.0; - } - - if (zone->slope_ranges_count > 0) - { - value_steepness = 0.0; - for (i = 0; i < zone->slope_ranges_count; i++) - { - value = _getRangeInfluence(zone->slope_ranges[i], (1.0 - normal.y)); - if (value > value_steepness) - { - value_steepness = value; - } - } - } - else - { - value_steepness = 1.0; - } + value_height = curveGetValue(zone->value_by_height, location.y); + value_steepness = curveGetValue(zone->value_by_slope, (1.0 - normal.y)); if (value_steepness < value_height) { diff --git a/lib_paysages/zone.h b/lib_paysages/zone.h index c9c4b25..9596b9b 100644 --- a/lib_paysages/zone.h +++ b/lib_paysages/zone.h @@ -2,6 +2,7 @@ #define _PAYSAGES_ZONE_H_ #include "shared/types.h" +#include "curve.h" #include "pack.h" #ifdef __cplusplus @@ -10,15 +11,6 @@ extern "C" { typedef struct Zone Zone; -typedef struct -{ - double value; - double hardmin; - double softmin; - double softmax; - double hardmax; -} ZoneRangeCondition; - Zone* zoneCreate(); void zoneDelete(Zone* zone); void zoneSave(PackStream* stream, Zone* zone); @@ -27,17 +19,13 @@ void zoneCopy(Zone* source, Zone* destination); void zoneIncludeCircleArea(Zone* zone, double value, double centerx, double centerz, double softradius, double hardradius); void zoneExcludeCircleArea(Zone* zone, double centerx, double centerz, double softradius, double hardradius); -int zoneAddHeightRange(Zone* zone); -int zoneGetHeightRangeCount(Zone* zone); -int zoneGetHeightRange(Zone* zone, int position, ZoneRangeCondition* range); -int zoneSetHeightRange(Zone* zone, int position, ZoneRangeCondition* range); -int zoneAddHeightRangeQuick(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax); +void zoneGetHeightCurve(Zone* zone, Curve* curve); +void zoneSetHeightCurve(Zone* zone, Curve* curve); +void zoneAddHeightRangeQuick(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax); -int zoneAddSlopeRange(Zone* zone); -int zoneGetSlopeRangeCount(Zone* zone); -int zoneGetSlopeRange(Zone* zone, int position, ZoneRangeCondition* range); -int zoneSetSlopeRange(Zone* zone, int position, ZoneRangeCondition* range); -int zoneAddSlopeRangeQuick(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax); +void zoneGetSlopeCurve(Zone* zone, Curve* curve); +void zoneSetSlopeCurve(Zone* zone, Curve* curve); +void zoneAddSlopeRangeQuick(Zone* zone, double value, double hardmin, double softmin, double softmax, double hardmax); double zoneGetValue(Zone* zone, Vector3 location, Vector3 normal);