paysages : Added noise ridge factor.

git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@425 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
Michaël Lemaire 2012-08-27 20:40:35 +00:00 committed by ThunderK
parent 6cd571f92f
commit 163cca53a9
10 changed files with 174 additions and 44 deletions

View file

@ -8,6 +8,7 @@
#include <QSlider>
#include <QScrollArea>
#include <QPushButton>
#include <math.h>
/**************** Previews ****************/
class PreviewLevel:public BasePreview
@ -34,13 +35,13 @@ protected:
}
QColor getColor(double x, double y)
{
if ((_level >= 0) && (y > noiseGet1DLevel(_noise_preview, _level, x)))
if ((_level >= 0) && (-y > noiseGet1DLevel(_noise_preview, _level, x)))
{
return QColor(255, 255, 255);
return Qt::black;
}
else
{
return QColor(0, 0, 0);
return Qt::white;
}
}
private:
@ -66,13 +67,13 @@ protected:
}
QColor getColor(double x, double y)
{
if (y > noiseGet1DTotal(_noise_preview, x))
if (-y > noiseGet1DTotal(_noise_preview, x))
{
return QColor(255, 255, 255);
return Qt::black;
}
else
{
return QColor(0, 0, 0);
return Qt::white;
}
}
private:
@ -84,6 +85,7 @@ private:
DialogNoise::DialogNoise(QWidget *parent, NoiseGenerator* value):
DialogWithPreview(parent)
{
QWidget* function;
QWidget* previews;
QWidget* form;
QWidget* buttons;
@ -116,6 +118,23 @@ DialogNoise::DialogNoise(QWidget *parent, NoiseGenerator* value):
form->setLayout(new QVBoxLayout());
layout()->addWidget(form);
function = new QWidget(form);
function->setLayout(new QHBoxLayout());
form->layout()->addWidget(function);
function->layout()->addWidget(new QLabel(tr("Noise function")));
function_algo = new QComboBox(function);
function_algo->addItems(QStringList(tr("Simplex")) << tr("Perlin") << tr("Naive"));
function->layout()->addWidget(function_algo);
function->layout()->addWidget(new QLabel(tr("Ridge factor")));
function_ridge = new QSlider(Qt::Horizontal, function);
function_ridge->setRange(-10, 10);
function_ridge->setTickInterval(10);
function_ridge->setTickPosition(QSlider::TicksBelow);
function->layout()->addWidget(function_ridge);
QObject::connect(function_algo, SIGNAL(currentIndexChanged(int)), this, SLOT(functionChanged()));
QObject::connect(function_ridge, SIGNAL(valueChanged(int)), this, SLOT(functionChanged()));
form->layout()->addWidget(new QLabel(tr("Noise components")));
levels = new QListWidget(form);
form->layout()->addWidget(levels);
@ -223,6 +242,7 @@ void DialogNoise::revertToCurrent()
{
int i, n;
int selected;
NoiseFunction function;
selected = levels->currentRow();
@ -246,6 +266,10 @@ void DialogNoise::revertToCurrent()
levels->setCurrentRow(selected);
}
function = noiseGetFunction(_current);
function_algo->setCurrentIndex((int)function.algorithm);
function_ridge->setValue(round(function.ridge_factor * 20.0));
previewLevel->redraw();
previewTotal->redraw();
}
@ -283,6 +307,20 @@ void DialogNoise::removeLevel()
levels->setCurrentRow(row);
}
void DialogNoise::functionChanged()
{
NoiseFunction function;
function.algorithm = (NoiseFunctionAlgorithm)function_algo->currentIndex();
function.ridge_factor = (double)function_ridge->value() * 0.05;
noiseSetFunction(_current, &function);
noiseValidate(_current);
previewLevel->redraw();
previewTotal->redraw();
}
void DialogNoise::levelChanged(int row)
{
if (noiseGetLevel(_current, row, &_current_level_params))

View file

@ -2,6 +2,7 @@
#define _PAYSAGES_QT_DIALOGNOISE_H_
#include <QListWidget>
#include <QComboBox>
#include "basepreview.h"
#include "tools.h"
@ -29,6 +30,7 @@ private:
private slots:
void addLevel();
void removeLevel();
void functionChanged();
void levelChanged(int row);
void heightChanged(int value);
void scalingChanged(int value);
@ -40,6 +42,8 @@ private:
NoiseLevel _current_level_params;
BasePreview* previewLevel;
BasePreview* previewTotal;
QComboBox* function_algo;
QSlider* function_ridge;
QListWidget* levels;
QSlider* slider_height;
QSlider* slider_scaling;

View file

@ -14,7 +14,7 @@ public:
PreviewCloudsCoverage(QWidget* parent, CloudsLayerDefinition* layer):BasePreview(parent)
{
_renderer = rendererCreate();
_renderer.render_quality = 3;
_renderer.render_quality = 5;
_renderer.applyLightStatus = _applyLightStatus;
_original_layer = layer;
@ -81,7 +81,7 @@ public:
lightingValidateDefinition(&_lighting);
_renderer = rendererCreate();
_renderer.render_quality = 3;
_renderer.render_quality = 8;
_renderer.alterLight = _alterLight;
_renderer.getLightStatus = _getLightStatus;
_renderer.customData[0] = _preview_layer;
@ -109,9 +109,9 @@ protected:
void updateData()
{
cloudsLayerCopyDefinition(_original_layer, _preview_layer);
//noiseForceValue(_preview_layer.shape_noise, 1.0);
//noiseForceValue(_preview_layer->shape_noise, 1.0);
_preview_layer->lower_altitude = -_preview_layer->thickness * 0.5;
//curveClear(_preview_layer.coverage_by_altitude);
//curveClear(_preview_layer->coverage_by_altitude);
_preview_layer->base_coverage = 1.0;
_preview_layer->_custom_coverage = _coverageFunc;
}
@ -172,8 +172,8 @@ FormClouds::FormClouds(QWidget *parent):
addInputDouble(tr("Edge length"), &_layer->edge_length, 0.0, 1.0, 0.01, 0.1);
addInputMaterial(tr("Material"), &_layer->material);
addInputDouble(tr("Hardness to light"), &_layer->hardness, 0.0, 1.0, 0.01, 0.1);
addInputDouble(tr("Transparency depth"), &_layer->transparencydepth, 0.0, 100.0, 0.5, 5.0);
addInputDouble(tr("Light traversal depth"), &_layer->lighttraversal, 0.0, 100.0, 0.5, 5.0);
addInputDouble(tr("Transparency depth"), &_layer->transparencydepth, 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);
setLayers(_definition.layers);

View file

@ -31,10 +31,10 @@ public:
for (int x = 0; x < width; x++)
{
factor = ((double)(height / 2)) / noiseGetMaxValue(noise);
value = noiseGet1DTotal(noise, ((double)x) / factor) * factor;
painter.setPen(QColor(255, 255, 255));
value = -noiseGet1DTotal(noise, ((double)x) / factor) * factor;
painter.setPen(Qt::white);
painter.drawLine(x, 0, x, height / 2 + value);
painter.setPen(QColor(0, 0, 0));
painter.setPen(Qt::black);
painter.drawLine(x, height / 2 + value + 1, x, height);
}
}

View file

@ -100,6 +100,7 @@ void autoGenRealisticLandscape(int seed)
noiseClearLevels(water.waves_noise);
noiseAddLevelsSimple(water.waves_noise, 2, 1.0, 1.0);
noiseAddLevelsSimple(water.waves_noise, 3, 0.15, 0.1);
noiseSetFunctionParams(water.waves_noise, NOISE_FUNCTION_SIMPLEX, -0.3);
scenerySetWater(&water);
waterDeleteDefinition(&water);
@ -137,8 +138,9 @@ void autoGenRealisticLandscape(int seed)
terrain = terrainCreateDefinition();
noiseClearLevels(terrain.height_noise);
noiseAddLevelsSimple(terrain.height_noise, 10, 1.0, 1.0);
noiseSetFunctionParams(terrain.height_noise, NOISE_FUNCTION_SIMPLEX, -0.2);
terrain.height_factor = 12.0 / noiseGetMaxValue(terrain.height_noise);
terrain.scaling = 60.0;
terrain.scaling = 80.0;
terrain.shadow_smoothing = 0.03;
scenerySetTerrain(&terrain);
terrainDeleteDefinition(&terrain);

View file

@ -89,13 +89,15 @@ CloudsLayerDefinition* cloudsLayerCreateDefinition()
result->lighttraversal = 7.0;
result->minimumlight = 0.4;
result->shape_scaling = 10.0;
result->edge_scaling = 0.2;
result->edge_length = 0.2;
result->edge_scaling = 0.3;
result->edge_length = 0.4;
result->base_coverage = 0.35;
result->shape_noise = noiseCreateGenerator();
noiseAddLevelsSimple(result->shape_noise, 5, 1.0, 1.0);
noiseAddLevelsSimple(result->shape_noise, 6, 1.0, 1.0);
noiseSetFunctionParams(result->shape_noise, NOISE_FUNCTION_SIMPLEX, 0.3);
result->edge_noise = noiseCreateGenerator();
noiseAddLevelsSimple(result->edge_noise, 8, 1.0, 1.0);
noiseSetFunctionParams(result->edge_noise, NOISE_FUNCTION_SIMPLEX, 0.5);
result->_custom_coverage = _standardCoverageFunc;

View file

@ -13,11 +13,15 @@ struct NoiseLevel;
struct NoiseGenerator
{
NoiseFunction function;
double height_offset;
int level_count;
struct NoiseLevel levels[MAX_LEVEL_COUNT];
double _max_height;
double (*_func_noise_1d)(double x);
double (*_func_noise_2d)(double x, double y);
double (*_func_noise_3d)(double x, double y, double z);
};
void noiseInit()
@ -45,6 +49,8 @@ NoiseGenerator* noiseCreateGenerator()
/* initialize */
result = malloc(sizeof(NoiseGenerator));
result->function.algorithm = NOISE_FUNCTION_SIMPLEX;
result->function.ridge_factor = 0.0;
result->level_count = 0;
result->height_offset = 0.0;
@ -62,6 +68,10 @@ void noiseSaveGenerator(PackStream* stream, NoiseGenerator* generator)
{
int x;
x = (int)generator->function.algorithm;
packWriteInt(stream, &x);
packWriteDouble(stream, &generator->function.ridge_factor);
packWriteDouble(stream, &generator->height_offset);
packWriteInt(stream, &generator->level_count);
@ -81,6 +91,10 @@ void noiseLoadGenerator(PackStream* stream, NoiseGenerator* generator)
{
int x;
packReadInt(stream, &x);
generator->function.algorithm = (NoiseFunctionAlgorithm)x;
packReadDouble(stream, &generator->function.ridge_factor);
packReadDouble(stream, &generator->height_offset);
packReadInt(stream, &generator->level_count);
@ -100,6 +114,7 @@ void noiseLoadGenerator(PackStream* stream, NoiseGenerator* generator)
void noiseCopy(NoiseGenerator* source, NoiseGenerator* destination)
{
destination->function = source->function;
destination->height_offset = source->height_offset;
destination->level_count = source->level_count;
@ -113,6 +128,34 @@ void noiseValidate(NoiseGenerator* generator)
int x;
double max_height = generator->height_offset;
if (generator->function.algorithm < 0 || generator->function.algorithm > NOISE_FUNCTION_NAIVE)
{
generator->function.algorithm = NOISE_FUNCTION_SIMPLEX;
}
switch (generator->function.algorithm)
{
case NOISE_FUNCTION_SIMPLEX:
generator->_func_noise_1d = noiseSimplexGet1DValue;
generator->_func_noise_2d = noiseSimplexGet2DValue;
generator->_func_noise_3d = noiseSimplexGet3DValue;
break;
case NOISE_FUNCTION_PERLIN:
/*TODO*/
break;
case NOISE_FUNCTION_NAIVE:
/* TODO */
break;
}
if (generator->function.ridge_factor > 0.5)
{
generator->function.ridge_factor = 0.5;
}
if (generator->function.ridge_factor < -0.5)
{
generator->function.ridge_factor = -0.5;
}
for (x = 0; x < generator->level_count; x++)
{
max_height += generator->levels[x].height / 2.0;
@ -121,6 +164,23 @@ void noiseValidate(NoiseGenerator* generator)
generator->_max_height = max_height;
}
NoiseFunction noiseGetFunction(NoiseGenerator* generator)
{
return generator->function;
}
void noiseSetFunction(NoiseGenerator* generator, NoiseFunction* function)
{
generator->function = *function;
noiseValidate(generator);
}
void noiseSetFunctionParams(NoiseGenerator* generator, NoiseFunctionAlgorithm algorithm, double ridge_factor)
{
NoiseFunction function = {algorithm, ridge_factor};
noiseSetFunction(generator, &function);
}
void noiseForceValue(NoiseGenerator* generator, double value)
{
noiseClearLevels(generator);
@ -269,17 +329,28 @@ void noiseNormalizeHeight(NoiseGenerator* generator, double min_height, double m
noiseValidate(generator);
}
static inline double _get1DRawNoiseValue(NoiseGenerator* generator, double x)
static inline double _applyRidge(double value, double ridge)
{
return noiseSimplexGet2DValue(x, 0.0) * 0.5;
if (ridge > 0.0)
{
return fabs(value + 0.5 - ridge) - 0.5 + ridge;
}
else if (ridge < 0.0)
{
return -fabs(value - 0.5 - ridge) + 0.5 + ridge;
}
else
{
return value;
}
}
static inline double _get1DLevelValue(NoiseGenerator* generator, NoiseLevel* level, double x)
{
return _get1DRawNoiseValue(generator, x / level->scaling + level->xoffset) * level->height;
return _applyRidge(generator->_func_noise_1d(x / level->scaling + level->xoffset) * level->height, generator->function.ridge_factor);
}
double noiseGet1DLevel(NoiseGenerator* generator, int level, double x)
@ -334,14 +405,9 @@ double noiseGet1DDetail(NoiseGenerator* generator, double x, double detail)
static inline double _get2DRawNoiseValue(NoiseGenerator* generator, double x, double y)
{
return noiseSimplexGet2DValue(x, y) * 0.5;
}
static inline double _get2DLevelValue(NoiseGenerator* generator, NoiseLevel* level, double x, double y)
{
return _get2DRawNoiseValue(generator, x / level->scaling + level->xoffset, y / level->scaling + level->yoffset) * level->height;
return _applyRidge(generator->_func_noise_2d(x / level->scaling + level->xoffset, y / level->scaling + level->yoffset) * level->height, generator->function.ridge_factor);
}
double noiseGet2DLevel(NoiseGenerator* generator, int level, double x, double y)
@ -396,14 +462,9 @@ double noiseGet2DDetail(NoiseGenerator* generator, double x, double y, double de
static inline double _get3DRawNoiseValue(NoiseGenerator* generator, double x, double y, double z)
{
return noiseSimplexGet3DValue(x, y, z) * 0.5;
}
static inline double _get3DLevelValue(NoiseGenerator* generator, NoiseLevel* level, double x, double y, double z)
{
return _get3DRawNoiseValue(generator, x / level->scaling + level->xoffset, y / level->scaling + level->yoffset, z / level->scaling + level->zoffset) * level->height;
return _applyRidge(generator->_func_noise_3d(x / level->scaling + level->xoffset, y / level->scaling + level->yoffset, z / level->scaling + level->zoffset) * level->height, generator->function.ridge_factor);
}
double noiseGet3DLevel(NoiseGenerator* generator, int level, double x, double y, double z)

View file

@ -7,6 +7,19 @@
extern "C" {
#endif
typedef enum
{
NOISE_FUNCTION_SIMPLEX,
NOISE_FUNCTION_PERLIN,
NOISE_FUNCTION_NAIVE
} NoiseFunctionAlgorithm;
typedef struct
{
NoiseFunctionAlgorithm algorithm;
double ridge_factor;
} NoiseFunction;
struct NoiseLevel
{
double scaling;
@ -29,6 +42,9 @@ void noiseSaveGenerator(PackStream* stream, NoiseGenerator* generator);
void noiseLoadGenerator(PackStream* stream, NoiseGenerator* generator);
void noiseCopy(NoiseGenerator* source, NoiseGenerator* destination);
void noiseValidate(NoiseGenerator* generator);
NoiseFunction noiseGetFunction(NoiseGenerator* generator);
void noiseSetFunction(NoiseGenerator* generator, NoiseFunction* function);
void noiseSetFunctionParams(NoiseGenerator* generator, NoiseFunctionAlgorithm algorithm, double ridge_factor);
void noiseForceValue(NoiseGenerator* generator, double value);
double noiseGetMaxValue(NoiseGenerator* generator);
int noiseGetLevelCount(NoiseGenerator* generator);

View file

@ -139,6 +139,12 @@ void noiseSimplexInit()
_G4 = (5.0 - sqrt(5.0)) / 20.0;
}
double noiseSimplexGet1DValue(double xin)
{
/* TODO Find custom function */
return noiseSimplexGet2DValue(xin, 0.0);
}
double noiseSimplexGet2DValue(double xin, double yin)
{
double n0, n1, n2; /* Noise contributions from the three corners */
@ -200,8 +206,8 @@ double noiseSimplexGet2DValue(double xin, double yin)
n2 = t2 * t2 * _dot2(_grad3[gi2], x2, y2);
}
/* Add contributions from each corner to get the final noise value.
The result is scaled to return values in the interval [-1,1]. */
return 70.0 * (n0 + n1 + n2);
The result is scaled to return values in the interval [-0.5,0.5]. */
return 35.0 * (n0 + n1 + n2);
}
double noiseSimplexGet3DValue(double xin, double yin, double zin)
@ -334,8 +340,8 @@ double noiseSimplexGet3DValue(double xin, double yin, double zin)
n3 = t3 * t3 * _dot3(_grad3[gi3], x3, y3, z3);
}
/* Add contributions from each corner to get the final noise value.
The result is scaled to stay just inside [-1,1] */
return 32.0 * (n0 + n1 + n2 + n3);
The result is scaled to stay just inside [-0.5,0.5] */
return 16.0 * (n0 + n1 + n2 + n3);
}
double noiseSimplexGet4DValue(double x, double y, double z, double w)
@ -462,6 +468,6 @@ double noiseSimplexGet4DValue(double x, double y, double z, double w)
t4 *= t4;
n4 = t4 * t4 * _dot4(_grad4[gi4], x4, y4, z4, w4);
}
/* Sum up and scale the result to cover the range [-1,1] */
return 27.0 * (n0 + n1 + n2 + n3 + n4);
/* Sum up and scale the result to cover the range [-0.5,0.5] */
return 13.5 * (n0 + n1 + n2 + n3 + n4);
}

View file

@ -6,6 +6,7 @@ extern "C" {
#endif
void noiseSimplexInit();
double noiseSimplexGet1DValue(double xin);
double noiseSimplexGet2DValue(double xin, double yin);
double noiseSimplexGet3DValue(double xin, double yin, double zin);
double noiseSimplexGet4DValue(double x, double y, double z, double w);