paysages : Texture ranges replaced with curves.

git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@370 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
Michaël Lemaire 2012-07-02 15:35:10 +00:00 committed by ThunderK
parent 2579d17f4a
commit b15b6c7d80
9 changed files with 82 additions and 289 deletions

View file

@ -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).

1
TODO
View file

@ -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.

View file

@ -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);
}

View file

@ -11,6 +11,7 @@ class FormTextures : public BaseForm
public:
explicit FormTextures(QWidget *parent = 0);
~FormTextures();
protected:
virtual void layerAddedEvent();

View file

@ -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);

View file

@ -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)
{

View file

@ -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);

View file

@ -1,10 +1,12 @@
#include "zone.h"
#include <string.h>
#include <stdlib.h>
#include <math.h>
#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)
{

View file

@ -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);