paysages : Heightmap painting - Added noise brush.

git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@399 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
Michaël Lemaire 2012-07-24 14:59:06 +00:00 committed by ThunderK
parent 8654276b07
commit a16c5dd975
4 changed files with 111 additions and 9 deletions

View file

@ -4,6 +4,7 @@
#include <QMouseEvent> #include <QMouseEvent>
#include <math.h> #include <math.h>
#include <GL/glu.h> #include <GL/glu.h>
#include <qt4/QtCore/qlocale.h>
#include "tools.h" #include "tools.h"
#include "../lib_paysages/terrain.h" #include "../lib_paysages/terrain.h"
#include "../lib_paysages/scenery.h" #include "../lib_paysages/scenery.h"
@ -27,6 +28,7 @@ WidgetHeightMap::WidgetHeightMap(QWidget *parent, HeightMap* heightmap):
_last_brush_action = 0; _last_brush_action = 0;
_last_mouse_x = 0; _last_mouse_x = 0;
_last_mouse_y = 0; _last_mouse_y = 0;
_last_time = QDateTime::currentDateTime();
_mouse_moved = false; _mouse_moved = false;
_angle_h = 0.0; _angle_h = 0.0;
@ -38,10 +40,14 @@ WidgetHeightMap::WidgetHeightMap(QWidget *parent, HeightMap* heightmap):
_brush_size = 10.0; _brush_size = 10.0;
_brush_smoothing = 0.5; _brush_smoothing = 0.5;
_brush_strength = 1.0; _brush_strength = 1.0;
_brush_noise = noiseCreateGenerator();
noiseGenerateBaseNoise(_brush_noise, 102400);
noiseAddLevelsSimple(_brush_noise, 6, 1.0, 1.0);
} }
WidgetHeightMap::~WidgetHeightMap() WidgetHeightMap::~WidgetHeightMap()
{ {
noiseDeleteGenerator(_brush_noise);
delete[] _vertexes; delete[] _vertexes;
} }
@ -155,10 +161,15 @@ void WidgetHeightMap::mouseMoveEvent(QMouseEvent* event)
updateGL(); updateGL();
} }
void WidgetHeightMap::timerEvent(QTimerEvent* event) void WidgetHeightMap::timerEvent(QTimerEvent*)
{ {
if (_last_brush_action) QDateTime new_time = QDateTime::currentDateTime();
double duration = 0.001 * (double)_last_time.msecsTo(new_time);
_last_time = new_time;
if (_last_brush_action != 0)
{ {
double brush_strength;
HeightMapBrush brush; HeightMapBrush brush;
brush.relative_x = (_brush_x + 40.0) / 80.0; brush.relative_x = (_brush_x + 40.0) / 80.0;
@ -166,15 +177,28 @@ void WidgetHeightMap::timerEvent(QTimerEvent* event)
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_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);
break;
case HEIGHTMAP_BRUSH_SMOOTH:
if (_last_brush_action < 0)
{
heightmapBrushSmooth(_heightmap, &brush, brush_strength);
}
else
{
heightmapBrushAddNoise(_heightmap, &brush, _brush_noise, brush_strength);
}
break; break;
default: default:
return; return;
} }
// TODO Only mark dirty the updated area
_dirty = true; _dirty = true;
updateGL(); updateGL();
} }

View file

@ -2,6 +2,7 @@
#define _PAYSAGES_QT_WIDGETHEIGHTMAP_H_ #define _PAYSAGES_QT_WIDGETHEIGHTMAP_H_
#include <QGLWidget> #include <QGLWidget>
#include <QDateTime>
#include "../lib_paysages/euclid.h" #include "../lib_paysages/euclid.h"
#include "../lib_paysages/heightmap.h" #include "../lib_paysages/heightmap.h"
@ -60,6 +61,7 @@ private:
int _last_brush_action; int _last_brush_action;
int _last_mouse_x; int _last_mouse_x;
int _last_mouse_y; int _last_mouse_y;
QDateTime _last_time;
bool _mouse_moved; bool _mouse_moved;
double _angle_h; double _angle_h;
@ -71,6 +73,7 @@ private:
double _brush_size; double _brush_size;
double _brush_smoothing; double _brush_smoothing;
double _brush_strength; double _brush_strength;
NoiseGenerator* _brush_noise;
}; };
#endif #endif

View file

@ -1,6 +1,7 @@
#include "heightmap.h" #include "heightmap.h"
#include "tools.h" #include "tools.h"
#include "system.h" #include "system.h"
#include "noise.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -140,17 +141,46 @@ double heightmapGetValue(HeightMap* heightmap, double x, double z)
return toolsBicubicInterpolate(stencil, x * xmax - (double)xlow, z * zmax - (double)zlow); return toolsBicubicInterpolate(stencil, x * xmax - (double)xlow, z * zmax - (double)zlow);
} }
static inline void _getBrushBoundaries(HeightMapBrush* brush, int rx, int rz, int* x1, int* x2, int* z1, int* z2)
{
double cx = brush->relative_x * rx;
double cz = brush->relative_z * rz;
double s = brush->smoothed_size + brush->hard_radius;
double sx = s * rx;
double sz = s * rz;
*x1 = (int)floor(cx - sx);
*x2 = (int)ceil(cx + sx);
*z1 = (int)floor(cz - sz);
*z2 = (int)ceil(cz + sz);
if (*x1 < 0)
{
*x1 = 0;
}
if (*x1 > rx)
{
*x1 = rx;
}
if (*z1 < 0)
{
*z1 = 0;
}
if (*z1 > rz)
{
*z1 = rz;
}
}
void heightmapBrushElevation(HeightMap* heightmap, HeightMapBrush* brush, double value) void heightmapBrushElevation(HeightMap* heightmap, HeightMapBrush* brush, double value)
{ {
int x, z; int x, x1, x2, z, z1, z2;
double dx, dz, distance; double dx, dz, distance;
/* TODO Limit to brush radius */ _getBrushBoundaries(brush, heightmap->resolution_x - 1, heightmap->resolution_z - 1, &x1, &x2, &z1, &z2);
for (x = 0; x < heightmap->resolution_x; x++) for (x = x1; x <= x2; x++)
{ {
dx = (double)x / (double)heightmap->resolution_x; dx = (double)x / (double)heightmap->resolution_x;
for (z = 0; z < heightmap->resolution_z; z++) for (z = z1; z <= z2; z++)
{ {
dz = (double)z / (double)heightmap->resolution_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)); distance = sqrt((brush->relative_x - dx) * (brush->relative_x - dx) + (brush->relative_z - dz) * (brush->relative_z - dz));
@ -169,3 +199,45 @@ void heightmapBrushElevation(HeightMap* heightmap, HeightMapBrush* brush, double
} }
} }
} }
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);
brush_size = brush->hard_radius + brush->smoothed_size;
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)
{
factor = (1.0 - (distance - brush->hard_radius) / brush->smoothed_size);
}
else
{
continue;
}
}
else
{
factor = 1.0;
}
heightmap->data[z * heightmap->resolution_x + x] += factor * noiseGet2DTotal(generator, dx / brush_size, dz / brush_size) * brush_size;
}
}
}

View file

@ -4,6 +4,7 @@
/* Height map for terrain */ /* Height map for terrain */
#include "pack.h" #include "pack.h"
#include "noise.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -40,6 +41,8 @@ void heightmapChangeResolution(HeightMap* heightmap, int resolution_x, int resol
void heightmapImportFromPicture(HeightMap* heightmap, const char* picturepath); void heightmapImportFromPicture(HeightMap* heightmap, const char* picturepath);
void heightmapBrushElevation(HeightMap* heightmap, HeightMapBrush* brush, double value); void heightmapBrushElevation(HeightMap* heightmap, HeightMapBrush* brush, double value);
void heightmapBrushSmooth(HeightMap* heightmap, HeightMapBrush* brush, double value);
void heightmapBrushAddNoise(HeightMap* heightmap, HeightMapBrush* brush, NoiseGenerator* generator, double value);
#ifdef __cplusplus #ifdef __cplusplus
} }