paysages : Heightmap painting - Added smooth brush.

git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@400 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
Michaël Lemaire 2012-07-26 11:55:19 +00:00 committed by ThunderK
parent a16c5dd975
commit 0ab0bd9475
4 changed files with 55 additions and 45 deletions

View file

@ -68,7 +68,7 @@ DialogHeightMap::DialogHeightMap(QWidget* parent, HeightMap* heightmap) : Dialog
combobox = new QComboBox(panel); combobox = new QComboBox(panel);
combobox->addItem(tr("Raise / lower")); combobox->addItem(tr("Raise / lower"));
combobox->addItem(tr("Smooth / add noise")); combobox->addItem(tr("Add noise / smooth"));
connect(combobox, SIGNAL(currentIndexChanged(int)), this, SLOT(brushModeChanged(int))); connect(combobox, SIGNAL(currentIndexChanged(int)), this, SLOT(brushModeChanged(int)));
panel->layout()->addWidget(combobox); panel->layout()->addWidget(combobox);
@ -76,10 +76,10 @@ DialogHeightMap::DialogHeightMap(QWidget* parent, HeightMap* heightmap) : Dialog
panel->layout()->addWidget(label); panel->layout()->addWidget(label);
slider = new QSlider(Qt::Horizontal, panel); slider = new QSlider(Qt::Horizontal, panel);
slider->setRange(6, 150); slider->setRange(6, 300);
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(brushSizeChanged(int))); connect(slider, SIGNAL(valueChanged(int)), this, SLOT(brushSizeChanged(int)));
panel->layout()->addWidget(slider); panel->layout()->addWidget(slider);
slider->setValue(30); slider->setValue(60);
label = new QLabel(tr("Brush smoothing"), panel); label = new QLabel(tr("Brush smoothing"), panel);
panel->layout()->addWidget(label); panel->layout()->addWidget(label);

View file

@ -176,13 +176,14 @@ void WidgetHeightMap::timerEvent(QTimerEvent*)
brush.relative_z = (_brush_z + 40.0) / 80.0; brush.relative_z = (_brush_z + 40.0) / 80.0;
brush.hard_radius = _brush_size * (1.0 - _brush_smoothing) / 80.0; brush.hard_radius = _brush_size * (1.0 - _brush_smoothing) / 80.0;
brush.smoothed_size = _brush_size * _brush_smoothing / 80.0; brush.smoothed_size = _brush_size * _brush_smoothing / 80.0;
brush.total_radius = brush.hard_radius + brush.smoothed_size;
brush_strength = _brush_strength * duration / 0.1; brush_strength = _brush_strength * duration / 0.1;
switch (_brush_mode) switch (_brush_mode)
{ {
case HEIGHTMAP_BRUSH_RAISE: case HEIGHTMAP_BRUSH_RAISE:
heightmapBrushElevation(_heightmap, &brush, brush_strength * _last_brush_action); heightmapBrushElevation(_heightmap, &brush, brush_strength * _last_brush_action * 20.0);
break; break;
case HEIGHTMAP_BRUSH_SMOOTH: case HEIGHTMAP_BRUSH_SMOOTH:
if (_last_brush_action < 0) if (_last_brush_action < 0)
@ -191,7 +192,7 @@ void WidgetHeightMap::timerEvent(QTimerEvent*)
} }
else else
{ {
heightmapBrushAddNoise(_heightmap, &brush, _brush_noise, brush_strength); heightmapBrushAddNoise(_heightmap, &brush, _brush_noise, brush_strength * 10.0);
} }
break; break;
default: default:

View file

@ -170,45 +170,12 @@ static inline void _getBrushBoundaries(HeightMapBrush* brush, int rx, int rz, in
} }
} }
void heightmapBrushElevation(HeightMap* heightmap, HeightMapBrush* brush, double value) typedef double (*BrushCallback)(HeightMap* heightmap, HeightMapBrush* brush, double x, double z, double basevalue, double influence, double force, void* data);
static inline void _applyBrush(HeightMap* heightmap, HeightMapBrush* brush, double force, void* data, BrushCallback callback)
{ {
int x, x1, x2, z, z1, z2; int x, x1, x2, z, z1, z2;
double dx, dz, distance; double dx, dz, distance, influence, brush_size;
_getBrushBoundaries(brush, heightmap->resolution_x - 1, heightmap->resolution_z - 1, &x1, &x2, &z1, &z2);
for (x = x1; x <= x2; x++)
{
dx = (double)x / (double)heightmap->resolution_x;
for (z = z1; z <= z2; z++)
{
dz = (double)z / (double)heightmap->resolution_z;
distance = sqrt((brush->relative_x - dx) * (brush->relative_x - dx) + (brush->relative_z - dz) * (brush->relative_z - dz));
if (distance > brush->hard_radius)
{
if (distance <= brush->hard_radius + brush->smoothed_size)
{
heightmap->data[z * heightmap->resolution_x + x] += value * (1.0 - (distance - brush->hard_radius) / brush->smoothed_size);
}
}
else
{
heightmap->data[z * heightmap->resolution_x + x] += value;
}
}
}
}
void heightmapBrushSmooth(HeightMap* heightmap, HeightMapBrush* brush, double value)
{
/* TODO */
}
void heightmapBrushAddNoise(HeightMap* heightmap, HeightMapBrush* brush, NoiseGenerator* generator, double value)
{
int x, x1, x2, z, z1, z2;
double dx, dz, distance, factor, brush_size;
_getBrushBoundaries(brush, heightmap->resolution_x - 1, heightmap->resolution_z - 1, &x1, &x2, &z1, &z2); _getBrushBoundaries(brush, heightmap->resolution_x - 1, heightmap->resolution_z - 1, &x1, &x2, &z1, &z2);
brush_size = brush->hard_radius + brush->smoothed_size; brush_size = brush->hard_radius + brush->smoothed_size;
@ -225,7 +192,7 @@ void heightmapBrushAddNoise(HeightMap* heightmap, HeightMapBrush* brush, NoiseGe
{ {
if (distance <= brush->hard_radius + brush->smoothed_size) if (distance <= brush->hard_radius + brush->smoothed_size)
{ {
factor = (1.0 - (distance - brush->hard_radius) / brush->smoothed_size); influence = (1.0 - (distance - brush->hard_radius) / brush->smoothed_size);
} }
else else
{ {
@ -234,10 +201,51 @@ void heightmapBrushAddNoise(HeightMap* heightmap, HeightMapBrush* brush, NoiseGe
} }
else else
{ {
factor = 1.0; influence = 1.0;
} }
heightmap->data[z * heightmap->resolution_x + x] += factor * noiseGet2DTotal(generator, dx / brush_size, dz / brush_size) * brush_size; heightmap->data[z * heightmap->resolution_x + x] = callback(heightmap, brush, dx, dz, heightmap->data[z * heightmap->resolution_x + x], influence, force, data);
} }
} }
} }
static double _applyBrushElevation(HeightMap* heightmap, HeightMapBrush* brush, double x, double z, double basevalue, double influence, double force, void* data)
{
return basevalue + influence * force * brush->total_radius;
}
void heightmapBrushElevation(HeightMap* heightmap, HeightMapBrush* brush, double value)
{
_applyBrush(heightmap, brush, value, NULL, _applyBrushElevation);
}
static double _applyBrushSmooth(HeightMap* heightmap, HeightMapBrush* brush, double x, double z, double basevalue, double influence, double force, void* data)
{
double ideal, factor;
ideal = heightmapGetValue(heightmap, x + brush->total_radius * 0.5, z);
ideal += heightmapGetValue(heightmap, x - brush->total_radius * 0.5, z);
ideal += heightmapGetValue(heightmap, x, z - brush->total_radius * 0.5);
ideal += heightmapGetValue(heightmap, x, z + brush->total_radius * 0.5);
ideal /= 4.0;
factor = influence * force;
if (factor > 1.0)
{
factor = 0.0;
}
return basevalue + (ideal - basevalue) * factor;
}
void heightmapBrushSmooth(HeightMap* heightmap, HeightMapBrush* brush, double value)
{
_applyBrush(heightmap, brush, value, NULL, _applyBrushSmooth);
}
static double _applyBrushAddNoise(HeightMap* heightmap, HeightMapBrush* brush, double x, double z, double basevalue, double influence, double force, void* data)
{
return basevalue + noiseGet2DTotal((NoiseGenerator*)data, x / brush->total_radius, z / brush->total_radius) * influence * force * brush->total_radius;
}
void heightmapBrushAddNoise(HeightMap* heightmap, HeightMapBrush* brush, NoiseGenerator* generator, double value)
{
_applyBrush(heightmap, brush, value, generator, _applyBrushAddNoise);
}

View file

@ -23,6 +23,7 @@ typedef struct
double relative_z; double relative_z;
double hard_radius; double hard_radius;
double smoothed_size; double smoothed_size;
double total_radius;
} HeightMapBrush; } HeightMapBrush;
HeightMap heightmapCreate(); HeightMap heightmapCreate();