paysages: Terrain painting dialog (WIP)

git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@563 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
Michaël Lemaire 2013-05-05 13:37:06 +00:00 committed by ThunderK
parent b7b483f673
commit 1a193f4e78
20 changed files with 1214 additions and 344 deletions

7
TODO
View file

@ -1,7 +1,6 @@
Technology Preview 2 :
- Finalize terrain editor.
=> Add a generation dialog for base noise (overwriting changes).
=> Implement chunks merging (with max size control).
- Get rid of noise dialogs, for simpler settings.
- Finalize lighting/clouds refactoring
=> Restore cloud lighting
@ -14,10 +13,8 @@ Technology Preview 2 :
- Translations.
Technlogy Preview 3 :
- Start using unit testing.
- Improve terrain 3D editor:
=> Add a map preview with edit area highlighted.
=> Allow zooming and simplified camera control.
- Start an undo/redo system ?
- Add a map preview to terrain editor.
- Better time selection widget for atmosphere.
- Clouds should keep distance to ground.
- Find a proper model for night sky (maybe Shirley).

7
data/ui_pictures.qrc Normal file
View file

@ -0,0 +1,7 @@
<RCC>
<qresource prefix="/buttons/logo">
<file>images/apply.png</file>
<file>images/cancel.png</file>
<file>images/revert.png</file>
</qresource>
</RCC>

View file

@ -0,0 +1,32 @@
#include "widgetglobalformbuttons.h"
#include "ui_widgetglobalformbuttons.h"
WidgetGlobalFormButtons::WidgetGlobalFormButtons(QWidget *parent) :
QWidget(parent),
ui(new Ui::WidgetGlobalFormButtons)
{
QPushButton* button;
ui->setupUi(this);
button = findChild<QPushButton*>("button_ok");
if (button)
{
connect(button, SIGNAL(clicked()), this, SIGNAL(okClicked()));
}
button = findChild<QPushButton*>("button_cancel");
if (button)
{
connect(button, SIGNAL(clicked()), this, SIGNAL(cancelClicked()));
}
button = findChild<QPushButton*>("button_revert");
if (button)
{
connect(button, SIGNAL(clicked()), this, SIGNAL(revertClicked()));
}
}
WidgetGlobalFormButtons::~WidgetGlobalFormButtons()
{
delete ui;
}

View file

@ -0,0 +1,27 @@
#ifndef WIDGETGLOBALFORMBUTTONS_H
#define WIDGETGLOBALFORMBUTTONS_H
#include <QWidget>
namespace Ui {
class WidgetGlobalFormButtons;
}
class WidgetGlobalFormButtons : public QWidget
{
Q_OBJECT
public:
explicit WidgetGlobalFormButtons(QWidget *parent = 0);
~WidgetGlobalFormButtons();
signals:
void okClicked();
void revertClicked();
void cancelClicked();
private:
Ui::WidgetGlobalFormButtons *ui;
};
#endif // WIDGETGLOBALFORMBUTTONS_H

View file

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>WidgetGlobalFormButtons</class>
<widget class="QWidget" name="WidgetGlobalFormButtons">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>560</width>
<height>43</height>
</rect>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>50</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="button_cancel">
<property name="minimumSize">
<size>
<width>0</width>
<height>25</height>
</size>
</property>
<property name="text">
<string>Cancel</string>
</property>
<property name="icon">
<iconset resource="../../../data/ui_pictures.qrc">
<normaloff>:/buttons/logo/images/cancel.png</normaloff>:/buttons/logo/images/cancel.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="button_revert">
<property name="minimumSize">
<size>
<width>0</width>
<height>25</height>
</size>
</property>
<property name="text">
<string>Revert modifications</string>
</property>
<property name="icon">
<iconset resource="../../../data/ui_pictures.qrc">
<normaloff>:/buttons/logo/images/revert.png</normaloff>:/buttons/logo/images/revert.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="button_ok">
<property name="minimumSize">
<size>
<width>0</width>
<height>25</height>
</size>
</property>
<property name="text">
<string>Validate</string>
</property>
<property name="icon">
<iconset resource="../../../data/ui_pictures.qrc">
<normaloff>:/buttons/logo/images/apply.png</normaloff>:/buttons/logo/images/apply.png</iconset>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../../../data/ui_pictures.qrc"/>
</resources>
<connections/>
<slots>
<signal>applyClicked()</signal>
<signal>revertClicked()</signal>
<signal>cancelClicked()</signal>
</slots>
</ui>

View file

@ -1,171 +0,0 @@
#include "dialogheightmap.h"
#include <QLabel>
#include <QBoxLayout>
#include <QGridLayout>
#include <QPushButton>
#include <QComboBox>
#include <QSlider>
#include <QFileDialog>
#include <QInputDialog>
#include <math.h>
#include "rendering/scenery.h"
#include "widgetheightmap.h"
/**************** Dialog form ****************/
DialogHeightMap::DialogHeightMap(QWidget* parent, TerrainDefinition* terrain) : DialogWithPreview(parent)
{
QWidget* mainarea;
QWidget* buttons;
QWidget* panel;
QLabel* label;
QSlider* slider;
QPushButton* button;
QComboBox* combobox;
_value_original = terrain;
_value_modified = (TerrainDefinition*)TerrainDefinitionClass.create();
TerrainDefinitionClass.copy(_value_original, _value_modified);
setLayout(new QVBoxLayout());
// Dialog layout (main area + buttons)
mainarea = new QWidget(this);
mainarea->setLayout(new QHBoxLayout());
this->layout()->addWidget(mainarea);
buttons = new QWidget(this);
buttons->setLayout(new QHBoxLayout());
buttons->layout()->setAlignment(buttons, Qt::AlignBottom);
this->layout()->addWidget(buttons);
// Main area layout (viewer + panel)
_3dview = new WidgetHeightMap(mainarea, _value_modified);
connect(_3dview, SIGNAL(heightmapChanged()), this, SLOT(heightmapChanged()));
mainarea->layout()->addWidget(_3dview);
panel = new QWidget(mainarea);
panel->setLayout(new QVBoxLayout());
mainarea->layout()->addWidget(panel);
mainarea->layout()->setAlignment(panel, Qt::AlignTop);
// Panel layout
_info_memory = new QLabel(panel);
panel->layout()->addWidget(_info_memory);
/*button = new QPushButton(tr("Load from picture file"), panel);
connect(button, SIGNAL(clicked()), this, SLOT(loadFromFile()));
panel->layout()->addWidget(button);*/
combobox = new QComboBox(panel);
combobox->addItem(tr("Raise / lower"));
combobox->addItem(tr("Add noise / smooth"));
combobox->addItem(tr("Restore to original"));
connect(combobox, SIGNAL(currentIndexChanged(int)), this, SLOT(brushModeChanged(int)));
panel->layout()->addWidget(combobox);
label = new QLabel(tr("Brush size"), panel);
panel->layout()->addWidget(label);
slider = new QSlider(Qt::Horizontal, panel);
slider->setRange(6, 300);
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(brushSizeChanged(int)));
panel->layout()->addWidget(slider);
slider->setValue(60);
label = new QLabel(tr("Brush smoothing"), panel);
panel->layout()->addWidget(label);
slider = new QSlider(Qt::Horizontal, panel);
slider->setRange(0, 1000);
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(brushSmoothingChanged(int)));
panel->layout()->addWidget(slider);
slider->setValue(600);
label = new QLabel(tr("Brush strength"), panel);
panel->layout()->addWidget(label);
slider = new QSlider(Qt::Horizontal, panel);
slider->setRange(0, 1000);
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(brushStrengthChanged(int)));
panel->layout()->addWidget(slider);
slider->setValue(200);
// Buttons layout
button = new QPushButton(tr("Cancel"), buttons);
button->setIcon(QIcon(getDataPath("images/cancel.png")));
buttons->layout()->addWidget(button);
QObject::connect(button, SIGNAL(clicked()), this, SLOT(reject()));
button = new QPushButton(tr("Revert"), buttons);
button->setIcon(QIcon(getDataPath("images/revert.png")));
buttons->layout()->addWidget(button);
QObject::connect(button, SIGNAL(clicked()), this, SLOT(revert()));
button = new QPushButton(tr("Validate"), buttons);
button->setIcon(QIcon(getDataPath("images/apply.png")));
buttons->layout()->addWidget(button);
QObject::connect(button, SIGNAL(clicked()), this, SLOT(accept()));
setWindowTitle(tr("Paysages 3D - Height map painting"));
}
bool DialogHeightMap::editHeightMap(QWidget* parent, TerrainDefinition* terrain)
{
int result;
DialogHeightMap* dialog = new DialogHeightMap(parent, terrain);
result = dialog->exec();
delete dialog;
return (result != 0) ? true : false;
}
void DialogHeightMap::accept()
{
TerrainDefinitionClass.copy(_value_modified, _value_original);
QDialog::accept();
}
void DialogHeightMap::revert()
{
TerrainDefinitionClass.copy(_value_original, _value_modified);
_3dview->revert();
}
void DialogHeightMap::brushModeChanged(int value)
{
_3dview->setBrushMode((HeightMapBrushMode)value);
}
void DialogHeightMap::brushSizeChanged(int value)
{
_3dview->setBrushSize((double)value / 10.0);
}
void DialogHeightMap::brushSmoothingChanged(int value)
{
_3dview->setBrushSmoothing((double)value / 1000.0);
}
void DialogHeightMap::brushStrengthChanged(int value)
{
_3dview->setBrushStrength((double)value / 2000.0);
}
void DialogHeightMap::heightmapChanged()
{
_info_memory->setText(tr("Memory used: %1").arg(_3dview->getMemoryStats()));
}
/*void DialogHeightMap::loadFromFile()
{
QString filepath = QFileDialog::getOpenFileName(this, tr("Paysages 3D - Choose a picture to load"), QString(), tr("Images (*.jpg *.jpeg *.bmp *.png)"));
if (!filepath.isNull())
{
heightmapImportFromPicture(&_value_modified, (char*) filepath.toStdString().c_str());
_3dview->revert();
updateResolutionLabel();
}
}*/

View file

@ -1,35 +0,0 @@
#ifndef _PAYSAGES_QT_DIALOGHEIGHTMAP_H_
#define _PAYSAGES_QT_DIALOGHEIGHTMAP_H_
#include <QLabel>
#include "rendering/terrain/public.h"
#include "tools.h"
#include "widgetheightmap.h"
class DialogHeightMap : public DialogWithPreview
{
Q_OBJECT
public:
explicit DialogHeightMap(QWidget* parent, TerrainDefinition* terrain);
static bool editHeightMap(QWidget* parent, TerrainDefinition* terrain);
public slots:
virtual void accept();
void revert();
private slots:
void brushModeChanged(int value);
void brushSizeChanged(int value);
void brushSmoothingChanged(int value);
void brushStrengthChanged(int value);
void heightmapChanged();
//void loadFromFile();
private:
TerrainDefinition* _value_original;
TerrainDefinition* _value_modified;
QLabel* _info_memory;
WidgetHeightMap* _3dview;
};
#endif

View file

@ -4,6 +4,7 @@
#include <QSlider>
#include "tools.h"
#include "dialogheightmap.h"
#include "terrain/dialogterrainpainting.h"
#include "rendering/scenery.h"
static TerrainDefinition* _definition;
@ -76,8 +77,12 @@ void FormTerrain::configChangeEvent()
void FormTerrain::startPainting()
{
if (DialogHeightMap::editHeightMap(this, _definition))
DialogTerrainPainting* dialog = new DialogTerrainPainting(this, _definition);
dialog->exec();
delete dialog;
/*if (DialogHeightMap::editHeightMap(this, _definition))
{
configChangeEvent();
}
}*/
}

View file

@ -17,9 +17,104 @@ LIBS += -lGLU
unix:LIBS += -L$$DESTDIR -lpaysages_rendering -lpaysages_exploring
win32:LIBS += ../libpaysages.a ../libpaysages_exploring.a -lDevIL -lILU -lILUT -lglib-2.0 -lgthread-2.0
HEADERS += $$files(*.h) $$files(../rendering/*.h) $$files(../rendering/shared/*.h) $$files(../exploring/*.h)
SOURCES += $$files(*.cpp)
TRANSLATIONS = $$PROJECT_PATH/data/i18n/paysages_fr.ts
#system(lupdate paysages-qt.pro)
#system(lrelease $$TRANSLATIONS)
HEADERS += \
widgetheightmap.h \
widgetexplorer.h \
widgetcurveeditor.h \
tools.h \
previewosd.h \
previewmaterial.h \
previewcolorgradation.h \
mainwindow.h \
inputnoise.h \
inputmaterial.h \
inputlayers.h \
inputint.h \
inputenum.h \
inputdouble.h \
inputcurve.h \
inputcolorgradation.h \
inputcolor.h \
inputcamera.h \
inputboolean.h \
formwater.h \
formtextures.h \
formterrain.h \
formrender.h \
formmaterial.h \
formclouds.h \
formatmosphere.h \
explorerchunkterrain.h \
explorerchunksky.h \
dialogrender.h \
dialognoise.h \
dialogmaterial.h \
dialoglayers.h \
dialogexplorer.h \
dialogcurve.h \
dialogcolorgradation.h \
basepreview.h \
baseinput.h \
baseformlayer.h \
baseform.h \
baseexplorerchunk.h \
terrain/dialogterrainpainting.h \
common/widgetglobalformbuttons.h \
terrain/paintingbrush.h
SOURCES += \
widgetheightmap.cpp \
widgetexplorer.cpp \
widgetcurveeditor.cpp \
tools.cpp \
previewosd.cpp \
previewmaterial.cpp \
previewcolorgradation.cpp \
mainwindow.cpp \
inputnoise.cpp \
inputmaterial.cpp \
inputlayers.cpp \
inputint.cpp \
inputenum.cpp \
inputdouble.cpp \
inputcurve.cpp \
inputcolorgradation.cpp \
inputcolor.cpp \
inputcamera.cpp \
inputboolean.cpp \
formwater.cpp \
formtextures.cpp \
formterrain.cpp \
formrender.cpp \
formmaterial.cpp \
formclouds.cpp \
formatmosphere.cpp \
explorerchunkterrain.cpp \
explorerchunksky.cpp \
dialogrender.cpp \
dialognoise.cpp \
dialogmaterial.cpp \
dialoglayers.cpp \
dialogexplorer.cpp \
dialogcurve.cpp \
dialogcolorgradation.cpp \
basepreview.cpp \
baseinput.cpp \
baseformlayer.cpp \
baseform.cpp \
baseexplorerchunk.cpp \
terrain/dialogterrainpainting.cpp \
common/widgetglobalformbuttons.cpp \
terrain/paintingbrush.cpp
FORMS += \
terrain/dialogterrainpainting.ui \
common/widgetglobalformbuttons.ui
RESOURCES += \
../../data/ui_pictures.qrc

View file

@ -0,0 +1,98 @@
#include "dialogterrainpainting.h"
#include "ui_dialogterrainpainting.h"
#include "tools.h"
DialogTerrainPainting::DialogTerrainPainting(QWidget*parent, TerrainDefinition* terrain) :
QDialog(parent),
ui(new Ui::DialogTerrainPainting)
{
ui->setupUi(this);
_terrain_original = terrain;
_terrain_modified = (TerrainDefinition*)TerrainDefinitionClass.create();
revert();
brushConfigChanged();
}
DialogTerrainPainting::~DialogTerrainPainting()
{
delete ui;
}
void DialogTerrainPainting::accept()
{
TerrainDefinitionClass.copy(_terrain_modified, _terrain_original);
QDialog::accept();
}
void DialogTerrainPainting::revert()
{
TerrainDefinitionClass.copy(_terrain_original, _terrain_modified);
WidgetHeightMap* heightmap = findChild<WidgetHeightMap*>("widget_heightmap");
if (heightmap)
{
heightmap->setTerrain(_terrain_modified);
heightmap->setBrush(&_brush);
}
}
void DialogTerrainPainting::brushConfigChanged()
{
QComboBox* combobox;
QSlider* slider;
// Fill brush object
combobox = findChild<QComboBox*>("input_brush_mode");
if (combobox)
{
_brush.setMode((PaintingBrushMode)combobox->currentIndex());
}
slider = findChild<QSlider*>("input_brush_size");
if (slider)
{
_brush.setSize(slider);
}
slider = findChild<QSlider*>("input_brush_smoothing");
if (slider)
{
_brush.setSmoothing(slider);
}
slider = findChild<QSlider*>("input_brush_strength");
if (slider)
{
_brush.setStrength(slider);
}
// Update brush description
// Update brush preview
// Tell to 3D widget
WidgetHeightMap* heightmap = findChild<WidgetHeightMap*>("widget_heightmap");
if (heightmap)
{
heightmap->setBrush(&_brush);
}
}
void DialogTerrainPainting::heightmapChanged()
{
QLabel* label = findChild<QLabel*>("label_memory_consumption");
if (label)
{
qint64 memused = terrainGetMemoryStats(_terrain_modified);
label->setText(tr("Memory used: %1").arg(getHumanMemory(memused)));
// TODO Find available memory
QProgressBar* progress = findChild<QProgressBar*>("progress_memory_consumption");
if (progress)
{
progress->setMaximum(1024);
progress->setValue(memused / 1024);
}
}
}

View file

@ -0,0 +1,34 @@
#ifndef DIALOGTERRAINPAINTING_H
#define DIALOGTERRAINPAINTING_H
#include <QDialog>
#include "paintingbrush.h"
#include "rendering/terrain/public.h"
namespace Ui {
class DialogTerrainPainting;
}
class DialogTerrainPainting : public QDialog
{
Q_OBJECT
public:
explicit DialogTerrainPainting(QWidget *parent, TerrainDefinition* terrain);
~DialogTerrainPainting();
public slots:
void brushConfigChanged();
void heightmapChanged();
virtual void accept();
void revert();
private:
Ui::DialogTerrainPainting *ui;
TerrainDefinition* _terrain_modified;
TerrainDefinition* _terrain_original;
PaintingBrush _brush;
};
#endif // DIALOGTERRAINPAINTING_H

View file

@ -0,0 +1,455 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogTerrainPainting</class>
<widget class="QDialog" name="DialogTerrainPainting">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>912</width>
<height>619</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Paysages 3D - Terrain painting</string>
</property>
<property name="sizeGripEnabled">
<bool>true</bool>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="WidgetHeightMap" name="widget_heightmap" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>400</width>
<height>400</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="verticalWidget" native="true">
<property name="maximumSize">
<size>
<width>450</width>
<height>16777215</height>
</size>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QWidget" name="widget_2" native="true">
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Brush Tool : </string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="input_brush_mode">
<item>
<property name="text">
<string>Raise / Lower (F1)</string>
</property>
</item>
<item>
<property name="text">
<string>Add noise / Smooth (F2)</string>
</property>
</item>
<item>
<property name="text">
<string>Flatten terrain (F3)</string>
</property>
</item>
<item>
<property name="text">
<string>Fix discontinuities (F11)</string>
</property>
</item>
<item>
<property name="text">
<string>Restore to default (F12)</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Brush size :</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSlider" name="input_brush_size">
<property name="minimum">
<number>5</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>20</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Brush smoothing :</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSlider" name="input_brush_smoothing">
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>80</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Brush strength :</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSlider" name="input_brush_strength">
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>20</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string notr="true">{ Brush information }</string>
</property>
<property name="margin">
<number>20</number>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="topMargin">
<number>8</number>
</property>
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<string>Brush preview :</string>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="widget_3" native="true">
<property name="minimumSize">
<size>
<width>200</width>
<height>200</height>
</size>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<widget class="QProgressBar" name="progress_memory_consumption">
<property name="maximumSize">
<size>
<width>150</width>
<height>16777215</height>
</size>
</property>
<property name="value">
<number>24</number>
</property>
<property name="textVisible">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_memory_consumption">
<property name="text">
<string notr="true">{ memory consumption }</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="WidgetGlobalFormButtons" name="widget_4" native="true">
<property name="minimumSize">
<size>
<width>100</width>
<height>30</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>WidgetGlobalFormButtons</class>
<extends>QWidget</extends>
<header>common/widgetglobalformbuttons.h</header>
<container>1</container>
<slots>
<signal>okClicked()</signal>
<signal>revertClicked()</signal>
<signal>cancelClicked()</signal>
</slots>
</customwidget>
<customwidget>
<class>WidgetHeightMap</class>
<extends>QWidget</extends>
<header>widgetheightmap.h</header>
<container>1</container>
<slots>
<signal>heightmapChanged()</signal>
</slots>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>input_brush_mode</tabstop>
<tabstop>input_brush_size</tabstop>
<tabstop>input_brush_smoothing</tabstop>
<tabstop>input_brush_strength</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>input_brush_size</sender>
<signal>valueChanged(int)</signal>
<receiver>DialogTerrainPainting</receiver>
<slot>brushConfigChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>676</x>
<y>67</y>
</hint>
<hint type="destinationlabel">
<x>437</x>
<y>72</y>
</hint>
</hints>
</connection>
<connection>
<sender>input_brush_smoothing</sender>
<signal>valueChanged(int)</signal>
<receiver>DialogTerrainPainting</receiver>
<slot>brushConfigChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>728</x>
<y>97</y>
</hint>
<hint type="destinationlabel">
<x>437</x>
<y>102</y>
</hint>
</hints>
</connection>
<connection>
<sender>input_brush_strength</sender>
<signal>valueChanged(int)</signal>
<receiver>DialogTerrainPainting</receiver>
<slot>brushConfigChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>762</x>
<y>135</y>
</hint>
<hint type="destinationlabel">
<x>437</x>
<y>132</y>
</hint>
</hints>
</connection>
<connection>
<sender>input_brush_mode</sender>
<signal>currentIndexChanged(int)</signal>
<receiver>DialogTerrainPainting</receiver>
<slot>brushConfigChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>752</x>
<y>42</y>
</hint>
<hint type="destinationlabel">
<x>437</x>
<y>40</y>
</hint>
</hints>
</connection>
<connection>
<sender>widget_heightmap</sender>
<signal>heightmapChanged()</signal>
<receiver>DialogTerrainPainting</receiver>
<slot>heightmapChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>396</x>
<y>566</y>
</hint>
<hint type="destinationlabel">
<x>445</x>
<y>618</y>
</hint>
</hints>
</connection>
<connection>
<sender>widget_4</sender>
<signal>okClicked()</signal>
<receiver>DialogTerrainPainting</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>816</x>
<y>593</y>
</hint>
<hint type="destinationlabel">
<x>683</x>
<y>615</y>
</hint>
</hints>
</connection>
<connection>
<sender>widget_4</sender>
<signal>cancelClicked()</signal>
<receiver>DialogTerrainPainting</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>870</x>
<y>600</y>
</hint>
<hint type="destinationlabel">
<x>711</x>
<y>618</y>
</hint>
</hints>
</connection>
<connection>
<sender>widget_4</sender>
<signal>revertClicked()</signal>
<receiver>DialogTerrainPainting</receiver>
<slot>revert()</slot>
<hints>
<hint type="sourcelabel">
<x>827</x>
<y>606</y>
</hint>
<hint type="destinationlabel">
<x>747</x>
<y>618</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>brushConfigChanged()</slot>
<slot>heightmapChanged()</slot>
<slot>revert()</slot>
</slots>
</ui>

View file

@ -0,0 +1,120 @@
#include "paintingbrush.h"
#include <cmath>
PaintingBrush::PaintingBrush()
{
_mode = PAINTING_BRUSH_RAISE;
_size = 0.0;
_smoothing = 0.0;
_strength = 0.0;
_noise = noiseCreateGenerator();
noiseAddLevelsSimple(_noise, 10, 1.0, -0.5, 0.5, 0.5);
}
PaintingBrush::~PaintingBrush()
{
noiseDeleteGenerator(_noise);
}
void PaintingBrush::setMode(PaintingBrushMode mode)
{
_mode = mode;
}
void PaintingBrush::setSize(double value)
{
_size = value;
}
void PaintingBrush::setSize(QAbstractSlider* slider)
{
setSize(20.0 * (double)slider->value() / (double)slider->maximum());
}
void PaintingBrush::setSmoothing(double value)
{
_smoothing = value;
}
void PaintingBrush::setSmoothing(QAbstractSlider* slider)
{
setSmoothing((double)slider->value() / (double)slider->maximum());
}
void PaintingBrush::setStrength(double value)
{
_strength = value;
}
void PaintingBrush::setStrength(QAbstractSlider* slider)
{
setStrength((double)slider->value() / (double)slider->maximum());
}
void PaintingBrush::randomizeNoise()
{
noiseRandomizeOffsets(_noise);
}
double PaintingBrush::getInfluence(double relative_x, double relative_z)
{
double distance = sqrt(relative_x * relative_x + relative_z * relative_z);
if (distance > _size)
{
return 0.0;
}
else if (distance > _size * (1.0 - _smoothing))
{
return 1.0 - (distance - _size * (1.0 - _smoothing)) / (_size * _smoothing);
}
else
{
return 1.0;
}
}
void PaintingBrush::drawPreview(QWidget* widget)
{
}
void PaintingBrush::applyToTerrain(TerrainDefinition* terrain, double x, double z, double duration, bool reverse)
{
double brush_strength;
TerrainBrush brush;
brush.relative_x = x;
brush.relative_z = z;
brush.hard_radius = _size * (1.0 - _smoothing);
brush.smoothed_size = _size * _smoothing;
brush.total_radius = brush.hard_radius + brush.smoothed_size;
brush_strength = 0.5 * _strength * duration / 0.1;
switch (_mode)
{
case PAINTING_BRUSH_RAISE:
if (reverse)
{
brush_strength = -brush_strength;
}
terrainBrushElevation(terrain->height_map, &brush, brush_strength * 2.0);
break;
case PAINTING_BRUSH_SMOOTH:
if (reverse)
{
terrainBrushSmooth(terrain->height_map, &brush, brush_strength);
}
else
{
terrainBrushAddNoise(terrain->height_map, &brush, _noise, brush_strength * 0.5);
}
break;
case PAINTING_BRUSH_RESTORE:
terrainBrushReset(terrain->height_map, &brush, brush_strength);
break;
default:
return;
}
}

View file

@ -0,0 +1,46 @@
#ifndef PAINTINGBRUSH_H
#define PAINTINGBRUSH_H
#include <QAbstractSlider>
#include "rendering/noise.h"
#include "rendering/terrain/public.h"
typedef enum
{
PAINTING_BRUSH_RAISE = 0,
PAINTING_BRUSH_SMOOTH = 1,
PAINTING_BRUSH_FLATTEN = 2,
PAINTING_BRUSH_FIX_DISCONTINUITIES = 3,
PAINTING_BRUSH_RESTORE = 4
} PaintingBrushMode;
class PaintingBrush
{
public:
PaintingBrush();
~PaintingBrush();
void setMode(PaintingBrushMode mode);
void setSize(double value);
void setSize(QAbstractSlider* slider);
void setSmoothing(double value);
void setSmoothing(QAbstractSlider* slider);
void setStrength(double value);
void setStrength(QAbstractSlider* slider);
void randomizeNoise();
double getInfluence(double relative_x, double relative_z);
void drawPreview(QWidget* widget);
void applyToTerrain(TerrainDefinition* terrain, double x, double z, double duration, bool reverse);
private:
PaintingBrushMode _mode;
double _size;
double _smoothing;
double _strength;
NoiseGenerator* _noise;
};
#endif // PAINTINGBRUSH_H

View file

@ -16,3 +16,32 @@ bool DialogWithPreview::event(QEvent* event)
return QDialog::event(event);
}
QString getHumanMemory(qint64 memused)
{
if (memused >= 1024)
{
memused /= 1024;
if (memused >= 1024)
{
memused /= 1024;
if (memused >= 1024)
{
memused /= 1024;
return QObject::tr("%1 GB").arg(memused);
}
else
{
return QObject::tr("%1 MB").arg(memused);
}
}
else
{
return QObject::tr("%1 kB").arg(memused);
}
}
else
{
return QObject::tr("%1 B").arg(memused);
}
}

View file

@ -19,6 +19,8 @@ static inline QString getDataPath(QString path)
return QDir("./data").absoluteFilePath(path);
}
QString getHumanMemory(qint64 memused);
class DialogWithPreview:public QDialog
{
Q_OBJECT

View file

@ -10,7 +10,7 @@
#define HEIGHTMAP_RESOLUTION 256
WidgetHeightMap::WidgetHeightMap(QWidget* parent, TerrainDefinition* terrain) :
WidgetHeightMap::WidgetHeightMap(QWidget* parent) :
QGLWidget(parent)
{
setMinimumSize(500, 500);
@ -19,11 +19,8 @@ QGLWidget(parent)
setCursor(Qt::CrossCursor);
startTimer(100);
_memory_stats = terrainGetMemoryStats(terrain);
_terrain = terrain;
_terrain = NULL;
_renderer = rendererCreate();
TerrainRendererClass.bind(_renderer, _terrain);
_vertices = new _VertexInfo[HEIGHTMAP_RESOLUTION * HEIGHTMAP_RESOLUTION];
_dirty = true;
@ -59,14 +56,9 @@ QGLWidget(parent)
cameraSetZoomToTarget(_top_camera, _zoom);
cameraCopyDefinition(_current_camera, _top_camera);
_brush = NULL;
_brush_x = 0.0;
_brush_z = 0.0;
_brush_mode = HEIGHTMAP_BRUSH_RAISE;
_brush_size = 10.0;
_brush_smoothing = 0.5;
_brush_strength = 1.0;
_brush_noise = noiseCreateGenerator();
noiseAddLevelsSimple(_brush_noise, 10, 1.0, -0.5, 0.5, 0.5);
}
WidgetHeightMap::~WidgetHeightMap()
@ -75,72 +67,23 @@ WidgetHeightMap::~WidgetHeightMap()
cameraDeleteDefinition(_top_camera);
cameraDeleteDefinition(_temp_camera);
rendererDelete(_renderer);
noiseDeleteGenerator(_brush_noise);
delete[] _vertices;
}
void WidgetHeightMap::setBrushMode(HeightMapBrushMode mode)
void WidgetHeightMap::setTerrain(TerrainDefinition* terrain)
{
_brush_mode = mode;
_brush_x = 0.0;
_brush_z = 0.0;
updateGL();
_terrain = terrain;
TerrainRendererClass.bind(_renderer, _terrain);
revert();
}
void WidgetHeightMap::setBrushSize(double size)
void WidgetHeightMap::setBrush(PaintingBrush* brush)
{
_brush_size = size;
_brush_x = 0.0;
_brush_z = 0.0;
_brush = brush;
updateGL();
}
void WidgetHeightMap::setBrushSmoothing(double smoothing)
{
_brush_smoothing = smoothing;
_brush_x = 0.0;
_brush_z = 0.0;
updateGL();
}
void WidgetHeightMap::setBrushStrength(double strength)
{
_brush_strength = strength;
_brush_x = 0.0;
_brush_z = 0.0;
updateGL();
}
QString WidgetHeightMap::getMemoryStats()
{
qint64 memused = _memory_stats;
if (memused >= 1024)
{
memused /= 1024;
if (memused >= 1024)
{
memused /= 1024;
if (memused >= 1024)
{
memused /= 1024;
return tr("%1 GB").arg(memused);
}
else
{
return tr("%1 MB").arg(memused);
}
}
else
{
return tr("%1 kB").arg(memused);
}
}
else
{
return tr("%1 B").arg(memused);
}
}
void WidgetHeightMap::revert()
{
_dirty = true;
@ -205,7 +148,14 @@ void WidgetHeightMap::mousePressEvent(QMouseEvent* event)
void WidgetHeightMap::mouseReleaseEvent(QMouseEvent*)
{
_last_brush_action = 0;
terrainEndBrushStroke(_terrain->height_map);
if (_terrain)
{
terrainEndBrushStroke(_terrain->height_map);
}
if (_brush)
{
_brush->randomizeNoise();
}
}
void WidgetHeightMap::mouseMoveEvent(QMouseEvent* event)
@ -230,6 +180,11 @@ void WidgetHeightMap::mouseMoveEvent(QMouseEvent* event)
void WidgetHeightMap::timerEvent(QTimerEvent*)
{
if (not _terrain)
{
return;
}
QDateTime new_time = QDateTime::currentDateTime();
double duration = 0.001 * (double) _last_time.msecsTo(new_time);
_last_time = new_time;
@ -258,40 +213,9 @@ void WidgetHeightMap::timerEvent(QTimerEvent*)
}
// Apply brush action
if (_last_brush_action != 0)
if (_last_brush_action != 0 && _brush)
{
double brush_strength;
TerrainBrush brush;
brush.relative_x = _brush_x + _target_x;
brush.relative_z = _brush_z + _target_z;
brush.hard_radius = _brush_size * (1.0 - _brush_smoothing);
brush.smoothed_size = _brush_size * _brush_smoothing;
brush.total_radius = brush.hard_radius + brush.smoothed_size;
brush_strength = _brush_strength * duration / 0.1;
switch (_brush_mode)
{
case HEIGHTMAP_BRUSH_RAISE:
terrainBrushElevation(_terrain->height_map, &brush, brush_strength * _last_brush_action * 3.0);
break;
case HEIGHTMAP_BRUSH_SMOOTH:
if (_last_brush_action < 0)
{
terrainBrushSmooth(_terrain->height_map, &brush, brush_strength);
}
else
{
terrainBrushAddNoise(_terrain->height_map, &brush, _brush_noise, brush_strength * 0.5);
}
break;
case HEIGHTMAP_BRUSH_RESTORE:
terrainBrushReset(_terrain->height_map, &brush, brush_strength);
break;
default:
return;
}
_brush->applyToTerrain(_terrain, _brush_x + _target_x, _brush_z + _target_z, duration, _last_brush_action < 0);
// TODO Only mark dirty the updated area
_dirty = true;
@ -378,6 +302,11 @@ void WidgetHeightMap::paintGL()
double frame_time;
int rx, rz;
if (not _terrain)
{
return;
}
rx = HEIGHTMAP_RESOLUTION;
rz = HEIGHTMAP_RESOLUTION;
@ -444,24 +373,23 @@ void WidgetHeightMap::paintGL()
for (int dx = 1; dx >= 0; dx--)
{
_VertexInfo* vertex = _vertices + z * rx + x + dx;
double diff_x, diff_z, diff;
double brush_influence;
diff_x = vertex->point.x - _target_x - _brush_x;
diff_z = vertex->point.z - _target_z - _brush_z;
diff = sqrt(diff_x * diff_x + diff_z * diff_z);
if (diff > _brush_size)
if (_brush)
{
diff = 0.0;
}
else if (diff > _brush_size * (1.0 - _brush_smoothing))
{
diff = 1.0 - (diff - _brush_size * (1.0 - _brush_smoothing)) / (_brush_size * _brush_smoothing);
double diff_x, diff_z;
diff_x = vertex->point.x - _target_x - _brush_x;
diff_z = vertex->point.z - _target_z - _brush_z;
brush_influence = _brush->getInfluence(diff_x, diff_z);
}
else
{
diff = 1.0;
brush_influence = 0.0;
}
glColor3f(0.8 + diff, vertex->painted ? 1.0 : 0.8, 0.8);
glColor3f(0.8 + brush_influence, vertex->painted ? 1.0 : 0.8, 0.8);
glNormal3f(vertex->normal.x, vertex->normal.y, vertex->normal.z);
glVertex3f(vertex->point.x, vertex->point.y, vertex->point.z);
}
@ -567,8 +495,6 @@ void WidgetHeightMap::updateVertexInfo()
_vertices = new _VertexInfo[rx * rz];
delete[] old_vertices;
_memory_stats = terrainGetMemoryStats(_terrain);
_last_update_x = (int) (floor(_target_x));
_last_update_z = (int) (floor(_target_z));

View file

@ -3,6 +3,7 @@
#include <QGLWidget>
#include <QDateTime>
#include "terrain/paintingbrush.h"
#include "rendering/camera.h"
#include "rendering/tools/euclid.h"
#include "rendering/renderer.h"
@ -26,15 +27,11 @@ class WidgetHeightMap : public QGLWidget
{
Q_OBJECT
public:
WidgetHeightMap(QWidget* parent, TerrainDefinition* terrain);
WidgetHeightMap(QWidget* parent);
~WidgetHeightMap();
void setBrushMode(HeightMapBrushMode mode);
void setBrushSize(double size);
void setBrushSmoothing(double smoothing);
void setBrushStrength(double smoothing);
QString getMemoryStats();
void setTerrain(TerrainDefinition* terrain);
void setBrush(PaintingBrush* brush);
public slots:
void revert();
@ -67,7 +64,6 @@ private:
_VertexInfo* _vertices;
bool _dirty;
qint64 _memory_stats;
double _water_height;
bool _water;
@ -91,13 +87,9 @@ private:
CameraDefinition* _current_camera;
double _zoom;
PaintingBrush* _brush;
double _brush_x;
double _brush_z;
HeightMapBrushMode _brush_mode;
double _brush_size;
double _brush_smoothing;
double _brush_strength;
NoiseGenerator* _brush_noise;
};
#endif

View file

@ -30,7 +30,7 @@ struct CameraDefinition
void cameraSave(PackStream* stream, CameraDefinition* camera)
{
v3Save(stream, &camera->location);
packWriteDouble(stream, &camera->direction.r);
packWriteDouble(stream , &camera->direction.r);
packWriteDouble(stream, &camera->direction.phi);
packWriteDouble(stream, &camera->direction.theta);
packWriteDouble(stream, &camera->roll);

126
src/rendering/rendering.pro Normal file
View file

@ -0,0 +1,126 @@
#-------------------------------------------------
#
# Project created by QtCreator 2013-05-01T12:27:33
#
#-------------------------------------------------
QT -= core gui
TARGET = rendering
TEMPLATE = lib
DEFINES += RENDERING_LIBRARY
SOURCES += \
zone.c \
tools.c \
system.c \
scenery.c \
renderer.c \
render.c \
opencl.c \
noisesimplex.c \
noiseperlin.c \
noisenaive.c \
noise.c \
main.c \
layers.c \
geoarea.c \
camera.c \
auto.c \
atmosphere/atm_render.c \
atmosphere/atm_raster.c \
atmosphere/atm_preview.c \
atmosphere/atm_presets.c \
atmosphere/atm_definition.c \
atmosphere/atm_bruneton.c \
clouds/clo_tools.c \
clouds/clo_rendering.c \
clouds/clo_preview.c \
clouds/clo_presets.c \
clouds/clo_definition.c \
shared/preview.c \
terrain/ter_raster.c \
terrain/ter_preview.c \
terrain/ter_presets.c \
terrain/ter_painting.c \
terrain/ter_definition.c \
textures/tex_tools.c \
textures/tex_rendering.c \
textures/tex_preview.c \
textures/tex_presets.c \
textures/tex_definition.c \
tools/texture.c \
tools/parallel.c \
tools/pack.c \
tools/memory.c \
tools/lighting.c \
tools/euclid.c \
tools/curve.c \
tools/color.c \
tools/cache.c \
tools/array.c \
water/wat_render.c \
water/wat_raster.c \
water/wat_preview.c \
water/wat_presets.c \
water/wat_definition.c
HEADERS += \
zone.h \
tools.h \
system.h \
scenery.h \
renderer.h \
render.h \
opencl.h \
noisesimplex.h \
noiseperlin.h \
noisenaive.h \
noise.h \
main.h \
layers.h \
geoarea.h \
camera.h \
auto.h \
atmosphere/public.h \
atmosphere/private.h \
clouds/public.h \
clouds/private.h \
shared/types.h \
shared/preview.h \
terrain/public.h \
terrain/private.h \
textures/public.h \
textures/private.h \
tools/texture.h \
tools/parallel.h \
tools/pack.h \
tools/memory.h \
tools/lighting.h \
tools/euclid.h \
tools/curve.h \
tools/color.h \
tools/cache.h \
tools/array.h \
water/public.h \
water/private.h
symbian {
MMP_RULES += EXPORTUNFROZEN
TARGET.UID3 = 0xEC48CBFE
TARGET.CAPABILITY =
TARGET.EPOCALLOWDLLDATA = 1
addFiles.sources = rendering.dll
addFiles.path = !:/sys/bin
DEPLOYMENT += addFiles
}
unix:!symbian {
maemo5 {
target.path = /opt/usr/lib
} else {
target.path = /usr/lib
}
INSTALLS += target
}