diff --git a/ChangeLog b/ChangeLog index de7cb90..34a2c21 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,7 @@ Previews : * Progressive rendering now takes advantage of multiple CPU cores. Scenery : + * Added terrain canvases to paint the shape directly. * Added clouds hardness to light. * Added sun halo control. * New cloud model with 2 noises : one for the global shape and one for edges. diff --git a/gui_qt/dialogheightmap.cpp b/gui_qt/dialogheightmap.cpp index 9026977..88f40ff 100644 --- a/gui_qt/dialogheightmap.cpp +++ b/gui_qt/dialogheightmap.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include "widgetheightmap.h" @@ -20,6 +21,7 @@ DialogHeightMap::DialogHeightMap(QWidget* parent, HeightMap* heightmap) : Dialog QLabel* label; QSlider* slider; QPushButton* button; + QComboBox* combobox; _value_original = heightmap; _value_modified = heightmapCreate(); @@ -64,6 +66,12 @@ DialogHeightMap::DialogHeightMap(QWidget* parent, HeightMap* heightmap) : Dialog connect(button, SIGNAL(clicked()), _3dview, SLOT(resetToTerrain())); panel->layout()->addWidget(button); + combobox = new QComboBox(panel); + combobox->addItem(tr("Raise / lower")); + combobox->addItem(tr("Smooth / add noise")); + connect(combobox, SIGNAL(currentIndexChanged(int)), this, SLOT(brushModeChanged(int))); + panel->layout()->addWidget(combobox); + label = new QLabel(tr("Brush size"), panel); panel->layout()->addWidget(label); @@ -129,6 +137,11 @@ void DialogHeightMap::angleVChanged(int value) _3dview->setVerticalViewAngle(M_PI_2 * ((double)value) / 1000.0); } +void DialogHeightMap::brushModeChanged(int value) +{ + _3dview->setBrushMode((HeightMapBrushMode)value); +} + void DialogHeightMap::brushSizeChanged(int value) { _3dview->setBrushSize((double)value / 10.0); diff --git a/gui_qt/dialogheightmap.h b/gui_qt/dialogheightmap.h index 5562611..099d5f5 100644 --- a/gui_qt/dialogheightmap.h +++ b/gui_qt/dialogheightmap.h @@ -19,6 +19,7 @@ public slots: private slots: void angleHChanged(int value); void angleVChanged(int value); + void brushModeChanged(int value); void brushSizeChanged(int value); void brushSmoothingChanged(int value); diff --git a/gui_qt/widgetheightmap.cpp b/gui_qt/widgetheightmap.cpp index 6a915bd..1aa9cbb 100644 --- a/gui_qt/widgetheightmap.cpp +++ b/gui_qt/widgetheightmap.cpp @@ -30,6 +30,7 @@ WidgetHeightMap::WidgetHeightMap(QWidget *parent, HeightMap* heightmap): _brush_x = 0.0; _brush_z = 0.0; + _brush_mode = HEIGHTMAP_BRUSH_RAISE; _brush_size = 10.0; _brush_smoothing = 0.5; } @@ -51,6 +52,11 @@ void WidgetHeightMap::setVerticalViewAngle(double angle_v) updateGL(); } +void WidgetHeightMap::setBrushMode(HeightMapBrushMode mode) +{ + _brush_mode = mode; +} + void WidgetHeightMap::setBrushSize(double size) { _brush_size = size; @@ -96,6 +102,7 @@ void WidgetHeightMap::keyPressEvent(QKeyEvent* event) void WidgetHeightMap::mousePressEvent(QMouseEvent* event) { + mouseMoveEvent(event); } void WidgetHeightMap::mouseMoveEvent(QMouseEvent* event) @@ -103,7 +110,27 @@ void WidgetHeightMap::mouseMoveEvent(QMouseEvent* event) int move_x = event->x() - _last_mouse_x; int move_y = event->y() - _last_mouse_y; - if (event->buttons() & Qt::MiddleButton) + if ((event->buttons() & Qt::LeftButton) || (event->buttons() & Qt::RightButton)) + { + HeightMapBrush brush; + + brush.relative_x = (_brush_x + 40.0) / 80.0; + brush.relative_z = (_brush_z + 40.0) / 80.0; + brush.hard_radius = _brush_size / 80.0 - _brush_smoothing; + brush.smoothed_size = (_brush_size / 80.0) * _brush_smoothing; + + switch (_brush_mode) + { + case HEIGHTMAP_BRUSH_RAISE: + heightmapBrushElevation(_heightmap, &brush, (event->buttons() & Qt::RightButton) ? -0.01 : 0.01); + _dirty = true; + updateGL(); + break; + default: + ; + } + } + else if (event->buttons() & Qt::MiddleButton) { // Rotate around the turntable _angle_h -= (double)move_x * 0.008; diff --git a/gui_qt/widgetheightmap.h b/gui_qt/widgetheightmap.h index 3b2d145..e3d0f8e 100644 --- a/gui_qt/widgetheightmap.h +++ b/gui_qt/widgetheightmap.h @@ -11,6 +11,12 @@ typedef struct Vector3 normal; } _VertexInfo; +typedef enum +{ + HEIGHTMAP_BRUSH_RAISE = 0, + HEIGHTMAP_BRUSH_SMOOTH = 1 +} HeightMapBrushMode; + class WidgetHeightMap : public QGLWidget { Q_OBJECT @@ -20,6 +26,7 @@ public: void setHorizontalViewAngle(double angle_h); void setVerticalViewAngle(double angle_v); + void setBrushMode(HeightMapBrushMode mode); void setBrushSize(double size); void setBrushSmoothing(double smoothing); @@ -55,6 +62,7 @@ private: double _brush_x; double _brush_z; + HeightMapBrushMode _brush_mode; double _brush_size; double _brush_smoothing; }; diff --git a/lib_paysages/heightmap.c b/lib_paysages/heightmap.c index 704465b..7371da6 100644 --- a/lib_paysages/heightmap.c +++ b/lib_paysages/heightmap.c @@ -2,6 +2,7 @@ #include #include +#include HeightMap heightmapCreate() { @@ -68,3 +69,33 @@ void heightmapChangeResolution(HeightMap* heightmap, int resolution_x, int resol heightmap->data[i] = 0.0; } } + +void heightmapBrushElevation(HeightMap* heightmap, HeightMapBrush* brush, double value) +{ + int x, z; + double dx, dz, distance; + + // TODO Limit to brush radius + + for (x = 0; x < heightmap->resolution_x; x++) + { + dx = (double)x / (double)heightmap->resolution_x; + for (z = 0; z < heightmap->resolution_z; 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 * (distance - brush->hard_radius) / brush->smoothed_size; + } + } + else + { + heightmap->data[z * heightmap->resolution_x +x] += value; + } + } + } +} diff --git a/lib_paysages/heightmap.h b/lib_paysages/heightmap.h index 682f569..0ef3d77 100644 --- a/lib_paysages/heightmap.h +++ b/lib_paysages/heightmap.h @@ -16,6 +16,14 @@ typedef struct double* data; } HeightMap; +typedef struct +{ + double relative_x; + double relative_z; + double hard_radius; + double smoothed_size; +} HeightMapBrush; + HeightMap heightmapCreate(); void heightmapDelete(HeightMap* heightmap); void heightmapCopy(HeightMap* source, HeightMap* destination); @@ -25,6 +33,8 @@ void heightmapSave(PackStream* stream, HeightMap* heightmap); void heightmapLoad(PackStream* stream, HeightMap* heightmap); void heightmapChangeResolution(HeightMap* heightmap, int resolution_x, int resolution_z); + +void heightmapBrushElevation(HeightMap* heightmap, HeightMapBrush* brush, double value); #ifdef __cplusplus }