paysages : Big terrain refactoring for future sculpt mode (WIP).

git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@476 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
Michaël Lemaire 2012-12-10 22:05:53 +00:00 committed by ThunderK
parent 5f22647b1c
commit f82b0f1e02
13 changed files with 178 additions and 259 deletions

View file

@ -13,7 +13,6 @@
#include "../lib_paysages/curve.h" #include "../lib_paysages/curve.h"
#include "../lib_paysages/color.h" #include "../lib_paysages/color.h"
#include "../lib_paysages/layers.h" #include "../lib_paysages/layers.h"
#include "../lib_paysages/heightmap.h"
#include "../lib_paysages/pack.h" #include "../lib_paysages/pack.h"
class BaseForm:public QWidget class BaseForm:public QWidget

View file

@ -13,7 +13,7 @@
#include "widgetheightmap.h" #include "widgetheightmap.h"
/**************** Dialog form ****************/ /**************** Dialog form ****************/
DialogHeightMap::DialogHeightMap(QWidget* parent, HeightMap* heightmap, void* canvas) : DialogWithPreview(parent) DialogHeightMap::DialogHeightMap(QWidget* parent, TerrainDefinition* terrain) : DialogWithPreview(parent)
{ {
QWidget* mainarea; QWidget* mainarea;
QWidget* buttons; QWidget* buttons;
@ -26,9 +26,9 @@ DialogHeightMap::DialogHeightMap(QWidget* parent, HeightMap* heightmap, void* ca
QPushButton* button; QPushButton* button;
QComboBox* combobox; QComboBox* combobox;
_value_original = heightmap; _value_original = terrain;
_value_modified = heightmapCreate(); _value_modified = (TerrainDefinition*)TerrainDefinitionClass.create();
heightmapCopy(_value_original, &_value_modified); TerrainDefinitionClass.copy(_value_original, _value_modified);
setLayout(new QVBoxLayout()); setLayout(new QVBoxLayout());
// Dialog layout (main area + buttons) // Dialog layout (main area + buttons)
@ -53,7 +53,7 @@ DialogHeightMap::DialogHeightMap(QWidget* parent, HeightMap* heightmap, void* ca
mainarea->layout()->setAlignment(panel, Qt::AlignTop); mainarea->layout()->setAlignment(panel, Qt::AlignTop);
// Viewer layout (3d display + sliders) // Viewer layout (3d display + sliders)
_3dview = new WidgetHeightMap(viewer, &_value_modified); _3dview = new WidgetHeightMap(viewer, _value_modified);
viewer_layout->addWidget(_3dview, 0, 0); viewer_layout->addWidget(_3dview, 0, 0);
slider = new QSlider(Qt::Horizontal, viewer); slider = new QSlider(Qt::Horizontal, viewer);
slider->setRange(0, 1000); slider->setRange(0, 1000);
@ -65,24 +65,9 @@ DialogHeightMap::DialogHeightMap(QWidget* parent, HeightMap* heightmap, void* ca
viewer_layout->addWidget(slider, 0, 1); viewer_layout->addWidget(slider, 0, 1);
// Panel layout // Panel layout
if (canvas) /*button = new QPushButton(tr("Load from picture file"), panel);
{
button = new QPushButton(tr("Reset to terrain height"), panel);
connect(button, SIGNAL(clicked()), this, SLOT(resetToTerrain()));
panel->layout()->addWidget(button);
}
button = new QPushButton(tr("Load from picture file"), panel);
connect(button, SIGNAL(clicked()), this, SLOT(loadFromFile())); connect(button, SIGNAL(clicked()), this, SLOT(loadFromFile()));
panel->layout()->addWidget(button); panel->layout()->addWidget(button);*/
button = new QPushButton(tr("Change resolution"), panel);
connect(button, SIGNAL(clicked()), this, SLOT(changeResolution()));
panel->layout()->addWidget(button);
_resolution_label = new QLabel("", panel);
panel->layout()->addWidget(_resolution_label);
updateResolutionLabel();
combobox = new QComboBox(panel); combobox = new QComboBox(panel);
combobox->addItem(tr("Raise / lower")); combobox->addItem(tr("Raise / lower"));
@ -136,11 +121,11 @@ DialogHeightMap::DialogHeightMap(QWidget* parent, HeightMap* heightmap, void* ca
setWindowTitle(tr("Paysages 3D - Height map painting")); setWindowTitle(tr("Paysages 3D - Height map painting"));
} }
bool DialogHeightMap::editHeightMap(QWidget* parent, HeightMap* heightmap, void* canvas) bool DialogHeightMap::editHeightMap(QWidget* parent, TerrainDefinition* terrain)
{ {
int result; int result;
DialogHeightMap* dialog = new DialogHeightMap(parent, heightmap, canvas); DialogHeightMap* dialog = new DialogHeightMap(parent, terrain);
result = dialog->exec(); result = dialog->exec();
delete dialog; delete dialog;
@ -150,15 +135,14 @@ bool DialogHeightMap::editHeightMap(QWidget* parent, HeightMap* heightmap, void*
void DialogHeightMap::accept() void DialogHeightMap::accept()
{ {
heightmapCopy(&_value_modified, _value_original); TerrainDefinitionClass.copy(_value_modified, _value_original);
QDialog::accept(); QDialog::accept();
} }
void DialogHeightMap::revert() void DialogHeightMap::revert()
{ {
heightmapCopy(_value_original, &_value_modified); TerrainDefinitionClass.copy(_value_original, _value_modified);
_3dview->revert(); _3dview->revert();
updateResolutionLabel();
} }
void DialogHeightMap::angleHChanged(int value) void DialogHeightMap::angleHChanged(int value)
@ -191,7 +175,7 @@ void DialogHeightMap::brushStrengthChanged(int value)
_3dview->setBrushStrength((double)value / 2000.0); _3dview->setBrushStrength((double)value / 2000.0);
} }
void DialogHeightMap::loadFromFile() /*void DialogHeightMap::loadFromFile()
{ {
QString filepath = QFileDialog::getOpenFileName(this, tr("Paysages 3D - Choose a picture to load"), QString(), tr("Images (*.jpg *.jpeg *.bmp *.png)")); QString filepath = QFileDialog::getOpenFileName(this, tr("Paysages 3D - Choose a picture to load"), QString(), tr("Images (*.jpg *.jpeg *.bmp *.png)"));
if (!filepath.isNull()) if (!filepath.isNull())
@ -200,76 +184,4 @@ void DialogHeightMap::loadFromFile()
_3dview->revert(); _3dview->revert();
updateResolutionLabel(); updateResolutionLabel();
} }
} }*/
void DialogHeightMap::resetToTerrain()
{
/*if (_canvas)
{
TerrainDefinition terrain;
terrain = terrainCreateDefinition();
sceneryGetTerrain(&terrain);
heightmapRevertToTerrain(&_value_modified, &terrain, &_canvas->area);
terrainDeleteDefinition(&terrain);
_3dview->revert();
}*/
}
void DialogHeightMap::changeResolution()
{
QString result;
QStringList items;
int current;
items << QString("64 x 64") << QString("128 x 128") << QString("256 x 256") << QString("512 x 512");
current = 1;
if (_value_modified.resolution_x == 64 && _value_modified.resolution_z == 64)
{
current = 0;
}
else if (_value_modified.resolution_x == 256 && _value_modified.resolution_z == 256)
{
current = 2;
}
else if (_value_modified.resolution_x == 512 && _value_modified.resolution_z == 512)
{
current = 3;
}
result = QInputDialog::getItem(this, tr("Paysages 3D - Change heightmap resolution"), tr("Choose the new heightmap resolution.\nBeware that lowering the resolution may imply a loss of accuracy."), items, current, false);
if (!result.isEmpty())
{
int new_res_x, new_res_z;
if (result == QString("64 x 64"))
{
new_res_x = new_res_z = 64;
}
else if (result == QString("256 x 256"))
{
new_res_x = new_res_z = 256;
}
else if (result == QString("512 x 512"))
{
new_res_x = new_res_z = 512;
}
else
{
new_res_x = new_res_z = 128;
}
if (new_res_x != _value_modified.resolution_x or new_res_z != _value_modified.resolution_z)
{
heightmapChangeResolution(&_value_modified, new_res_x, new_res_z);
_3dview->revert();
updateResolutionLabel();
}
}
}
void DialogHeightMap::updateResolutionLabel()
{
_resolution_label->setText(tr("Map resolution : %1 x %2").arg(_value_modified.resolution_x).arg(_value_modified.resolution_z));
}

View file

@ -2,16 +2,16 @@
#define _PAYSAGES_QT_DIALOGHEIGHTMAP_H_ #define _PAYSAGES_QT_DIALOGHEIGHTMAP_H_
#include <QLabel> #include <QLabel>
#include "../lib_paysages/terrain/public.h"
#include "tools.h" #include "tools.h"
#include "widgetheightmap.h" #include "widgetheightmap.h"
#include "../lib_paysages/heightmap.h"
class DialogHeightMap : public DialogWithPreview class DialogHeightMap : public DialogWithPreview
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit DialogHeightMap(QWidget* parent, HeightMap* heightmap, void* canvas); explicit DialogHeightMap(QWidget* parent, TerrainDefinition* terrain);
static bool editHeightMap(QWidget* parent, HeightMap* heightmap, void* canvas); static bool editHeightMap(QWidget* parent, TerrainDefinition* terrain);
public slots: public slots:
virtual void accept(); virtual void accept();
@ -24,16 +24,12 @@ private slots:
void brushSizeChanged(int value); void brushSizeChanged(int value);
void brushSmoothingChanged(int value); void brushSmoothingChanged(int value);
void brushStrengthChanged(int value); void brushStrengthChanged(int value);
void loadFromFile(); //void loadFromFile();
void resetToTerrain();
void changeResolution();
void updateResolutionLabel();
private: private:
HeightMap* _value_original; TerrainDefinition* _value_original;
HeightMap _value_modified; TerrainDefinition* _value_modified;
WidgetHeightMap* _3dview; WidgetHeightMap* _3dview;
QLabel* _resolution_label;
}; };
#endif #endif

View file

@ -7,6 +7,7 @@
#include "../lib_paysages/scenery.h" #include "../lib_paysages/scenery.h"
#include "../lib_paysages/euclid.h" #include "../lib_paysages/euclid.h"
#include "dialogheightmap.h"
static TerrainDefinition* _definition; static TerrainDefinition* _definition;
@ -52,6 +53,7 @@ public:
_renderer.render_quality = 3; _renderer.render_quality = 3;
_renderer.applyTextures = _applyTextures; _renderer.applyTextures = _applyTextures;
_renderer.getLightStatus = _getLightStatus; _renderer.getLightStatus = _getLightStatus;
_renderer.alterLight = _alterLight;
_renderer.camera_location.x = 0.0; _renderer.camera_location.x = 0.0;
_renderer.camera_location.y = 50.0; _renderer.camera_location.y = 50.0;
_renderer.camera_location.z = 0.0; _renderer.camera_location.z = 0.0;
@ -127,6 +129,11 @@ private:
lightingGetStatus((LightingDefinition*)renderer->customData[2], renderer, location, status); lightingGetStatus((LightingDefinition*)renderer->customData[2], renderer, location, status);
} }
static void _alterLight(Renderer* renderer, LightDefinition* light, Vector3 location)
{
*light = renderer->terrain->alterLight(renderer, light, location);
}
}; };
/**************** Form ****************/ /**************** Form ****************/
@ -135,6 +142,9 @@ FormTerrain::FormTerrain(QWidget *parent):
{ {
_definition = (TerrainDefinition*)TerrainDefinitionClass.create(); _definition = (TerrainDefinition*)TerrainDefinitionClass.create();
QPushButton* button = addButton(tr("Paint"));
connect(button, SIGNAL(clicked()), this, SLOT(startPainting()));
previewHeight = new PreviewTerrainHeight(this); previewHeight = new PreviewTerrainHeight(this);
previewColor = new PreviewTerrainColor(this); previewColor = new PreviewTerrainColor(this);
addPreview(previewHeight, tr("Height preview (normalized)")); addPreview(previewHeight, tr("Height preview (normalized)"));
@ -165,3 +175,8 @@ void FormTerrain::configChangeEvent()
TerrainDefinitionClass.validate(_definition); TerrainDefinitionClass.validate(_definition);
BaseForm::configChangeEvent(); BaseForm::configChangeEvent();
} }
void FormTerrain::startPainting()
{
DialogHeightMap::editHeightMap(this, _definition);
}

View file

@ -19,6 +19,9 @@ public slots:
protected slots: protected slots:
virtual void configChangeEvent(); virtual void configChangeEvent();
private slots:
void startPainting();
private: private:
BasePreview* previewHeight; BasePreview* previewHeight;
BasePreview* previewColor; BasePreview* previewColor;

View file

@ -6,7 +6,9 @@
#include <GL/glu.h> #include <GL/glu.h>
#include "tools.h" #include "tools.h"
WidgetHeightMap::WidgetHeightMap(QWidget *parent, HeightMap* heightmap): #define HEIGHTMAP_RESOLUTION 512
WidgetHeightMap::WidgetHeightMap(QWidget *parent, TerrainDefinition* terrain):
QGLWidget(parent) QGLWidget(parent)
{ {
setMinimumSize(500, 500); setMinimumSize(500, 500);
@ -15,22 +17,22 @@ WidgetHeightMap::WidgetHeightMap(QWidget *parent, HeightMap* heightmap):
setCursor(Qt::CrossCursor); setCursor(Qt::CrossCursor);
startTimer(100); startTimer(100);
_heightmap = heightmap; _terrain = terrain;
_vertices = new _VertexInfo[heightmap->resolution_x * heightmap->resolution_z]; _vertices = new _VertexInfo[HEIGHTMAP_RESOLUTION * HEIGHTMAP_RESOLUTION];
_dirty = true; _dirty = true;
_average_frame_time = 0.0; _average_frame_time = 0.0;
_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(); _last_time = QDateTime::currentDateTime();
_mouse_moved = false; _mouse_moved = false;
_angle_h = 0.0; _angle_h = 0.0;
_angle_v = 0.3; _angle_v = 0.3;
_brush_x = 0.0; _brush_x = 0.0;
_brush_z = 0.0; _brush_z = 0.0;
_brush_mode = HEIGHTMAP_BRUSH_RAISE; _brush_mode = HEIGHTMAP_BRUSH_RAISE;
@ -123,11 +125,11 @@ void WidgetHeightMap::mouseMoveEvent(QMouseEvent* event)
// Rotate around the turntable // Rotate around the turntable
int move_x = event->x() - _last_mouse_x; int move_x = event->x() - _last_mouse_x;
int move_y = event->y() - _last_mouse_y; int move_y = event->y() - _last_mouse_y;
_angle_h -= (double)move_x * 0.008; _angle_h -= (double)move_x * 0.008;
_angle_v += (double)move_y * 0.003; _angle_v += (double)move_y * 0.003;
} }
_last_mouse_x = event->x(); _last_mouse_x = event->x();
_last_mouse_y = event->y(); _last_mouse_y = event->y();
_mouse_moved = true; _mouse_moved = true;
@ -140,39 +142,39 @@ void WidgetHeightMap::timerEvent(QTimerEvent*)
QDateTime new_time = QDateTime::currentDateTime(); QDateTime new_time = QDateTime::currentDateTime();
double duration = 0.001 * (double)_last_time.msecsTo(new_time); double duration = 0.001 * (double)_last_time.msecsTo(new_time);
_last_time = new_time; _last_time = new_time;
if (_last_brush_action != 0) if (_last_brush_action != 0)
{ {
double brush_strength; double brush_strength;
HeightMapBrush brush; TerrainBrush brush;
brush.relative_x = (_brush_x + 40.0) / 80.0; brush.relative_x = (_brush_x + 40.0) / 80.0;
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.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 * 20.0); terrainBrushElevation(_terrain, &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)
{ {
heightmapBrushSmooth(_heightmap, &brush, brush_strength * 0.1); terrainBrushSmooth(_terrain, &brush, brush_strength * 0.1);
} }
else else
{ {
heightmapBrushAddNoise(_heightmap, &brush, _brush_noise, brush_strength * 10.0); terrainBrushAddNoise(_terrain, &brush, _brush_noise, brush_strength * 10.0);
} }
break; break;
default: default:
return; return;
} }
// TODO Only mark dirty the updated area // TODO Only mark dirty the updated area
_dirty = true; _dirty = true;
updateGL(); updateGL();
@ -197,7 +199,7 @@ void WidgetHeightMap::initializeGL()
glEnable(GL_LIGHT0); glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1); glEnable(GL_LIGHT1);
glEnable(GL_COLOR_MATERIAL); glEnable(GL_COLOR_MATERIAL);
//glFrontFace(GL_CCW); //glFrontFace(GL_CCW);
//glCullFace(GL_BACK); //glCullFace(GL_BACK);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
@ -222,7 +224,7 @@ void WidgetHeightMap::resizeGL(int w, int h)
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glLoadIdentity(); glLoadIdentity();
gluPerspective(1.57 * 180.0 / M_PI, 1.0, 1.0, 1000.0); gluPerspective(1.57 * 180.0 / M_PI, 1.0, 1.0, 1000.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
} }
@ -232,14 +234,14 @@ void WidgetHeightMap::paintGL()
QTime start_time; QTime start_time;
double frame_time; double frame_time;
int rx, rz; int rx, rz;
// Update vertex cache // Update vertex cache
if (_dirty) if (_dirty)
{ {
updateVertexInfo(); updateVertexInfo();
_dirty = false; _dirty = false;
} }
// Picking mouse position using z-buffer (for brush) // Picking mouse position using z-buffer (for brush)
if (_mouse_moved) if (_mouse_moved)
{ {
@ -263,7 +265,7 @@ void WidgetHeightMap::paintGL()
_brush_z = point.z; _brush_z = point.z;
_mouse_moved = false; _mouse_moved = false;
} }
// Place camera // Place camera
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); glLoadIdentity();
@ -275,13 +277,13 @@ void WidgetHeightMap::paintGL()
light_position[0] = -40.0; light_position[0] = -40.0;
light_position[2] = -60.0; light_position[2] = -60.0;
glLightfv(GL_LIGHT1, GL_POSITION, light_position); glLightfv(GL_LIGHT1, GL_POSITION, light_position);
// Background // Background
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Height map // Height map
rx = _heightmap->resolution_x; rx = HEIGHTMAP_RESOLUTION;
rz = _heightmap->resolution_z; rz = HEIGHTMAP_RESOLUTION;
for (int x = 0; x < rx - 1; x++) for (int x = 0; x < rx - 1; x++)
{ {
glBegin(GL_QUAD_STRIP); glBegin(GL_QUAD_STRIP);
@ -289,7 +291,7 @@ void WidgetHeightMap::paintGL()
{ {
_VertexInfo* vertex = _vertices + z * rx + x; _VertexInfo* vertex = _vertices + z * rx + x;
double diff_x, diff_z, diff; double diff_x, diff_z, diff;
diff_x = (vertex + 1)->point.x - _brush_x; diff_x = (vertex + 1)->point.x - _brush_x;
diff_z = (vertex + 1)->point.z - _brush_z; diff_z = (vertex + 1)->point.z - _brush_z;
diff = sqrt(diff_x * diff_x + diff_z * diff_z); diff = sqrt(diff_x * diff_x + diff_z * diff_z);
@ -308,7 +310,7 @@ void WidgetHeightMap::paintGL()
glColor3d(1.0, 1.0 - diff, 1.0 - diff); glColor3d(1.0, 1.0 - diff, 1.0 - diff);
glNormal3d((vertex + 1)->normal.x, (vertex + 1)->normal.y, (vertex + 1)->normal.z); glNormal3d((vertex + 1)->normal.x, (vertex + 1)->normal.y, (vertex + 1)->normal.z);
glVertex3d((vertex + 1)->point.x, (vertex + 1)->point.y, (vertex + 1)->point.z); glVertex3d((vertex + 1)->point.x, (vertex + 1)->point.y, (vertex + 1)->point.z);
diff_x = vertex->point.x - _brush_x; diff_x = vertex->point.x - _brush_x;
diff_z = vertex->point.z - _brush_z; diff_z = vertex->point.z - _brush_z;
diff = sqrt(diff_x * diff_x + diff_z * diff_z); diff = sqrt(diff_x * diff_x + diff_z * diff_z);
@ -335,7 +337,7 @@ void WidgetHeightMap::paintGL()
frame_time = 0.001 * (double)start_time.msecsTo(QTime::currentTime()); frame_time = 0.001 * (double)start_time.msecsTo(QTime::currentTime());
_average_frame_time = _average_frame_time * 0.8 + frame_time * 0.2; _average_frame_time = _average_frame_time * 0.8 + frame_time * 0.2;
//printf("%d %f\n", quality, average_frame_time); //printf("%d %f\n", quality, average_frame_time);
while ((error_code = glGetError()) != GL_NO_ERROR) while ((error_code = glGetError()) != GL_NO_ERROR)
{ {
logDebug(QString("[OpenGL] ERROR : ") + (const char*)gluErrorString(error_code)); logDebug(QString("[OpenGL] ERROR : ") + (const char*)gluErrorString(error_code));
@ -344,33 +346,33 @@ void WidgetHeightMap::paintGL()
void WidgetHeightMap::updateVertexInfo() void WidgetHeightMap::updateVertexInfo()
{ {
int rx = _heightmap->resolution_x; int rx = HEIGHTMAP_RESOLUTION;
int rz = _heightmap->resolution_z; int rz = HEIGHTMAP_RESOLUTION;
_VertexInfo* old_vertices = _vertices; _VertexInfo* old_vertices = _vertices;
_vertices = new _VertexInfo[rx * rz]; _vertices = new _VertexInfo[rx * rz];
delete[] old_vertices; delete[] old_vertices;
// Update positions // Update positions
for (int x = 0; x < rx; x++) for (int x = 0; x < rx; x++)
{ {
for (int z = 0; z < rz; z++) for (int z = 0; z < rz; z++)
{ {
_VertexInfo* vertex = _vertices + z * rx + x; _VertexInfo* vertex = _vertices + z * rx + x;
vertex->point.x = 80.0 * (double)x / (double)(rx - 1) - 40.0; vertex->point.x = 80.0 * (double)x / (double)(rx - 1) - 40.0;
vertex->point.y = _heightmap->data[z * rx + x]; vertex->point.y = 0.0; //_heightmap->data[z * rx + x];
vertex->point.z = 80.0 * (double)z / (double)(rz - 1) - 40.0; vertex->point.z = 80.0 * (double)z / (double)(rz - 1) - 40.0;
} }
} }
// Update normals // Update normals
for (int x = 0; x < rx; x++) for (int x = 0; x < rx; x++)
{ {
for (int z = 0; z < rz; z++) for (int z = 0; z < rz; z++)
{ {
_VertexInfo* vertex = _vertices + z * rx + x; _VertexInfo* vertex = _vertices + z * rx + x;
if (x == rx - 1) if (x == rx - 1)
{ {
vertex->normal = (vertex - 1)->normal; vertex->normal = (vertex - 1)->normal;
@ -382,10 +384,10 @@ void WidgetHeightMap::updateVertexInfo()
else else
{ {
Vector3 dx, dz; Vector3 dx, dz;
dx = v3Sub((vertex + 1)->point, vertex->point); dx = v3Sub((vertex + 1)->point, vertex->point);
dz = v3Sub((vertex + rx)->point, vertex->point); dz = v3Sub((vertex + rx)->point, vertex->point);
vertex->normal = v3Cross(v3Normalize(dz), v3Normalize(dx)); vertex->normal = v3Cross(v3Normalize(dz), v3Normalize(dx));
} }
} }

View file

@ -4,7 +4,7 @@
#include <QGLWidget> #include <QGLWidget>
#include <QDateTime> #include <QDateTime>
#include "../lib_paysages/euclid.h" #include "../lib_paysages/euclid.h"
#include "../lib_paysages/heightmap.h" #include "../lib_paysages/terrain/public.h"
typedef struct typedef struct
{ {
@ -22,16 +22,16 @@ class WidgetHeightMap : public QGLWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
WidgetHeightMap(QWidget* parent, HeightMap* heightmap); WidgetHeightMap(QWidget* parent, TerrainDefinition* terrain);
~WidgetHeightMap(); ~WidgetHeightMap();
void setHorizontalViewAngle(double angle_h); void setHorizontalViewAngle(double angle_h);
void setVerticalViewAngle(double angle_v); void setVerticalViewAngle(double angle_v);
void setBrushMode(HeightMapBrushMode mode); void setBrushMode(HeightMapBrushMode mode);
void setBrushSize(double size); void setBrushSize(double size);
void setBrushSmoothing(double smoothing); void setBrushSmoothing(double smoothing);
void setBrushStrength(double smoothing); void setBrushStrength(double smoothing);
public slots: public slots:
void revert(); void revert();
@ -39,33 +39,33 @@ protected:
void mousePressEvent(QMouseEvent* event); void mousePressEvent(QMouseEvent* event);
void mouseReleaseEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent* event);
void mouseMoveEvent(QMouseEvent* event); void mouseMoveEvent(QMouseEvent* event);
void timerEvent(QTimerEvent* event); void timerEvent(QTimerEvent* event);
void initializeGL(); void initializeGL();
void resizeGL(int w, int h); void resizeGL(int w, int h);
void paintGL(); void paintGL();
private: private:
void updateVertexInfo(); void updateVertexInfo();
private: private:
HeightMap* _heightmap; TerrainDefinition* _terrain;
_VertexInfo* _vertices; _VertexInfo* _vertices;
bool _dirty; bool _dirty;
double _average_frame_time; double _average_frame_time;
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; QDateTime _last_time;
bool _mouse_moved; bool _mouse_moved;
double _angle_h; double _angle_h;
double _angle_v; double _angle_v;
double _brush_x; double _brush_x;
double _brush_z; double _brush_z;
HeightMapBrushMode _brush_mode; HeightMapBrushMode _brush_mode;

View file

@ -1,55 +0,0 @@
#ifndef _PAYSAGES_HEIGHTMAP_H_
#define _PAYSAGES_HEIGHTMAP_H_
/* Height map for terrain */
#include "pack.h"
#include "noise.h"
#include "geoarea.h"
#include "terrain/public.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
int resolution_x;
int resolution_z;
double* data;
} HeightMap;
typedef struct
{
double relative_x;
double relative_z;
double hard_radius;
double smoothed_size;
double total_radius;
} HeightMapBrush;
HeightMap heightmapCreate();
void heightmapDelete(HeightMap* heightmap);
void heightmapCopy(HeightMap* source, HeightMap* destination);
void heightmapValidate(HeightMap* heightmap);
void heightmapSave(PackStream* stream, HeightMap* heightmap);
void heightmapLoad(PackStream* stream, HeightMap* heightmap);
void heightmapGetLimits(HeightMap* heightmap, double* ymin, double* ymax);
double heightmapGetRawValue(HeightMap* heightmap, double x, double z);
double heightmapGetValue(HeightMap* heightmap, double x, double z);
void heightmapChangeResolution(HeightMap* heightmap, int resolution_x, int resolution_z);
void heightmapImportFromPicture(HeightMap* heightmap, const char* picturepath);
void heightmapRevertToTerrain(HeightMap* heightmap, TerrainDefinition* terrain, GeoArea* area);
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
}
#endif
#endif

View file

@ -84,7 +84,13 @@ static double _fakeGetHeight(Renderer* renderer, double x, double z)
static double _getHeight(Renderer* renderer, double x, double z) static double _getHeight(Renderer* renderer, double x, double z)
{ {
TerrainDefinition* definition = renderer->terrain->definition; TerrainDefinition* definition = renderer->terrain->definition;
return noiseGet2DTotal(definition->_height_noise, x / definition->scaling, z / definition->scaling) * definition->height; x /= definition->scaling;
z /= definition->scaling;
double height = noiseGet2DTotal(definition->_height_noise, x, z);
/* TODO Apply paintings */
return height * definition->height;
} }
static Color _fakeGetFinalColor(Renderer* renderer, Vector3 location, double precision) static Color _fakeGetFinalColor(Renderer* renderer, Vector3 location, double precision)

View file

@ -1,57 +1,50 @@
#include "heightmap.h" #include "private.h"
/*
* Terrain height map painting.
*/
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include "tools.h"
#include "system.h"
#include "noise.h"
HeightMap heightmapCreate() TerrainHeightMap terrainHeightMapCreate()
{ {
HeightMap result; TerrainHeightMap result;
result.data = malloc(sizeof(double)); /*result.data = malloc(sizeof(double));
result.resolution_x = 1; result.resolution_x = 1;
result.resolution_z = 1; result.resolution_z = 1;*/
return result; return result;
} }
void heightmapDelete(HeightMap* heightmap) void terrainHeightmapDelete(TerrainHeightMap* heightmap)
{ {
free(heightmap->data); /*free(heightmap->data);*/
} }
void heightmapCopy(HeightMap* source, HeightMap* destination) void terrainHeightmapCopy(TerrainHeightMap* source, TerrainHeightMap* destination)
{ {
destination->resolution_x = source->resolution_x; /*destination->resolution_x = source->resolution_x;
destination->resolution_z = source->resolution_z; destination->resolution_z = source->resolution_z;
destination->data = realloc(destination->data, sizeof(double) * destination->resolution_x * destination->resolution_z); destination->data = realloc(destination->data, sizeof(double) * destination->resolution_x * destination->resolution_z);
memcpy(destination->data, source->data, sizeof(double) * destination->resolution_x * destination->resolution_z); memcpy(destination->data, source->data, sizeof(double) * destination->resolution_x * destination->resolution_z);*/
} }
void heightmapValidate(HeightMap* heightmap) void terrainHeightmapSave(PackStream* stream, TerrainHeightMap* heightmap)
{ {
UNUSED(heightmap); /*int i;
}
void heightmapSave(PackStream* stream, HeightMap* heightmap)
{
int i;
packWriteInt(stream, &heightmap->resolution_x); packWriteInt(stream, &heightmap->resolution_x);
packWriteInt(stream, &heightmap->resolution_z); packWriteInt(stream, &heightmap->resolution_z);
for (i = 0; i < heightmap->resolution_x * heightmap->resolution_z; i++) for (i = 0; i < heightmap->resolution_x * heightmap->resolution_z; i++)
{ {
packWriteDouble(stream, &heightmap->data[i]); packWriteDouble(stream, &heightmap->data[i]);
} }*/
} }
void heightmapLoad(PackStream* stream, HeightMap* heightmap) void terrainHeightmapLoad(PackStream* stream, TerrainHeightMap* heightmap)
{ {
int i; /*int i;
packReadInt(stream, &heightmap->resolution_x); packReadInt(stream, &heightmap->resolution_x);
packReadInt(stream, &heightmap->resolution_z); packReadInt(stream, &heightmap->resolution_z);
@ -59,9 +52,22 @@ void heightmapLoad(PackStream* stream, HeightMap* heightmap)
for (i = 0; i < heightmap->resolution_x * heightmap->resolution_z; i++) for (i = 0; i < heightmap->resolution_x * heightmap->resolution_z; i++)
{ {
packReadDouble(stream, &heightmap->data[i]); packReadDouble(stream, &heightmap->data[i]);
} }*/
} }
void terrainBrushElevation(TerrainDefinition* heightmap, TerrainBrush* brush, double value)
{
}
void terrainBrushSmooth(TerrainDefinition* heightmap, TerrainBrush* brush, double value)
{
}
void terrainBrushAddNoise(TerrainDefinition* heightmap, TerrainBrush* brush, NoiseGenerator* generator, double value)
{
}
#if 0
static void _loadFromFilePixel(HeightMap* heightmap, int x, int y, Color col) static void _loadFromFilePixel(HeightMap* heightmap, int x, int y, Color col)
{ {
assert(x >= 0 && x < heightmap->resolution_x); assert(x >= 0 && x < heightmap->resolution_x);
@ -184,7 +190,7 @@ void heightmapRevertToTerrain(HeightMap* heightmap, TerrainDefinition* terrain,
} }
static inline void _getBrushBoundaries(HeightMapBrush* brush, int rx, int rz, int* x1, int* x2, int* z1, int* z2) static inline void _getBrushBoundaries(TerrainBrush* brush, int rx, int rz, int* x1, int* x2, int* z1, int* z2)
{ {
double cx = brush->relative_x * rx; double cx = brush->relative_x * rx;
double cz = brush->relative_z * rz; double cz = brush->relative_z * rz;
@ -229,9 +235,9 @@ static inline void _getBrushBoundaries(HeightMapBrush* brush, int rx, int rz, in
} }
} }
typedef double (*BrushCallback)(HeightMap* heightmap, HeightMapBrush* brush, double x, double z, double basevalue, double influence, double force, void* data); typedef double (*BrushCallback)(HeightMap* heightmap, TerrainBrush* 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) static inline void _applyBrush(HeightMap* heightmap, TerrainBrush* 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, influence; double dx, dz, distance, influence;
@ -267,17 +273,17 @@ static inline void _applyBrush(HeightMap* heightmap, HeightMapBrush* brush, doub
} }
} }
static double _applyBrushElevation(HeightMap* heightmap, HeightMapBrush* brush, double x, double z, double basevalue, double influence, double force, void* data) static double _applyBrushElevation(HeightMap* heightmap, TerrainBrush* brush, double x, double z, double basevalue, double influence, double force, void* data)
{ {
return basevalue + influence * force * brush->total_radius; return basevalue + influence * force * brush->total_radius;
} }
void heightmapBrushElevation(HeightMap* heightmap, HeightMapBrush* brush, double value) void terrainBrushElevation(HeightMap* heightmap, TerrainBrush* brush, double value)
{ {
_applyBrush(heightmap, brush, value, NULL, _applyBrushElevation); _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) static double _applyBrushSmooth(HeightMap* heightmap, TerrainBrush* brush, double x, double z, double basevalue, double influence, double force, void* data)
{ {
double ideal, factor; double ideal, factor;
ideal = heightmapGetValue(heightmap, x + brush->total_radius * 0.5, z); ideal = heightmapGetValue(heightmap, x + brush->total_radius * 0.5, z);
@ -293,17 +299,18 @@ static double _applyBrushSmooth(HeightMap* heightmap, HeightMapBrush* brush, dou
return basevalue + (ideal - basevalue) * factor; return basevalue + (ideal - basevalue) * factor;
} }
void heightmapBrushSmooth(HeightMap* heightmap, HeightMapBrush* brush, double value) void terrainBrushSmooth(HeightMap* heightmap, TerrainBrush* brush, double value)
{ {
_applyBrush(heightmap, brush, value, NULL, _applyBrushSmooth); _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) static double _applyBrushAddNoise(HeightMap* heightmap, TerrainBrush* 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; 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) void terrainBrushAddNoise(HeightMap* heightmap, TerrainBrush* brush, NoiseGenerator* generator, double value)
{ {
_applyBrush(heightmap, brush, value, generator, _applyBrushAddNoise); _applyBrush(heightmap, brush, value, generator, _applyBrushAddNoise);
} }
#endif

View file

@ -11,10 +11,10 @@ void terrainAutoPreset(TerrainDefinition* definition, TerrainPreset preset)
{ {
case TERRAIN_PRESET_STANDARD: case TERRAIN_PRESET_STANDARD:
noiseClearLevels(definition->_height_noise); noiseClearLevels(definition->_height_noise);
noiseAddLevelsSimple(definition->_height_noise, 10, 1.0, 1.0); noiseAddLevelsSimple(definition->_height_noise, 8, 12.8, 12.8); /* Detail = 0.1 */
noiseSetFunctionParams(definition->_height_noise, NOISE_FUNCTION_SIMPLEX, -0.2); noiseSetFunctionParams(definition->_height_noise, NOISE_FUNCTION_SIMPLEX, 0.0);
definition->height = 12.0 / noiseGetMaxValue(definition->_height_noise); definition->height = 2.0;
definition->scaling = 80.0; definition->scaling = 10.0;
definition->shadow_smoothing = 0.03; definition->shadow_smoothing = 0.03;
break; break;
default: default:

View file

@ -1,4 +1,25 @@
#ifndef _PAYSAGES_TERRAIN_PRIVATE_H_ #ifndef _PAYSAGES_TERRAIN_PRIVATE_H_
#define _PAYSAGES_TERRAIN_PRIVATE_H_ #define _PAYSAGES_TERRAIN_PRIVATE_H_
#include "public.h"
#define TERRAIN_HEIGHTMAP_DETAIL 0.1
typedef struct
{
int xstart;
int ystart;
int xsize;
int ysize;
void* data;
} TerrainHeightMapData;
typedef struct
{
int fixed_count;
TerrainHeightMapData* fixed_data;
int floating_count;
TerrainHeightMapData* floating_data;
} TerrainHeightMap;
#endif #endif

View file

@ -49,6 +49,19 @@ void terrainRenderSurface(Renderer* renderer);
/*Renderer terrainCreatePreviewRenderer(); /*Renderer terrainCreatePreviewRenderer();
Color terrainGetPreview(Renderer* renderer, double x, double y);*/ Color terrainGetPreview(Renderer* renderer, double x, double y);*/
typedef struct
{
double relative_x;
double relative_z;
double hard_radius;
double smoothed_size;
double total_radius;
} TerrainBrush;
void terrainBrushElevation(TerrainDefinition* heightmap, TerrainBrush* brush, double value);
void terrainBrushSmooth(TerrainDefinition* heightmap, TerrainBrush* brush, double value);
void terrainBrushAddNoise(TerrainDefinition* heightmap, TerrainBrush* brush, NoiseGenerator* generator, double value);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif