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:
parent
a16c5dd975
commit
0ab0bd9475
4 changed files with 55 additions and 45 deletions
|
@ -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);
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in a new issue