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->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)));
|
||||
panel->layout()->addWidget(combobox);
|
||||
|
||||
|
@ -76,10 +76,10 @@ DialogHeightMap::DialogHeightMap(QWidget* parent, HeightMap* heightmap) : Dialog
|
|||
panel->layout()->addWidget(label);
|
||||
|
||||
slider = new QSlider(Qt::Horizontal, panel);
|
||||
slider->setRange(6, 150);
|
||||
slider->setRange(6, 300);
|
||||
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(brushSizeChanged(int)));
|
||||
panel->layout()->addWidget(slider);
|
||||
slider->setValue(30);
|
||||
slider->setValue(60);
|
||||
|
||||
label = new QLabel(tr("Brush smoothing"), panel);
|
||||
panel->layout()->addWidget(label);
|
||||
|
|
|
@ -176,13 +176,14 @@ void WidgetHeightMap::timerEvent(QTimerEvent*)
|
|||
brush.relative_z = (_brush_z + 40.0) / 80.0;
|
||||
brush.hard_radius = _brush_size * (1.0 - _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;
|
||||
|
||||
switch (_brush_mode)
|
||||
{
|
||||
case HEIGHTMAP_BRUSH_RAISE:
|
||||
heightmapBrushElevation(_heightmap, &brush, brush_strength * _last_brush_action);
|
||||
heightmapBrushElevation(_heightmap, &brush, brush_strength * _last_brush_action * 20.0);
|
||||
break;
|
||||
case HEIGHTMAP_BRUSH_SMOOTH:
|
||||
if (_last_brush_action < 0)
|
||||
|
@ -191,7 +192,7 @@ void WidgetHeightMap::timerEvent(QTimerEvent*)
|
|||
}
|
||||
else
|
||||
{
|
||||
heightmapBrushAddNoise(_heightmap, &brush, _brush_noise, brush_strength);
|
||||
heightmapBrushAddNoise(_heightmap, &brush, _brush_noise, brush_strength * 10.0);
|
||||
}
|
||||
break;
|
||||
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;
|
||||
double dx, dz, distance;
|
||||
|
||||
_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;
|
||||
double dx, dz, distance, influence, brush_size;
|
||||
|
||||
_getBrushBoundaries(brush, heightmap->resolution_x - 1, heightmap->resolution_z - 1, &x1, &x2, &z1, &z2);
|
||||
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)
|
||||
{
|
||||
factor = (1.0 - (distance - brush->hard_radius) / brush->smoothed_size);
|
||||
influence = (1.0 - (distance - brush->hard_radius) / brush->smoothed_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -234,10 +201,51 @@ void heightmapBrushAddNoise(HeightMap* heightmap, HeightMapBrush* brush, NoiseGe
|
|||
}
|
||||
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 hard_radius;
|
||||
double smoothed_size;
|
||||
double total_radius;
|
||||
} HeightMapBrush;
|
||||
|
||||
HeightMap heightmapCreate();
|
||||
|
|
Loading…
Reference in a new issue