Merge branch 'master' into perspective_correction
Conflicts: src/testing/main.c
This commit is contained in:
commit
feb422cd11
45 changed files with 1736 additions and 412 deletions
2
TODO
2
TODO
|
@ -1,4 +1,5 @@
|
||||||
Technology Preview 2 :
|
Technology Preview 2 :
|
||||||
|
- Implement perspective correction for coordinate mapping of rasterized polygons.
|
||||||
- Finalize terrain editor.
|
- Finalize terrain editor.
|
||||||
=> Add a generation dialog for base noise (overwriting changes).
|
=> Add a generation dialog for base noise (overwriting changes).
|
||||||
- Get rid of noise dialogs, for simpler settings.
|
- Get rid of noise dialogs, for simpler settings.
|
||||||
|
@ -15,6 +16,7 @@ Technology Preview 2 :
|
||||||
|
|
||||||
Technlogy Preview 3 :
|
Technlogy Preview 3 :
|
||||||
- Start an undo/redo system ?
|
- Start an undo/redo system ?
|
||||||
|
- Alter aerial perspective using estimation of the amount of light left after cloud layers traversal.
|
||||||
- Add a map preview to terrain editor.
|
- Add a map preview to terrain editor.
|
||||||
- Better time selection widget for atmosphere.
|
- Better time selection widget for atmosphere.
|
||||||
- Clouds should keep distance to ground.
|
- Clouds should keep distance to ground.
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
<file>images/explore.png</file>
|
<file>images/explore.png</file>
|
||||||
<file>images/render.png</file>
|
<file>images/render.png</file>
|
||||||
<file>images/about.png</file>
|
<file>images/about.png</file>
|
||||||
|
<file>images/load.png</file>
|
||||||
|
<file>images/new.png</file>
|
||||||
|
<file>images/save.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="/tabs">
|
<qresource prefix="/tabs">
|
||||||
<file>images/tab_atmosphere.png</file>
|
<file>images/tab_atmosphere.png</file>
|
||||||
|
@ -15,4 +18,10 @@
|
||||||
<file>images/tab_textures.png</file>
|
<file>images/tab_textures.png</file>
|
||||||
<file>images/tab_water.png</file>
|
<file>images/tab_water.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
|
<qresource prefix="/logo">
|
||||||
|
<file>images/logo_16.png</file>
|
||||||
|
<file>images/logo_32.png</file>
|
||||||
|
<file>images/logo_64.png</file>
|
||||||
|
<file>images/logo_256.png</file>
|
||||||
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
|
@ -2,11 +2,16 @@
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
#include <QResizeEvent>
|
||||||
|
#include <QSlider>
|
||||||
|
#include <QPushButton>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <qt4/QtGui/qwidget.h>
|
||||||
#include "dialogrender.h"
|
#include "dialogrender.h"
|
||||||
#include "dialogexplorer.h"
|
#include "dialogexplorer.h"
|
||||||
#include "rendering/scenery.h"
|
#include "rendering/scenery.h"
|
||||||
#include "rendering/renderer.h"
|
#include "rendering/renderer.h"
|
||||||
|
#include "tools.h"
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(double*)
|
Q_DECLARE_METATYPE(double*)
|
||||||
|
|
||||||
|
@ -24,8 +29,43 @@ FreeFormHelper::~FreeFormHelper()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FreeFormHelper::eventFilter(QObject* object, QEvent* event)
|
||||||
|
{
|
||||||
|
if (event->type() == QEvent::Resize && object == _form_widget)
|
||||||
|
{
|
||||||
|
QSize form_size = ((QResizeEvent*) event)->size();
|
||||||
|
QSize preview_size;
|
||||||
|
|
||||||
|
if (form_size.width() > 1400 && form_size.height() > 900)
|
||||||
|
{
|
||||||
|
preview_size = QSize(300, 300);
|
||||||
|
}
|
||||||
|
else if (form_size.width() < 1000 || form_size.height() < 700)
|
||||||
|
{
|
||||||
|
preview_size = QSize(160, 160);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
preview_size = QSize(220, 220);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < _previews.size(); i++)
|
||||||
|
{
|
||||||
|
if (_previews[i]->size() != preview_size)
|
||||||
|
{
|
||||||
|
_previews[i]->setMinimumSize(preview_size);
|
||||||
|
_previews[i]->setMaximumSize(preview_size);
|
||||||
|
_previews[i]->resize(preview_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void FreeFormHelper::startManaging()
|
void FreeFormHelper::startManaging()
|
||||||
{
|
{
|
||||||
|
_form_widget->installEventFilter(this);
|
||||||
|
|
||||||
connect(this, SIGNAL(needLocalRefreshing()), _form_widget, SLOT(refreshFromLocalData()));
|
connect(this, SIGNAL(needLocalRefreshing()), _form_widget, SLOT(refreshFromLocalData()));
|
||||||
connect(this, SIGNAL(needGlobalRefreshing()), _form_widget, SLOT(refreshFromFellowData()));
|
connect(this, SIGNAL(needGlobalRefreshing()), _form_widget, SLOT(refreshFromFellowData()));
|
||||||
connect(this, SIGNAL(needReverting()), _form_widget, SLOT(updateLocalDataFromScenery()));
|
connect(this, SIGNAL(needReverting()), _form_widget, SLOT(updateLocalDataFromScenery()));
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
#ifndef FREEFORMHELPER_H
|
#ifndef FREEFORMHELPER_H
|
||||||
#define FREEFORMHELPER_H
|
#define FREEFORMHELPER_H
|
||||||
|
|
||||||
#include <QSlider>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include "widgetsliderdecimal.h"
|
#include "widgetsliderdecimal.h"
|
||||||
#include "../basepreview.h"
|
#include "../basepreview.h"
|
||||||
|
|
||||||
|
class QSlider;
|
||||||
|
class QPushButton;
|
||||||
|
|
||||||
class FreeFormHelper:public QObject
|
class FreeFormHelper:public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -57,6 +58,9 @@ public slots:
|
||||||
void processRenderClicked();
|
void processRenderClicked();
|
||||||
void processDecimalChange(double value);
|
void processDecimalChange(double value);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool eventFilter(QObject* object, QEvent* event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QWidget* _form_widget;
|
QWidget* _form_widget;
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
#include "ui_mainwindow.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QMenuBar>
|
#include <QMenuBar>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <QToolBar>
|
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QTabWidget>
|
#include <QTabWidget>
|
||||||
#include <QTranslator>
|
#include <QTranslator>
|
||||||
|
@ -64,6 +64,7 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
window = new MainWindow();
|
window = new MainWindow();
|
||||||
window->show();
|
window->show();
|
||||||
|
//window->showMaximized();
|
||||||
splash->finish(window);
|
splash->finish(window);
|
||||||
|
|
||||||
delete splash;
|
delete splash;
|
||||||
|
@ -79,68 +80,60 @@ int main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent) :
|
MainWindow::MainWindow(QWidget *parent) :
|
||||||
QMainWindow(parent)
|
QMainWindow(parent),
|
||||||
|
ui(new Ui::MainWindow)
|
||||||
{
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
BaseForm* form;
|
BaseForm* form;
|
||||||
QTabWidget* tabs;
|
|
||||||
QToolBar* toolbar;
|
|
||||||
|
|
||||||
tabs = new QTabWidget(this);
|
connect(ui->action_explore, SIGNAL(triggered()), this, SLOT(explore3D()));
|
||||||
tabs->setIconSize(QSize(32, 32));
|
connect(ui->action_quick_render, SIGNAL(triggered()), this, SLOT(quickPreview()));
|
||||||
|
connect(ui->action_final_render, SIGNAL(triggered()), this, SLOT(finalRender()));
|
||||||
|
connect(ui->action_file_new, SIGNAL(triggered()), this, SLOT(fileNew()));
|
||||||
|
connect(ui->action_file_save, SIGNAL(triggered()), this, SLOT(fileSave()));
|
||||||
|
connect(ui->action_file_load, SIGNAL(triggered()), this, SLOT(fileLoad()));
|
||||||
|
connect(ui->action_about, SIGNAL(triggered()), this, SLOT(showAboutDialog()));
|
||||||
|
|
||||||
tabs->addTab(new MainTerrainForm(tabs), QIcon(getDataPath("images/tab_terrain.png")), tr("Landscape shape"));
|
form = new FormTextures(ui->tabs);
|
||||||
|
ui->tabs->addTab(form, QIcon(getDataPath("images/tab_textures.png")), tr("Textures"));
|
||||||
form = new FormTextures(tabs);
|
|
||||||
tabs->addTab(form, QIcon(getDataPath("images/tab_textures.png")), tr("Textures"));
|
|
||||||
QObject::connect(form, SIGNAL(configApplied()), this, SLOT(refreshAll()), Qt::QueuedConnection);
|
QObject::connect(form, SIGNAL(configApplied()), this, SLOT(refreshAll()), Qt::QueuedConnection);
|
||||||
_forms.append(form);
|
_forms.append(form);
|
||||||
|
|
||||||
form = new FormWater(tabs);
|
form = new FormWater(ui->tabs);
|
||||||
tabs->addTab(form, QIcon(getDataPath("images/tab_water.png")), tr("Water"));
|
ui->tabs->addTab(form, QIcon(getDataPath("images/tab_water.png")), tr("Water"));
|
||||||
QObject::connect(form, SIGNAL(configApplied()), this, SLOT(refreshAll()), Qt::QueuedConnection);
|
QObject::connect(form, SIGNAL(configApplied()), this, SLOT(refreshAll()), Qt::QueuedConnection);
|
||||||
_forms.append(form);
|
_forms.append(form);
|
||||||
|
|
||||||
form = new FormAtmosphere(tabs);
|
form = new FormAtmosphere(ui->tabs);
|
||||||
tabs->addTab(form, QIcon(getDataPath("images/tab_atmosphere.png")), tr("Atmosphere"));
|
ui->tabs->addTab(form, QIcon(getDataPath("images/tab_atmosphere.png")), tr("Atmosphere"));
|
||||||
QObject::connect(form, SIGNAL(configApplied()), this, SLOT(refreshAll()), Qt::QueuedConnection);
|
QObject::connect(form, SIGNAL(configApplied()), this, SLOT(refreshAll()), Qt::QueuedConnection);
|
||||||
_forms.append(form);
|
_forms.append(form);
|
||||||
|
|
||||||
form = new FormClouds(tabs);
|
form = new FormClouds(ui->tabs);
|
||||||
tabs->addTab(form, QIcon(getDataPath("images/tab_clouds.png")), tr("Clouds"));
|
ui->tabs->addTab(form, QIcon(getDataPath("images/tab_clouds.png")), tr("Clouds"));
|
||||||
QObject::connect(form, SIGNAL(configApplied()), this, SLOT(refreshAll()), Qt::QueuedConnection);
|
QObject::connect(form, SIGNAL(configApplied()), this, SLOT(refreshAll()), Qt::QueuedConnection);
|
||||||
_forms.append(form);
|
_forms.append(form);
|
||||||
|
|
||||||
_form_render = new FormRender(tabs);
|
_form_render = new FormRender(ui->tabs);
|
||||||
tabs->addTab(_form_render, QIcon(getDataPath("images/tab_render.png")), tr("Render"));
|
ui->tabs->addTab(_form_render, QIcon(getDataPath("images/tab_render.png")), tr("Render"));
|
||||||
_forms.append(_form_render);
|
_forms.append(_form_render);
|
||||||
|
|
||||||
toolbar = new QToolBar(this);
|
// TODO Decide this according to platform / screen size
|
||||||
toolbar->setOrientation(Qt::Vertical);
|
//ui->toolBar->hide();
|
||||||
toolbar->setAllowedAreas(Qt::LeftToolBarArea);
|
ui->tool_panel->hide();
|
||||||
toolbar->setMovable(false);
|
ui->menuBar->hide();
|
||||||
toolbar->setFloatable(false);
|
|
||||||
toolbar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
|
|
||||||
toolbar->toggleViewAction()->setEnabled(false);
|
|
||||||
toolbar->setIconSize(QSize(32, 32));
|
|
||||||
addToolBar(Qt::LeftToolBarArea, toolbar);
|
|
||||||
|
|
||||||
toolbar->addAction(QIcon(getDataPath("images/new.png")), tr("&New"), this, SLOT(fileNew()))->setShortcut(QKeySequence(tr("Crtl+N")));
|
|
||||||
toolbar->addAction(QIcon(getDataPath("images/save.png")), tr("&Save"), this, SLOT(fileSave()))->setShortcut(QKeySequence(tr("Crtl+S")));
|
|
||||||
toolbar->addAction(QIcon(getDataPath("images/load.png")), tr("&Load"), this, SLOT(fileLoad()))->setShortcut(QKeySequence(tr("Crtl+L")));
|
|
||||||
toolbar->addAction(QIcon(getDataPath("images/explore.png")), tr("&Explore (F2)"), this, SLOT(explore3D()))->setShortcut(QKeySequence(tr("F2")));
|
|
||||||
toolbar->addAction(QIcon(getDataPath("images/render.png")), tr("&Quick\nrender (F5)"), this, SLOT(quickPreview()))->setShortcut(QKeySequence(tr("F5")));
|
|
||||||
toolbar->addAction(QIcon(getDataPath("images/about.png")), tr("&About"), this, SLOT(showAboutDialog()));
|
|
||||||
|
|
||||||
setCentralWidget(tabs);
|
|
||||||
|
|
||||||
setWindowTitle("Paysages 3D");
|
|
||||||
setWindowIcon(QIcon(getDataPath("images/logo_32.png")));
|
|
||||||
|
|
||||||
scenerySetCustomDataCallback(MainWindow::guiSaveCallback, MainWindow::guiLoadCallback, this);
|
scenerySetCustomDataCallback(MainWindow::guiSaveCallback, MainWindow::guiLoadCallback, this);
|
||||||
|
|
||||||
refreshAll();
|
refreshAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MainWindow::~MainWindow()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
bool MainWindow::event(QEvent* event)
|
bool MainWindow::event(QEvent* event)
|
||||||
{
|
{
|
||||||
if (event->type() == QEvent::WindowActivate)
|
if (event->type() == QEvent::WindowActivate)
|
||||||
|
@ -160,6 +153,7 @@ void MainWindow::refreshAll()
|
||||||
{
|
{
|
||||||
_forms[i]->revertConfig();
|
_forms[i]->revertConfig();
|
||||||
}
|
}
|
||||||
|
// TODO Refresh free forms
|
||||||
|
|
||||||
// Refresh preview OSD
|
// Refresh preview OSD
|
||||||
CameraDefinition* camera = cameraCreateDefinition();
|
CameraDefinition* camera = cameraCreateDefinition();
|
||||||
|
@ -244,6 +238,16 @@ void MainWindow::quickPreview()
|
||||||
_form_render->startQuickRender();
|
_form_render->startQuickRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::finalRender()
|
||||||
|
{
|
||||||
|
_form_render->startRender();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::showLastRender()
|
||||||
|
{
|
||||||
|
_form_render->showRender();
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::explore3D()
|
void MainWindow::explore3D()
|
||||||
{
|
{
|
||||||
CameraDefinition* camera;
|
CameraDefinition* camera;
|
|
@ -1,16 +1,25 @@
|
||||||
#ifndef _PAYSAGES_QT_MAINWINDOW_H_
|
#ifndef MAINWINDOW_H
|
||||||
#define _PAYSAGES_QT_MAINWINDOW_H_
|
#define MAINWINDOW_H
|
||||||
|
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include "formrender.h"
|
#include <QVector>
|
||||||
#include "rendering/tools/pack.h"
|
#include "rendering/tools/pack.h"
|
||||||
|
|
||||||
|
class BaseForm;
|
||||||
|
class FormRender;
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class MainWindow;
|
||||||
|
}
|
||||||
|
|
||||||
class MainWindow : public QMainWindow
|
class MainWindow : public QMainWindow
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit MainWindow(QWidget *parent = 0);
|
explicit MainWindow(QWidget *parent = 0);
|
||||||
|
~MainWindow();
|
||||||
|
|
||||||
virtual bool event(QEvent* event);
|
virtual bool event(QEvent* event);
|
||||||
|
|
||||||
static void guiSaveCallback(PackStream* stream, void* data);
|
static void guiSaveCallback(PackStream* stream, void* data);
|
||||||
|
@ -26,9 +35,14 @@ public slots:
|
||||||
void showAboutDialog();
|
void showAboutDialog();
|
||||||
|
|
||||||
void quickPreview();
|
void quickPreview();
|
||||||
|
void finalRender();
|
||||||
|
void showLastRender();
|
||||||
|
|
||||||
void explore3D();
|
void explore3D();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Ui::MainWindow *ui;
|
||||||
|
|
||||||
void guiSave(PackStream* stream);
|
void guiSave(PackStream* stream);
|
||||||
void guiLoad(PackStream* stream);
|
void guiLoad(PackStream* stream);
|
||||||
|
|
||||||
|
@ -36,4 +50,4 @@ private:
|
||||||
FormRender* _form_render;
|
FormRender* _form_render;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // MAINWINDOW_H
|
572
src/editing/common/mainwindow.ui
Normal file
572
src/editing/common/mainwindow.ui
Normal file
|
@ -0,0 +1,572 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>MainWindow</class>
|
||||||
|
<widget class="QMainWindow" name="MainWindow">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>946</width>
|
||||||
|
<height>651</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Paysages 3D</string>
|
||||||
|
</property>
|
||||||
|
<property name="windowIcon">
|
||||||
|
<iconset resource="../../../data/ui_pictures.qrc">
|
||||||
|
<normaloff>:/logo/images/logo_32.png</normaloff>:/logo/images/logo_32.png</iconset>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="centralwidget">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="tool_panel" native="true">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string><html><head/><body><p><span style=" font-size:14pt; font-weight:600;">Paysages 3D</span></p><p><img src=":/logo/images/logo_32.png"/></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="textFormat">
|
||||||
|
<enum>Qt::RichText</enum>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="radioButton_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Preview</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="radioButton_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>3D</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="radioButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Top</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QFrame" name="frame">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::Panel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Raised</enum>
|
||||||
|
</property>
|
||||||
|
<property name="lineWidth">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetMinimumSize</enum>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="widget" native="true">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>200</width>
|
||||||
|
<height>150</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
<zorder>widget</zorder>
|
||||||
|
<zorder>widget</zorder>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer_4">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_2">
|
||||||
|
<property name="title">
|
||||||
|
<string>Actions</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="button_explore">
|
||||||
|
<property name="text">
|
||||||
|
<string>Explore in 3D</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../data/ui_pictures.qrc">
|
||||||
|
<normaloff>:/buttons/logo/images/explore.png</normaloff>:/buttons/logo/images/explore.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>F2</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="button_render">
|
||||||
|
<property name="text">
|
||||||
|
<string>Render</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../data/ui_pictures.qrc">
|
||||||
|
<normaloff>:/buttons/logo/images/render.png</normaloff>:/buttons/logo/images/render.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>File</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="button_file_new">
|
||||||
|
<property name="text">
|
||||||
|
<string>New</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../data/ui_pictures.qrc">
|
||||||
|
<normaloff>:/buttons/logo/images/new.png</normaloff>:/buttons/logo/images/new.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="button_file_save">
|
||||||
|
<property name="text">
|
||||||
|
<string>Save</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../data/ui_pictures.qrc">
|
||||||
|
<normaloff>:/buttons/logo/images/save.png</normaloff>:/buttons/logo/images/save.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="button_file_load">
|
||||||
|
<property name="text">
|
||||||
|
<string>Load</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../data/ui_pictures.qrc">
|
||||||
|
<normaloff>:/buttons/logo/images/load.png</normaloff>:/buttons/logo/images/load.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</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>
|
||||||
|
<item>
|
||||||
|
<widget class="QTabWidget" name="tabs">
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<widget class="MainTerrainForm" name="tab_terrain">
|
||||||
|
<attribute name="icon">
|
||||||
|
<iconset resource="../../../data/ui_pictures.qrc">
|
||||||
|
<normaloff>:/tabs/images/tab_terrain.png</normaloff>:/tabs/images/tab_terrain.png</iconset>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Lanscape shape</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QToolBar" name="toolBar">
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>toolBar</string>
|
||||||
|
</property>
|
||||||
|
<property name="movable">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="allowedAreas">
|
||||||
|
<set>Qt::LeftToolBarArea</set>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolButtonStyle">
|
||||||
|
<enum>Qt::ToolButtonTextUnderIcon</enum>
|
||||||
|
</property>
|
||||||
|
<property name="floatable">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<attribute name="toolBarArea">
|
||||||
|
<enum>LeftToolBarArea</enum>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="toolBarBreak">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<addaction name="action_file_new"/>
|
||||||
|
<addaction name="action_file_save"/>
|
||||||
|
<addaction name="action_file_load"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="action_explore"/>
|
||||||
|
<addaction name="action_quick_render"/>
|
||||||
|
<addaction name="action_final_render"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="action_about"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenuBar" name="menuBar">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>946</width>
|
||||||
|
<height>25</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<widget class="QMenu" name="menuFile">
|
||||||
|
<property name="title">
|
||||||
|
<string>File</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="action_file_new"/>
|
||||||
|
<addaction name="action_file_save"/>
|
||||||
|
<addaction name="action_file_load"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenu" name="menuActions">
|
||||||
|
<property name="title">
|
||||||
|
<string>Actions</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="action_explore"/>
|
||||||
|
<addaction name="action_quick_render"/>
|
||||||
|
<addaction name="action_final_render"/>
|
||||||
|
<addaction name="action_last_render"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenu" name="menuHelp">
|
||||||
|
<property name="title">
|
||||||
|
<string>Help</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="action_about"/>
|
||||||
|
</widget>
|
||||||
|
<addaction name="menuFile"/>
|
||||||
|
<addaction name="menuActions"/>
|
||||||
|
<addaction name="menuHelp"/>
|
||||||
|
</widget>
|
||||||
|
<action name="action_explore">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../data/ui_pictures.qrc">
|
||||||
|
<normaloff>:/buttons/logo/images/explore.png</normaloff>:/buttons/logo/images/explore.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Explore in 3D</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Start exploring your scenery in real-time 3D</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>F2</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_file_new">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../data/ui_pictures.qrc">
|
||||||
|
<normaloff>:/buttons/logo/images/new.png</normaloff>:/buttons/logo/images/new.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>New scene</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Create a virgin scene</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>Ctrl+N</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_file_load">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../data/ui_pictures.qrc">
|
||||||
|
<normaloff>:/buttons/logo/images/load.png</normaloff>:/buttons/logo/images/load.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Load scene</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Load a scenery from a file</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>Ctrl+O</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_file_save">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../data/ui_pictures.qrc">
|
||||||
|
<normaloff>:/buttons/logo/images/save.png</normaloff>:/buttons/logo/images/save.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Save scene</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Save a scenery to a file</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>Ctrl+S</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_quick_render">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../data/ui_pictures.qrc">
|
||||||
|
<normaloff>:/buttons/logo/images/render.png</normaloff>:/buttons/logo/images/render.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Quick render</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Start a quick render</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>F5</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_final_render">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../data/ui_pictures.qrc">
|
||||||
|
<normaloff>:/buttons/logo/images/render.png</normaloff>:/buttons/logo/images/render.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Final render</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Start the final rendering processs</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>Ctrl+F5</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_about">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../data/ui_pictures.qrc">
|
||||||
|
<normaloff>:/buttons/logo/images/about.png</normaloff>:/buttons/logo/images/about.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>About</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Display information on this software</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>F1</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_last_render">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../data/ui_pictures.qrc">
|
||||||
|
<normaloff>:/buttons/logo/images/render.png</normaloff>:/buttons/logo/images/render.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Show last render</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Display the last render done</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>F6</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>MainTerrainForm</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>terrain/mainterrainform.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources>
|
||||||
|
<include location="../../../data/ui_pictures.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>button_explore</sender>
|
||||||
|
<signal>clicked()</signal>
|
||||||
|
<receiver>action_explore</receiver>
|
||||||
|
<slot>trigger()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>127</x>
|
||||||
|
<y>380</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>-1</x>
|
||||||
|
<y>-1</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>button_render</sender>
|
||||||
|
<signal>clicked()</signal>
|
||||||
|
<receiver>action_final_render</receiver>
|
||||||
|
<slot>trigger()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>213</x>
|
||||||
|
<y>425</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>213</x>
|
||||||
|
<y>425</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>button_file_new</sender>
|
||||||
|
<signal>clicked()</signal>
|
||||||
|
<receiver>action_file_new</receiver>
|
||||||
|
<slot>trigger()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>213</x>
|
||||||
|
<y>522</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>-1</x>
|
||||||
|
<y>-1</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>button_file_load</sender>
|
||||||
|
<signal>clicked()</signal>
|
||||||
|
<receiver>action_file_load</receiver>
|
||||||
|
<slot>trigger()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>213</x>
|
||||||
|
<y>588</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>-1</x>
|
||||||
|
<y>-1</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>button_file_save</sender>
|
||||||
|
<signal>clicked()</signal>
|
||||||
|
<receiver>action_file_save</receiver>
|
||||||
|
<slot>trigger()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>213</x>
|
||||||
|
<y>555</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>-1</x>
|
||||||
|
<y>-1</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
|
@ -133,7 +133,7 @@ DialogRender::DialogRender(QWidget *parent, Renderer* renderer):
|
||||||
_actions->layout()->addWidget(_save_button);
|
_actions->layout()->addWidget(_save_button);
|
||||||
|
|
||||||
// Connections
|
// Connections
|
||||||
connect(this, SIGNAL(renderSizeChanged(int, int)), this, SLOT(applyRenderSize(int, int)));
|
//connect(this, SIGNAL(renderSizeChanged(int, int)), this, SLOT(applyRenderSize(int, int)));
|
||||||
connect(this, SIGNAL(progressChanged(double)), this, SLOT(applyProgress(double)));
|
connect(this, SIGNAL(progressChanged(double)), this, SLOT(applyProgress(double)));
|
||||||
connect(this, SIGNAL(renderEnded()), this, SLOT(applyRenderEnded()));
|
connect(this, SIGNAL(renderEnded()), this, SLOT(applyRenderEnded()));
|
||||||
connect(_save_button, SIGNAL(clicked()), this, SLOT(saveRender()));
|
connect(_save_button, SIGNAL(clicked()), this, SLOT(saveRender()));
|
||||||
|
@ -173,7 +173,7 @@ void DialogRender::startRender(RenderParams params)
|
||||||
{
|
{
|
||||||
_started = time(NULL);
|
_started = time(NULL);
|
||||||
|
|
||||||
//applyRenderSize(params.width, params.height);
|
applyRenderSize(params.width, params.height);
|
||||||
rendererSetPreviewCallbacks(_renderer, _renderStart, _renderDraw, _renderUpdate);
|
rendererSetPreviewCallbacks(_renderer, _renderStart, _renderDraw, _renderUpdate);
|
||||||
|
|
||||||
_render_thread = new RenderThread(this, _renderer, params);
|
_render_thread = new RenderThread(this, _renderer, params);
|
||||||
|
@ -217,9 +217,10 @@ void DialogRender::toneMappingChanged()
|
||||||
|
|
||||||
void DialogRender::loadLastRender()
|
void DialogRender::loadLastRender()
|
||||||
{
|
{
|
||||||
//applyRenderSize(_renderer->render_width, _renderer->render_height);
|
applyRenderSize(_renderer->render_width, _renderer->render_height);
|
||||||
rendererSetPreviewCallbacks(_renderer, _renderStart, _renderDraw, _renderUpdate);
|
rendererSetPreviewCallbacks(_renderer, _renderStart, _renderDraw, _renderUpdate);
|
||||||
renderEnded();
|
renderEnded();
|
||||||
|
toneMappingChanged();
|
||||||
|
|
||||||
exec();
|
exec();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "formclouds.h"
|
#include "formclouds.h"
|
||||||
|
|
||||||
|
#include "rendering/clouds/clo_preview.h"
|
||||||
#include "rendering/tools/color.h"
|
#include "rendering/tools/color.h"
|
||||||
#include "rendering/tools/euclid.h"
|
#include "rendering/tools/euclid.h"
|
||||||
#include "rendering/scenery.h"
|
#include "rendering/scenery.h"
|
||||||
|
@ -12,24 +13,22 @@ class PreviewCloudsCoverage:public BasePreview
|
||||||
public:
|
public:
|
||||||
PreviewCloudsCoverage(QWidget* parent, CloudsLayerDefinition* layer):BasePreview(parent)
|
PreviewCloudsCoverage(QWidget* parent, CloudsLayerDefinition* layer):BasePreview(parent)
|
||||||
{
|
{
|
||||||
_renderer = cloudsCreatePreviewCoverageRenderer();
|
_renderer = cloudsPreviewCoverageCreateRenderer();
|
||||||
_3d = true;
|
_3d = true;
|
||||||
|
|
||||||
_original_layer = layer;
|
_original_layer = layer;
|
||||||
_preview_definition = (CloudsDefinition*)CloudsDefinitionClass.create();
|
|
||||||
|
|
||||||
addToggle("3d", tr("Perspective"), true);
|
addToggle("3d", tr("Perspective"), true);
|
||||||
configScaling(100.0, 1000.0, 20.0, 200.0);
|
configScaling(100.0, 1000.0, 20.0, 200.0);
|
||||||
}
|
}
|
||||||
~PreviewCloudsCoverage()
|
~PreviewCloudsCoverage()
|
||||||
{
|
{
|
||||||
CloudsDefinitionClass.destroy(_preview_definition);
|
|
||||||
rendererDelete(_renderer);
|
rendererDelete(_renderer);
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
Color getColor(double x, double y)
|
Color getColor(double x, double y)
|
||||||
{
|
{
|
||||||
return cloudsGetPreviewCoverage(_renderer, x, y, scaling, _3d);
|
return cloudsPreviewCoverageGetPixel(_renderer, x, y, scaling, _3d);
|
||||||
}
|
}
|
||||||
virtual void toggleChangeEvent(QString key, bool value)
|
virtual void toggleChangeEvent(QString key, bool value)
|
||||||
{
|
{
|
||||||
|
@ -41,15 +40,12 @@ protected:
|
||||||
}
|
}
|
||||||
void updateData()
|
void updateData()
|
||||||
{
|
{
|
||||||
layersDeleteLayer(_preview_definition->layers, 0);
|
cloudsPreviewCoverageBindLayer(_renderer, _original_layer);
|
||||||
layersAddLayer(_preview_definition->layers, _original_layer);
|
|
||||||
CloudsRendererClass.bind(_renderer, _preview_definition);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Renderer* _renderer;
|
Renderer* _renderer;
|
||||||
CloudsLayerDefinition* _original_layer;
|
CloudsLayerDefinition* _original_layer;
|
||||||
CloudsDefinition* _preview_definition;
|
|
||||||
bool _3d;
|
bool _3d;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -59,27 +55,28 @@ public:
|
||||||
PreviewCloudsColor(QWidget* parent, CloudsLayerDefinition* layer):BasePreview(parent)
|
PreviewCloudsColor(QWidget* parent, CloudsLayerDefinition* layer):BasePreview(parent)
|
||||||
{
|
{
|
||||||
_original_layer = layer;
|
_original_layer = layer;
|
||||||
_preview_definition = (CloudsDefinition*)CloudsDefinitionClass.create();
|
|
||||||
|
|
||||||
_renderer = cloudsCreatePreviewColorRenderer();
|
_renderer = cloudsPreviewMaterialCreateRenderer();
|
||||||
|
|
||||||
configScaling(0.5, 2.0, 0.1, 2.0);
|
configScaling(0.5, 2.0, 0.1, 2.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~PreviewCloudsColor()
|
||||||
|
{
|
||||||
|
rendererDelete(_renderer);
|
||||||
|
}
|
||||||
protected:
|
protected:
|
||||||
Color getColor(double x, double y)
|
Color getColor(double x, double y)
|
||||||
{
|
{
|
||||||
return cloudsGetPreviewColor(_renderer, x, y);
|
return cloudsPreviewMaterialGetPixel(_renderer, x, y);
|
||||||
}
|
}
|
||||||
void updateData()
|
void updateData()
|
||||||
{
|
{
|
||||||
layersDeleteLayer(_preview_definition->layers, 0);
|
cloudsPreviewMaterialBindLayer(_renderer, _original_layer);
|
||||||
layersAddLayer(_preview_definition->layers, _original_layer);
|
|
||||||
CloudsRendererClass.bind(_renderer, _preview_definition);
|
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
Renderer* _renderer;
|
Renderer* _renderer;
|
||||||
CloudsLayerDefinition* _original_layer;
|
CloudsLayerDefinition* _original_layer;
|
||||||
CloudsDefinition* _preview_definition;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**************** Form ****************/
|
/**************** Form ****************/
|
||||||
|
|
|
@ -21,14 +21,12 @@ public slots:
|
||||||
virtual void revertConfig();
|
virtual void revertConfig();
|
||||||
virtual void applyConfig();
|
virtual void applyConfig();
|
||||||
void startQuickRender();
|
void startQuickRender();
|
||||||
|
void startRender();
|
||||||
|
void showRender();
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
virtual void configChangeEvent();
|
virtual void configChangeEvent();
|
||||||
|
|
||||||
private slots:
|
|
||||||
void startRender();
|
|
||||||
void showRender();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RenderParams _params;
|
RenderParams _params;
|
||||||
CameraDefinition* _camera;
|
CameraDefinition* _camera;
|
||||||
|
|
|
@ -24,14 +24,13 @@ win32:LIBS += ../libpaysages.a ../libpaysages_exploring.a -lDevIL -lILU -lILUT -
|
||||||
TRANSLATIONS = $$PROJECT_PATH/data/i18n/paysages_fr.ts
|
TRANSLATIONS = $$PROJECT_PATH/data/i18n/paysages_fr.ts
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
widgetheightmap.h \
|
terrain/widgetheightmap.h \
|
||||||
widgetexplorer.h \
|
widgetexplorer.h \
|
||||||
widgetcurveeditor.h \
|
widgetcurveeditor.h \
|
||||||
tools.h \
|
tools.h \
|
||||||
previewosd.h \
|
previewosd.h \
|
||||||
previewmaterial.h \
|
previewmaterial.h \
|
||||||
previewcolorgradation.h \
|
previewcolorgradation.h \
|
||||||
mainwindow.h \
|
|
||||||
inputnoise.h \
|
inputnoise.h \
|
||||||
inputmaterial.h \
|
inputmaterial.h \
|
||||||
inputlayers.h \
|
inputlayers.h \
|
||||||
|
@ -70,17 +69,19 @@ HEADERS += \
|
||||||
common/freeformhelper.h \
|
common/freeformhelper.h \
|
||||||
terrain/previewterrainshape.h \
|
terrain/previewterrainshape.h \
|
||||||
common/widgetsliderdecimal.h \
|
common/widgetsliderdecimal.h \
|
||||||
common/previewrenderer.h
|
common/previewrenderer.h \
|
||||||
|
terrain/widgetterrainbasenoisepreview.h \
|
||||||
|
common/mainwindow.h \
|
||||||
|
terrain/dialogbaseterrainnoise.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
widgetheightmap.cpp \
|
terrain/widgetheightmap.cpp \
|
||||||
widgetexplorer.cpp \
|
widgetexplorer.cpp \
|
||||||
widgetcurveeditor.cpp \
|
widgetcurveeditor.cpp \
|
||||||
tools.cpp \
|
tools.cpp \
|
||||||
previewosd.cpp \
|
previewosd.cpp \
|
||||||
previewmaterial.cpp \
|
previewmaterial.cpp \
|
||||||
previewcolorgradation.cpp \
|
previewcolorgradation.cpp \
|
||||||
mainwindow.cpp \
|
|
||||||
inputnoise.cpp \
|
inputnoise.cpp \
|
||||||
inputmaterial.cpp \
|
inputmaterial.cpp \
|
||||||
inputlayers.cpp \
|
inputlayers.cpp \
|
||||||
|
@ -119,12 +120,17 @@ SOURCES += \
|
||||||
common/freeformhelper.cpp \
|
common/freeformhelper.cpp \
|
||||||
terrain/previewterrainshape.cpp \
|
terrain/previewterrainshape.cpp \
|
||||||
common/widgetsliderdecimal.cpp \
|
common/widgetsliderdecimal.cpp \
|
||||||
common/previewrenderer.cpp
|
common/previewrenderer.cpp \
|
||||||
|
terrain/widgetterrainbasenoisepreview.cpp \
|
||||||
|
common/mainwindow.cpp \
|
||||||
|
terrain/dialogbaseterrainnoise.cpp
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
terrain/dialogterrainpainting.ui \
|
terrain/dialogterrainpainting.ui \
|
||||||
common/widgetglobalformbuttons.ui \
|
common/widgetglobalformbuttons.ui \
|
||||||
terrain/mainterrainform.ui
|
terrain/mainterrainform.ui \
|
||||||
|
common/mainwindow.ui \
|
||||||
|
terrain/dialogbaseterrainnoise.ui
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
../../data/ui_pictures.qrc
|
../../data/ui_pictures.qrc
|
||||||
|
|
31
src/editing/terrain/dialogbaseterrainnoise.cpp
Normal file
31
src/editing/terrain/dialogbaseterrainnoise.cpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#include "dialogbaseterrainnoise.h"
|
||||||
|
#include "ui_dialogbaseterrainnoise.h"
|
||||||
|
|
||||||
|
DialogBaseTerrainNoise::DialogBaseTerrainNoise(QWidget *parent) :
|
||||||
|
QDialog(parent),
|
||||||
|
ui(new Ui::DialogBaseTerrainNoise)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
_original = 0;
|
||||||
|
_modified = noiseCreateGenerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
DialogBaseTerrainNoise::~DialogBaseTerrainNoise()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
noiseDeleteGenerator(_modified);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogBaseTerrainNoise::setNoise(NoiseGenerator* noise)
|
||||||
|
{
|
||||||
|
_original = noise;
|
||||||
|
noiseCopy(noise, _modified);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DialogBaseTerrainNoise::editNoise(QWidget* parent, NoiseGenerator* noise)
|
||||||
|
{
|
||||||
|
DialogBaseTerrainNoise dialog(parent);
|
||||||
|
dialog.setNoise(noise);
|
||||||
|
return dialog.exec();
|
||||||
|
}
|
29
src/editing/terrain/dialogbaseterrainnoise.h
Normal file
29
src/editing/terrain/dialogbaseterrainnoise.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef DIALOGBASETERRAINNOISE_H
|
||||||
|
#define DIALOGBASETERRAINNOISE_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include "rendering/noise.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class DialogBaseTerrainNoise;
|
||||||
|
}
|
||||||
|
|
||||||
|
class DialogBaseTerrainNoise : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit DialogBaseTerrainNoise(QWidget *parent = 0);
|
||||||
|
~DialogBaseTerrainNoise();
|
||||||
|
|
||||||
|
void setNoise(NoiseGenerator* noise);
|
||||||
|
|
||||||
|
static int editNoise(QWidget* parent, NoiseGenerator* noise);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::DialogBaseTerrainNoise *ui;
|
||||||
|
NoiseGenerator* _original;
|
||||||
|
NoiseGenerator* _modified;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DIALOGBASETERRAINNOISE_H
|
43
src/editing/terrain/dialogbaseterrainnoise.ui
Normal file
43
src/editing/terrain/dialogbaseterrainnoise.ui
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>DialogBaseTerrainNoise</class>
|
||||||
|
<widget class="QDialog" name="DialogBaseTerrainNoise">
|
||||||
|
<property name="windowModality">
|
||||||
|
<enum>Qt::ApplicationModal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Paysages 3D - Base terrain noise</string>
|
||||||
|
</property>
|
||||||
|
<property name="modal">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="WidgetGlobalFormButtons" name="widget" native="true"/>
|
||||||
|
</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>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -789,7 +789,7 @@
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>WidgetHeightMap</class>
|
<class>WidgetHeightMap</class>
|
||||||
<extends>QWidget</extends>
|
<extends>QWidget</extends>
|
||||||
<header>widgetheightmap.h</header>
|
<header>terrain/widgetheightmap.h</header>
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
<slots>
|
<slots>
|
||||||
<signal>heightmapChanged()</signal>
|
<signal>heightmapChanged()</signal>
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "mainterrainform.h"
|
#include "mainterrainform.h"
|
||||||
#include "ui_mainterrainform.h"
|
#include "ui_mainterrainform.h"
|
||||||
|
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include "dialogbaseterrainnoise.h"
|
||||||
#include "dialogterrainpainting.h"
|
#include "dialogterrainpainting.h"
|
||||||
#include "previewterrainshape.h"
|
#include "previewterrainshape.h"
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
@ -20,15 +22,16 @@ MainTerrainForm::MainTerrainForm(QWidget *parent) :
|
||||||
_form_helper->addPreview(ui->preview_shape, _renderer_shape);
|
_form_helper->addPreview(ui->preview_shape, _renderer_shape);
|
||||||
|
|
||||||
_form_helper->addDoubleInputSlider(ui->input_scaling, &_terrain->scaling, 0.1, 3.0, 0.03, 0.3);
|
_form_helper->addDoubleInputSlider(ui->input_scaling, &_terrain->scaling, 0.1, 3.0, 0.03, 0.3);
|
||||||
_form_helper->addDoubleInputSlider(ui->input_height, &_terrain->height, 1.0, 45.0, 0.3, 3.0);
|
_form_helper->addDoubleInputSlider(ui->input_height, &_terrain->height, 1.0, 90.0, 0.5, 5.0);
|
||||||
_form_helper->addDoubleInputSlider(ui->input_shadow_smoothing, &_terrain->shadow_smoothing, 0.0, 0.3, 0.003, 0.03);
|
_form_helper->addDoubleInputSlider(ui->input_shadow_smoothing, &_terrain->shadow_smoothing, 0.0, 0.3, 0.003, 0.03);
|
||||||
_form_helper->addDoubleInputSlider(ui->input_water_height, &_terrain->water_height, -2.0, 2.0, 0.01, 0.1);
|
_form_helper->addDoubleInputSlider(ui->input_water_height, &_terrain->water_height, -1.0, 1.0, 0.01, 0.1);
|
||||||
|
|
||||||
_form_helper->setApplyButton(ui->button_apply);
|
_form_helper->setApplyButton(ui->button_apply);
|
||||||
_form_helper->setRevertButton(ui->button_revert);
|
_form_helper->setRevertButton(ui->button_revert);
|
||||||
_form_helper->setExploreButton(ui->button_explore);
|
_form_helper->setExploreButton(ui->button_explore);
|
||||||
_form_helper->setRenderButton(ui->button_render);
|
_form_helper->setRenderButton(ui->button_render);
|
||||||
|
|
||||||
|
connect(ui->button_dialog_basenoise, SIGNAL(clicked()), this, SLOT(buttonBaseNoisePressed()));
|
||||||
connect(ui->button_dialog_painting, SIGNAL(clicked()), this, SLOT(buttonPaintingPressed()));
|
connect(ui->button_dialog_painting, SIGNAL(clicked()), this, SLOT(buttonPaintingPressed()));
|
||||||
connect(ui->button_goto_textures, SIGNAL(clicked()), this, SLOT(buttonTexturesPressed()));
|
connect(ui->button_goto_textures, SIGNAL(clicked()), this, SLOT(buttonTexturesPressed()));
|
||||||
|
|
||||||
|
@ -55,6 +58,8 @@ void MainTerrainForm::refreshFromLocalData()
|
||||||
{
|
{
|
||||||
_form_helper->setLabelText("label_painting_info", tr("No manual scuplting done"));
|
_form_helper->setLabelText("label_painting_info", tr("No manual scuplting done"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ui->widget_base_noise_preview->setNoise(_terrain->_height_noise);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTerrainForm::refreshFromFellowData()
|
void MainTerrainForm::refreshFromFellowData()
|
||||||
|
@ -77,6 +82,27 @@ void MainTerrainForm::alterRenderer(Renderer* renderer)
|
||||||
TerrainRendererClass.bind(renderer, _terrain);
|
TerrainRendererClass.bind(renderer, _terrain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainTerrainForm::buttonBaseNoisePressed()
|
||||||
|
{
|
||||||
|
int erase;
|
||||||
|
if (terrainGetMemoryStats(_terrain) > 0)
|
||||||
|
{
|
||||||
|
erase = QMessageBox::question(this, tr("Paysages 3D - Base noise edition"), tr("You have manual modifications on this terrain, regenerating base noise may produce weird results."), tr("Keep my changes anyway"), tr("Erase my changes"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
erase = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DialogBaseTerrainNoise::editNoise(this, _terrain->_height_noise))
|
||||||
|
{
|
||||||
|
if (erase)
|
||||||
|
{
|
||||||
|
terrainClearPainting(_terrain->height_map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MainTerrainForm::buttonPaintingPressed()
|
void MainTerrainForm::buttonPaintingPressed()
|
||||||
{
|
{
|
||||||
DialogTerrainPainting dialog(this, _terrain);
|
DialogTerrainPainting dialog(this, _terrain);
|
||||||
|
|
|
@ -26,6 +26,7 @@ public slots:
|
||||||
void commitLocalDataToScenery();
|
void commitLocalDataToScenery();
|
||||||
void alterRenderer(Renderer* renderer);
|
void alterRenderer(Renderer* renderer);
|
||||||
|
|
||||||
|
void buttonBaseNoisePressed();
|
||||||
void buttonPaintingPressed();
|
void buttonPaintingPressed();
|
||||||
void buttonTexturesPressed();
|
void buttonTexturesPressed();
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="pushButton">
|
<widget class="QPushButton" name="button_dialog_basenoise">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Generate base noise</string>
|
<string>Generate base noise</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QWidget" name="widget" native="true">
|
<widget class="WidgetTerrainBaseNoisePreview" name="widget_base_noise_preview" native="true">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
<horstretch>1</horstretch>
|
<horstretch>1</horstretch>
|
||||||
|
@ -447,6 +447,12 @@
|
||||||
<extends>QSlider</extends>
|
<extends>QSlider</extends>
|
||||||
<header>common/widgetsliderdecimal.h</header>
|
<header>common/widgetsliderdecimal.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>WidgetTerrainBaseNoisePreview</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>terrain/widgetterrainbasenoisepreview.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../../../data/ui_pictures.qrc"/>
|
<include location="../../../data/ui_pictures.qrc"/>
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
PreviewTerrainShape::PreviewTerrainShape(TerrainDefinition* terrain)
|
PreviewTerrainShape::PreviewTerrainShape(TerrainDefinition* terrain)
|
||||||
{
|
{
|
||||||
_terrain = terrain;
|
_terrain = terrain;
|
||||||
|
_highlight_enabled = true;
|
||||||
|
|
||||||
// TODO Don't delete the base renderer, just alter it
|
// TODO Don't delete the base renderer, just alter it
|
||||||
rendererDelete(renderer);
|
rendererDelete(renderer);
|
||||||
|
@ -14,6 +15,7 @@ PreviewTerrainShape::PreviewTerrainShape(TerrainDefinition* terrain)
|
||||||
void PreviewTerrainShape::bindEvent(BasePreview* preview)
|
void PreviewTerrainShape::bindEvent(BasePreview* preview)
|
||||||
{
|
{
|
||||||
preview->addOsd(QString("geolocation"));
|
preview->addOsd(QString("geolocation"));
|
||||||
|
//preview->addToggle("highlight", tr("Coverage highlight"), true);
|
||||||
|
|
||||||
preview->configScaling(20.0, 1000.0, 20.0, 50.0);
|
preview->configScaling(20.0, 1000.0, 20.0, 50.0);
|
||||||
preview->configScrolling(-1000.0, 1000.0, 0.0, -1000.0, 1000.0, 0.0);
|
preview->configScrolling(-1000.0, 1000.0, 0.0, -1000.0, 1000.0, 0.0);
|
||||||
|
@ -26,5 +28,13 @@ void PreviewTerrainShape::updateEvent()
|
||||||
|
|
||||||
Color PreviewTerrainShape::getColor2D(double x, double y, double scaling)
|
Color PreviewTerrainShape::getColor2D(double x, double y, double scaling)
|
||||||
{
|
{
|
||||||
return terrainGetPreviewColor(renderer, x, y, scaling);
|
return waterGetPreviewCoverage(renderer, x, y, scaling, _highlight_enabled ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreviewTerrainShape::toggleChangeEvent(QString key, bool value)
|
||||||
|
{
|
||||||
|
if (key == "highlight")
|
||||||
|
{
|
||||||
|
_highlight_enabled = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,12 @@ protected:
|
||||||
virtual void bindEvent(BasePreview* preview);
|
virtual void bindEvent(BasePreview* preview);
|
||||||
virtual void updateEvent();
|
virtual void updateEvent();
|
||||||
virtual Color getColor2D(double x, double y, double scaling);
|
virtual Color getColor2D(double x, double y, double scaling);
|
||||||
|
virtual void toggleChangeEvent(QString key, bool value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TerrainDefinition* _terrain;
|
TerrainDefinition* _terrain;
|
||||||
|
bool _highlight_enabled;
|
||||||
|
double _water_height;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PREVIEWTERRAINSHAPE_H
|
#endif // PREVIEWTERRAINSHAPE_H
|
||||||
|
|
|
@ -35,8 +35,8 @@ QGLWidget(parent)
|
||||||
_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 = 250;
|
||||||
_last_mouse_y = 0;
|
_last_mouse_y = 250;
|
||||||
_last_time = QDateTime::currentDateTime();
|
_last_time = QDateTime::currentDateTime();
|
||||||
_mouse_moved = false;
|
_mouse_moved = false;
|
||||||
|
|
45
src/editing/terrain/widgetterrainbasenoisepreview.cpp
Normal file
45
src/editing/terrain/widgetterrainbasenoisepreview.cpp
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#include "widgetterrainbasenoisepreview.h"
|
||||||
|
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QPaintEvent>
|
||||||
|
#include "tools.h"
|
||||||
|
|
||||||
|
WidgetTerrainBaseNoisePreview::WidgetTerrainBaseNoisePreview(QWidget* parent) :
|
||||||
|
QWidget(parent)
|
||||||
|
{
|
||||||
|
_noise = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetTerrainBaseNoisePreview::setNoise(NoiseGenerator* noise)
|
||||||
|
{
|
||||||
|
_noise = noise;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetTerrainBaseNoisePreview::paintEvent(QPaintEvent* event)
|
||||||
|
{
|
||||||
|
QPainter painter(this);
|
||||||
|
|
||||||
|
painter.setBrush(Qt::SolidPattern);
|
||||||
|
painter.drawRect(rect());
|
||||||
|
|
||||||
|
int height = this->height();
|
||||||
|
|
||||||
|
if (_noise)
|
||||||
|
{
|
||||||
|
QRect boundaries = event->region().boundingRect();
|
||||||
|
double value, factor;
|
||||||
|
double minvalue, maxvalue;
|
||||||
|
|
||||||
|
noiseGetRange(_noise, &minvalue, &maxvalue);
|
||||||
|
factor = ((double)height) / (maxvalue - minvalue);
|
||||||
|
|
||||||
|
for (int x = boundaries.left(); x <= boundaries.right(); x++)
|
||||||
|
{
|
||||||
|
value = noiseGet1DTotal(_noise, 100.0 * ((double)x) / factor);
|
||||||
|
|
||||||
|
painter.setPen(Qt::white);
|
||||||
|
painter.drawLine(x, height - 1 - (value - minvalue) * factor, x, height - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
src/editing/terrain/widgetterrainbasenoisepreview.h
Normal file
26
src/editing/terrain/widgetterrainbasenoisepreview.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef _PAYSAGES_EDITING_TERRAIN_WIDGETTERRAINBASENOISEPREVIEW_H_
|
||||||
|
#define _PAYSAGES_EDITING_TERRAIN_WIDGETTERRAINBASENOISEPREVIEW_H_
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include "rendering/noise.h"
|
||||||
|
|
||||||
|
class WidgetTerrainBaseNoisePreview : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit WidgetTerrainBaseNoisePreview(QWidget* parent = 0);
|
||||||
|
|
||||||
|
void setNoise(NoiseGenerator* noise);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void paintEvent(QPaintEvent* event);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
private:
|
||||||
|
NoiseGenerator* _noise;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -922,6 +922,8 @@ static Color _getInscatterColor(Vector3* _x, double* _t, Vector3 v, Vector3 s, d
|
||||||
static Color _sunColor(Vector3 v, Vector3 s, double r, double mu, double radius)
|
static Color _sunColor(Vector3 v, Vector3 s, double r, double mu, double radius)
|
||||||
{
|
{
|
||||||
Color transmittance = r <= Rt ? _transmittanceWithShadow(r, mu) : COLOR_WHITE; /* T(x,xo) */
|
Color transmittance = r <= Rt ? _transmittanceWithShadow(r, mu) : COLOR_WHITE; /* T(x,xo) */
|
||||||
|
double d = _limit(r, mu);
|
||||||
|
radius *= (1.0 + 10.0 * d / Rt); /* Inflating due to lens effect near horizon */
|
||||||
double isun = step(cos(radius * M_PI / 180.0), v3Dot(v, s)) * ISun; /* Lsun */
|
double isun = step(cos(radius * M_PI / 180.0), v3Dot(v, s)) * ISun; /* Lsun */
|
||||||
transmittance.r *= isun;
|
transmittance.r *= isun;
|
||||||
transmittance.g *= isun;
|
transmittance.g *= isun;
|
||||||
|
|
|
@ -112,7 +112,7 @@ void cloudsLayerValidateDefinition(CloudsLayerDefinition* definition)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
noiseNormalizeAmplitude(definition->_coverage_noise, 0.0, 1.0, 0);
|
noiseNormalizeAmplitude(definition->_coverage_noise, -1.0, 3.0, 0);
|
||||||
noiseNormalizeAmplitude(definition->_shape_noise, -0.5, 0.5, 0);
|
noiseNormalizeAmplitude(definition->_shape_noise, -0.5, 0.5, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ Color _fakeApplyLightingToSurface(Renderer* renderer, Vector3 location, Vector3
|
||||||
return COLOR_WHITE;
|
return COLOR_WHITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer* cloudsCreatePreviewCoverageRenderer()
|
Renderer* cloudsPreviewCoverageCreateRenderer()
|
||||||
{
|
{
|
||||||
Renderer* result = rendererCreate();
|
Renderer* result = rendererCreate();
|
||||||
result->render_quality = 5;
|
result->render_quality = 5;
|
||||||
|
@ -26,7 +26,15 @@ Renderer* cloudsCreatePreviewCoverageRenderer()
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color cloudsGetPreviewCoverage(Renderer* renderer, double x, double y, double scaling, int perspective)
|
void cloudsPreviewCoverageBindLayer(Renderer* renderer, CloudsLayerDefinition* layer)
|
||||||
|
{
|
||||||
|
CloudsDefinition* definition = (CloudsDefinition*)CloudsDefinitionClass.create();
|
||||||
|
layersAddLayer(definition->layers, layer);
|
||||||
|
CloudsRendererClass.bind(renderer, definition);
|
||||||
|
CloudsDefinitionClass.destroy(definition);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color cloudsPreviewCoverageGetPixel(Renderer* renderer, double x, double y, double scaling, int perspective)
|
||||||
{
|
{
|
||||||
if (perspective)
|
if (perspective)
|
||||||
{
|
{
|
||||||
|
@ -55,25 +63,91 @@ Color cloudsGetPreviewCoverage(Renderer* renderer, double x, double y, double sc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer* cloudsCreatePreviewColorRenderer()
|
static void _getLightingStatus(Renderer* renderer, LightStatus* status, Vector3 normal, int opaque)
|
||||||
|
{
|
||||||
|
LightDefinition light;
|
||||||
|
|
||||||
|
UNUSED(renderer);
|
||||||
|
UNUSED(normal);
|
||||||
|
UNUSED(opaque);
|
||||||
|
|
||||||
|
light.color.r = 1.0;
|
||||||
|
light.color.g = 1.0;
|
||||||
|
light.color.b = 1.0;
|
||||||
|
light.direction.x = -1.0;
|
||||||
|
light.direction.y = -0.5;
|
||||||
|
light.direction.z = 1.0;
|
||||||
|
light.direction = v3Normalize(light.direction);
|
||||||
|
light.altered = 1;
|
||||||
|
light.reflection = 0.0;
|
||||||
|
lightingPushLight(status, &light);
|
||||||
|
|
||||||
|
light.color.r = 0.2;
|
||||||
|
light.color.g = 0.2;
|
||||||
|
light.color.b = 0.2;
|
||||||
|
light.direction.x = 1.0;
|
||||||
|
light.direction.y = -0.5;
|
||||||
|
light.direction.z = -1.0;
|
||||||
|
light.direction = v3Normalize(light.direction);
|
||||||
|
light.altered = 0;
|
||||||
|
light.reflection = 0.0;
|
||||||
|
lightingPushLight(status, &light);
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer* cloudsPreviewMaterialCreateRenderer()
|
||||||
{
|
{
|
||||||
Renderer* result = rendererCreate();
|
Renderer* result = rendererCreate();
|
||||||
result->render_quality = 8;
|
result->render_quality = 8;
|
||||||
|
result->atmosphere->getLightingStatus = _getLightingStatus;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color cloudsGetPreviewColor(Renderer* renderer, double x, double y)
|
static double _getDensity(Renderer* renderer, CloudsLayerDefinition* layer, Vector3 location)
|
||||||
|
{
|
||||||
|
UNUSED(renderer);
|
||||||
|
UNUSED(layer);
|
||||||
|
|
||||||
|
double distance = v3Norm(location);
|
||||||
|
if (distance > 1.0)
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
else if (distance < 0.8)
|
||||||
|
{
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (1.0 - distance) / 0.2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cloudsPreviewMaterialBindLayer(Renderer* renderer, CloudsLayerDefinition* layer)
|
||||||
|
{
|
||||||
|
CloudsDefinition* definition = (CloudsDefinition*)CloudsDefinitionClass.create();
|
||||||
|
layersAddLayer(definition->layers, layer);
|
||||||
|
CloudsRendererClass.bind(renderer, definition);
|
||||||
|
CloudsDefinitionClass.destroy(definition);
|
||||||
|
|
||||||
|
layer = layersGetLayer(renderer->clouds->definition->layers, 0);
|
||||||
|
layer->lower_altitude = -1.0;
|
||||||
|
layer->thickness = 2.0;
|
||||||
|
|
||||||
|
renderer->clouds->getLayerDensity = _getDensity;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color cloudsPreviewMaterialGetPixel(Renderer* renderer, double x, double y)
|
||||||
{
|
{
|
||||||
Vector3 start, end;
|
Vector3 start, end;
|
||||||
double thickness = 0.5;
|
double thickness = 2.0;
|
||||||
|
|
||||||
start.x = x * thickness * 0.5;
|
start.x = x * thickness * 0.5;
|
||||||
start.y = -y * thickness * 0.5;
|
start.z = y * thickness * 0.5;
|
||||||
start.z = thickness * 0.5;
|
start.y = thickness * 0.5;
|
||||||
|
|
||||||
end.x = start.x;
|
end.x = start.x;
|
||||||
end.y = start.y;
|
end.z = start.z;
|
||||||
end.z = -start.z;
|
end.y = -start.y;
|
||||||
|
|
||||||
return renderer->clouds->getColor(renderer, COLOR_BLUE, start, end);
|
return renderer->clouds->getColor(renderer, COLOR_BLUE, start, end);
|
||||||
}
|
}
|
||||||
|
|
28
src/rendering/clouds/clo_preview.h
Normal file
28
src/rendering/clouds/clo_preview.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef _PAYSAGES_CLOUDS_PREVIEW_H_
|
||||||
|
#define _PAYSAGES_CLOUDS_PREVIEW_H_
|
||||||
|
|
||||||
|
#include "public.h"
|
||||||
|
#include "../tools/euclid.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cloud preview helpers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Renderer* cloudsPreviewCoverageCreateRenderer();
|
||||||
|
void cloudsPreviewCoverageBindLayer(Renderer* renderer, CloudsLayerDefinition* layer);
|
||||||
|
Color cloudsPreviewCoverageGetPixel(Renderer* renderer, double x, double y, double scaling, int perspective);
|
||||||
|
|
||||||
|
Renderer* cloudsPreviewMaterialCreateRenderer();
|
||||||
|
void cloudsPreviewMaterialBindLayer(Renderer* renderer, CloudsLayerDefinition* layer);
|
||||||
|
Color cloudsPreviewMaterialGetPixel(Renderer* renderer, double x, double y);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,9 +1,11 @@
|
||||||
#include "private.h"
|
#include "private.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "../tools.h"
|
#include "../tools.h"
|
||||||
#include "../renderer.h"
|
#include "../renderer.h"
|
||||||
#include "clo_density.h"
|
#include "clo_density.h"
|
||||||
|
#include "clo_walking.h"
|
||||||
|
|
||||||
/******************** Fake ********************/
|
/******************** Fake ********************/
|
||||||
static int _fakeAlterLight(Renderer* renderer, LightDefinition* light, Vector3 location)
|
static int _fakeAlterLight(Renderer* renderer, LightDefinition* light, Vector3 location)
|
||||||
|
@ -25,24 +27,117 @@ static Color _fakeGetColor(Renderer* renderer, Color base, Vector3 start, Vector
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************** Real ********************/
|
/******************** Real ********************/
|
||||||
/*static int _cmpLayer(const void* layer1, const void* layer2)
|
typedef struct
|
||||||
{
|
{
|
||||||
return (((CloudsLayerDefinition*)layer1)->lower_altitude > ((CloudsLayerDefinition*)layer2)->lower_altitude) ? -1 : 1;
|
double light_power;
|
||||||
}*/
|
double out_scattering; /* Amount of light scattered away by heavy particles */
|
||||||
|
} AccumulatedLightData;
|
||||||
|
|
||||||
|
static void _walkerFilterCallback(CloudsWalker* walker)
|
||||||
|
{
|
||||||
|
CloudWalkerStepInfo* segment = cloudsWalkerGetLastSegment(walker);
|
||||||
|
AccumulatedLightData* data = (AccumulatedLightData*)segment->data;
|
||||||
|
|
||||||
|
assert(data != NULL);
|
||||||
|
|
||||||
|
double density_integral = segment->length * (segment->start.global_density + segment->end.global_density) / 2.0;
|
||||||
|
|
||||||
|
data->out_scattering += 0.3 * density_integral;
|
||||||
|
|
||||||
|
if (data->out_scattering > data->light_power)
|
||||||
|
{
|
||||||
|
cloudsWalkerOrderStop(walker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int _alterLight(Renderer* renderer, LightDefinition* light, Vector3 location)
|
static int _alterLight(Renderer* renderer, LightDefinition* light, Vector3 location)
|
||||||
{
|
{
|
||||||
CloudsDefinition* definition = renderer->clouds->definition;
|
CloudsDefinition* definition = renderer->clouds->definition;
|
||||||
int i, n;
|
int i, n;
|
||||||
|
|
||||||
|
AccumulatedLightData data;
|
||||||
|
data.out_scattering = 0.0;
|
||||||
|
data.light_power = colorGetPower(&light->color);
|
||||||
|
|
||||||
/* TODO Iter layers in sorted order */
|
/* TODO Iter layers in sorted order */
|
||||||
n = layersCount(definition->layers);
|
n = layersCount(definition->layers);
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
{
|
{
|
||||||
light->color = cloudsLayerFilterLight(layersGetLayer(definition->layers, i), renderer, light->color, location, v3Add(location, v3Scale(light->direction, -10000.0)), v3Scale(light->direction, -1.0));
|
CloudsLayerDefinition* layer = (CloudsLayerDefinition*)layersGetLayer(renderer->clouds->definition->layers, i);
|
||||||
/* TODO Reduce light->reflection too */
|
Vector3 ostart, oend;
|
||||||
|
|
||||||
|
ostart = location;
|
||||||
|
oend = v3Add(location, v3Scale(light->direction, -10000.0));
|
||||||
|
if (!cloudsOptimizeWalkingBounds(layer, &ostart, &oend))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
return n > 0;
|
else
|
||||||
|
{
|
||||||
|
CloudsWalker* walker;
|
||||||
|
|
||||||
|
walker = cloudsCreateWalker(renderer, layer, ostart, oend);
|
||||||
|
cloudsWalkerSetStepSize(walker, -1.0);
|
||||||
|
cloudsStartWalking(walker, _walkerFilterCallback, &data);
|
||||||
|
cloudsDeleteWalker(walker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double max_power = colorGetPower(&light->color) - data.out_scattering;
|
||||||
|
if (max_power < 0.0)
|
||||||
|
{
|
||||||
|
light->color = COLOR_BLACK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
colorLimitPower(&light->color, max_power);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.out_scattering > 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
double out_scattering; /* Amount of light scattered away by heavy particles */
|
||||||
|
Color in_scattering; /* Amount of light redirected toward the viewer */
|
||||||
|
} AccumulatedMaterialData;
|
||||||
|
|
||||||
|
static inline void _applyOutScattering(Color* col, double out_scattering)
|
||||||
|
{
|
||||||
|
if (out_scattering >= 1.0)
|
||||||
|
{
|
||||||
|
col->r = col->g = col->b = 0.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
col->r *= (1.0 - out_scattering);
|
||||||
|
col->g *= (1.0 - out_scattering);
|
||||||
|
col->b *= (1.0 - out_scattering);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _walkerMaterialCallback(CloudsWalker* walker)
|
||||||
|
{
|
||||||
|
CloudWalkerStepInfo* segment = cloudsWalkerGetLastSegment(walker);
|
||||||
|
AccumulatedMaterialData* data = (AccumulatedMaterialData*)segment->data;
|
||||||
|
Renderer* renderer = segment->renderer;
|
||||||
|
CloudsLayerDefinition* layer = segment->layer;
|
||||||
|
|
||||||
|
assert(data != NULL);
|
||||||
|
|
||||||
|
double density_integral = segment->length * (segment->start.global_density + segment->end.global_density) / 2.0;
|
||||||
|
|
||||||
|
data->out_scattering += 0.5 * density_integral;
|
||||||
|
|
||||||
|
Color in_scattering = renderer->applyLightingToSurface(renderer, segment->start.location, VECTOR_UP, &layer->material);
|
||||||
|
in_scattering.r *= density_integral * 5.0;
|
||||||
|
in_scattering.g *= density_integral * 5.0;
|
||||||
|
in_scattering.b *= density_integral * 5.0;
|
||||||
|
_applyOutScattering(&in_scattering, data->out_scattering);
|
||||||
|
|
||||||
|
data->in_scattering.r += in_scattering.r;
|
||||||
|
data->in_scattering.g += in_scattering.g;
|
||||||
|
data->in_scattering.b += in_scattering.b;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Color _getColor(Renderer* renderer, Color base, Vector3 start, Vector3 end)
|
static Color _getColor(Renderer* renderer, Color base, Vector3 start, Vector3 end)
|
||||||
|
@ -59,7 +154,39 @@ static Color _getColor(Renderer* renderer, Color base, Vector3 start, Vector3 en
|
||||||
/* TODO Iter layers in sorted order */
|
/* TODO Iter layers in sorted order */
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
{
|
{
|
||||||
base = cloudsApplyLayer(layersGetLayer(definition->layers, i), base, renderer, start, end);
|
CloudsLayerDefinition* layer = (CloudsLayerDefinition*)layersGetLayer(renderer->clouds->definition->layers, i);
|
||||||
|
Vector3 ostart, oend;
|
||||||
|
|
||||||
|
ostart = start;
|
||||||
|
oend = end;
|
||||||
|
if (!cloudsOptimizeWalkingBounds(layer, &ostart, &oend))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CloudsWalker* walker;
|
||||||
|
AccumulatedMaterialData data;
|
||||||
|
data.out_scattering = 0.0;
|
||||||
|
data.in_scattering = COLOR_BLACK;
|
||||||
|
|
||||||
|
walker = cloudsCreateWalker(renderer, layer, ostart, oend);
|
||||||
|
cloudsWalkerSetStepSize(walker, -1.0);
|
||||||
|
cloudsStartWalking(walker, _walkerMaterialCallback, &data);
|
||||||
|
cloudsDeleteWalker(walker);
|
||||||
|
|
||||||
|
/* Apply final out_scattering to base */
|
||||||
|
_applyOutScattering(&base, data.out_scattering);
|
||||||
|
|
||||||
|
/* Apply in_scattering */
|
||||||
|
base.r += data.in_scattering.r;
|
||||||
|
base.g += data.in_scattering.g;
|
||||||
|
base.b += data.in_scattering.b;
|
||||||
|
|
||||||
|
/* Apply aerial perspective approximation */
|
||||||
|
/* TODO This should be done at cloud entry */
|
||||||
|
base = renderer->atmosphere->applyAerialPerspective(renderer, ostart, base).final;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return base;
|
return base;
|
||||||
|
|
|
@ -1,149 +0,0 @@
|
||||||
#include "private.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Clouds tools.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "clo_walking.h"
|
|
||||||
#include "../renderer.h"
|
|
||||||
#include "../tools.h"
|
|
||||||
|
|
||||||
static inline Vector3 _getNormal(CloudsLayerDefinition* layer, Vector3 position, double detail)
|
|
||||||
{
|
|
||||||
Vector3 result = {0.0, 0.0, 0.0};
|
|
||||||
/*Vector3 dposition;
|
|
||||||
double val, dval;
|
|
||||||
|
|
||||||
val = _getDistanceToBorder(layer, position);
|
|
||||||
|
|
||||||
dposition.x = position.x + detail;
|
|
||||||
dposition.y = position.y;
|
|
||||||
dposition.z = position.z;
|
|
||||||
dval = val - _getDistanceToBorder(layer, dposition);
|
|
||||||
result.x += dval;
|
|
||||||
|
|
||||||
dposition.x = position.x - detail;
|
|
||||||
dval = val - _getDistanceToBorder(layer, dposition);
|
|
||||||
result.x -= dval;
|
|
||||||
|
|
||||||
dposition.x = position.x;
|
|
||||||
dposition.y = position.y + detail;
|
|
||||||
dval = val - _getDistanceToBorder(layer, dposition);
|
|
||||||
result.y += dval;
|
|
||||||
|
|
||||||
dposition.y = position.y - detail;
|
|
||||||
dval = val - _getDistanceToBorder(layer, dposition);
|
|
||||||
result.y -= dval;
|
|
||||||
|
|
||||||
dposition.y = position.y;
|
|
||||||
dposition.z = position.z + detail;
|
|
||||||
dval = val - _getDistanceToBorder(layer, dposition);
|
|
||||||
result.z += dval;
|
|
||||||
|
|
||||||
dposition.z = position.z - detail;
|
|
||||||
dval = val - _getDistanceToBorder(layer, dposition);
|
|
||||||
result.z -= dval;*/
|
|
||||||
|
|
||||||
return v3Normalize(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Color _applyLayerLighting(CloudsLayerDefinition* definition, Renderer* renderer, Vector3 location, double detail)
|
|
||||||
{
|
|
||||||
Vector3 normal;
|
|
||||||
Color col1, col2;
|
|
||||||
LightStatus* lighting;
|
|
||||||
|
|
||||||
normal = _getNormal(definition, location, 3.0);
|
|
||||||
if (renderer->render_quality > 3)
|
|
||||||
{
|
|
||||||
normal = v3Add(normal, _getNormal(definition, location, 2.0));
|
|
||||||
normal = v3Add(normal, _getNormal(definition, location, 1.0));
|
|
||||||
}
|
|
||||||
if (renderer->render_quality > 5)
|
|
||||||
{
|
|
||||||
normal = v3Add(normal, _getNormal(definition, location, 0.5));
|
|
||||||
}
|
|
||||||
if (renderer->render_quality > 8)
|
|
||||||
{
|
|
||||||
normal = v3Add(normal, _getNormal(definition, location, 0.75));
|
|
||||||
normal = v3Add(normal, _getNormal(definition, location, 1.25));
|
|
||||||
normal = v3Add(normal, _getNormal(definition, location, 2.5));
|
|
||||||
}
|
|
||||||
normal = v3Scale(v3Normalize(normal), definition->hardness);
|
|
||||||
|
|
||||||
return renderer->applyLightingToSurface(renderer, location, normal, &definition->material);
|
|
||||||
|
|
||||||
lighting = lightingCreateStatus(renderer->lighting, location, renderer->getCameraLocation(renderer, location));
|
|
||||||
renderer->atmosphere->getLightingStatus(renderer, lighting, normal, 0);
|
|
||||||
col1 = lightingApplyStatus(lighting, normal, &definition->material);
|
|
||||||
col2 = lightingApplyStatus(lighting, v3Scale(normal, -1.0), &definition->material);
|
|
||||||
lightingDeleteStatus(lighting);
|
|
||||||
|
|
||||||
col1.r = (col1.r + col2.r) / 2.0;
|
|
||||||
col1.g = (col1.g + col2.g) / 2.0;
|
|
||||||
col1.b = (col1.b + col2.b) / 2.0;
|
|
||||||
col1.a = (col1.a + col2.a) / 2.0;
|
|
||||||
|
|
||||||
return col1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Color cloudsApplyLayer(CloudsLayerDefinition* definition, Color base, Renderer* renderer, Vector3 start, Vector3 end)
|
|
||||||
{
|
|
||||||
int segment_count;
|
|
||||||
Color col;
|
|
||||||
CloudPrimarySegment segments[MAX_SEGMENT_COUNT];
|
|
||||||
|
|
||||||
segment_count = cloudsGetLayerPrimarySegments(renderer, definition, start, end, MAX_SEGMENT_COUNT, segments);
|
|
||||||
/* TODO Crawl in segments for render */
|
|
||||||
|
|
||||||
col = definition->material.base;
|
|
||||||
/*if (definition->transparencydepth == 0 || inside_length >= definition->transparencydepth)
|
|
||||||
{
|
|
||||||
col.a = 1.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
col.a = inside_length / definition->transparencydepth;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
col = renderer->atmosphere->applyAerialPerspective(renderer, start, col).final;
|
|
||||||
col.a = 0.0;
|
|
||||||
|
|
||||||
colorMask(&base, &col);
|
|
||||||
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
|
|
||||||
Color cloudsLayerFilterLight(CloudsLayerDefinition* definition, Renderer* renderer, Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light)
|
|
||||||
{
|
|
||||||
/*double inside_depth, total_depth, factor;
|
|
||||||
CloudSegment segments[MAX_SEGMENT_COUNT];
|
|
||||||
|
|
||||||
if (!cloudsOptimizeWalkingBounds(definition, &location, &light_location))
|
|
||||||
{
|
|
||||||
return light;
|
|
||||||
}
|
|
||||||
|
|
||||||
_getPrimarySegments(definition, renderer, location, direction_to_light, MAX_SEGMENT_COUNT, definition->lighttraversal, v3Norm(v3Sub(light_location, location)), &inside_depth, &total_depth, segments);
|
|
||||||
|
|
||||||
if (definition->lighttraversal < 0.0001)
|
|
||||||
{
|
|
||||||
factor = 0.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
factor = inside_depth / definition->lighttraversal;
|
|
||||||
if (factor > 1.0)
|
|
||||||
{
|
|
||||||
factor = 1.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
factor = 1.0 - (1.0 - definition->minimumlight) * factor;
|
|
||||||
|
|
||||||
light.r = light.r * factor;
|
|
||||||
light.g = light.g * factor;
|
|
||||||
light.b = light.b * factor;*/
|
|
||||||
|
|
||||||
return light;
|
|
||||||
}
|
|
|
@ -2,6 +2,47 @@
|
||||||
|
|
||||||
#include "../renderer.h"
|
#include "../renderer.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Control of the next walking order.
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CLOUD_WALKING_CONTINUE,
|
||||||
|
CLOUD_WALKING_STOP,
|
||||||
|
CLOUD_WALKING_REFINE,
|
||||||
|
CLOUD_WALKING_SUBDIVIDE
|
||||||
|
} CloudWalkingOrder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Additional info for walking orders.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CloudWalkingOrder order;
|
||||||
|
double precision;
|
||||||
|
int max_segments;
|
||||||
|
} CloudWalkingNextAction;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Private structure for the walker.
|
||||||
|
*/
|
||||||
|
struct CloudsWalker
|
||||||
|
{
|
||||||
|
Vector3 start;
|
||||||
|
Vector3 end;
|
||||||
|
Vector3 diff;
|
||||||
|
|
||||||
|
double cursor;
|
||||||
|
double max_length;
|
||||||
|
double step_size;
|
||||||
|
|
||||||
|
int started;
|
||||||
|
CloudWalkerStepInfo last_segment;
|
||||||
|
|
||||||
|
CloudWalkingNextAction next_action;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
int cloudsOptimizeWalkingBounds(CloudsLayerDefinition* layer, Vector3* start, Vector3* end)
|
int cloudsOptimizeWalkingBounds(CloudsLayerDefinition* layer, Vector3* start, Vector3* end)
|
||||||
{
|
{
|
||||||
Vector3 diff;
|
Vector3 diff;
|
||||||
|
@ -51,107 +92,176 @@ int cloudsOptimizeWalkingBounds(CloudsLayerDefinition* layer, Vector3* start, Ve
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO Limit the search length */
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cloudsGetLayerPrimarySegments(Renderer* renderer, CloudsLayerDefinition* layer, Vector3 start, Vector3 end, int max_segments, CloudPrimarySegment* out_segments)
|
CloudsWalker* cloudsCreateWalker(Renderer* renderer, CloudsLayerDefinition* layer, Vector3 start, Vector3 end)
|
||||||
{
|
{
|
||||||
int inside, segment_count;
|
CloudsWalker* result;
|
||||||
double step_length, segment_length;
|
|
||||||
Vector3 diff, walker, segment_start;
|
|
||||||
double render_precision, density;
|
|
||||||
double diff_length, progress;
|
|
||||||
|
|
||||||
if (max_segments <= 0)
|
result = (CloudsWalker*)malloc(sizeof (CloudsWalker));
|
||||||
{
|
|
||||||
return 0;
|
result->start = start;
|
||||||
|
result->end = end;
|
||||||
|
result->diff = v3Sub(end, start);
|
||||||
|
result->max_length = v3Norm(result->diff);
|
||||||
|
result->cursor = 0.0;
|
||||||
|
result->step_size = 1.0;
|
||||||
|
|
||||||
|
result->started = 0;
|
||||||
|
result->last_segment.renderer = renderer;
|
||||||
|
result->last_segment.layer = layer;
|
||||||
|
|
||||||
|
result->next_action.order = CLOUD_WALKING_CONTINUE;
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cloudsOptimizeWalkingBounds(layer, &start, &end))
|
void cloudsDeleteWalker(CloudsWalker* walker)
|
||||||
{
|
{
|
||||||
return 0;
|
free(walker);
|
||||||
}
|
}
|
||||||
|
|
||||||
diff = v3Sub(end, start);
|
void cloudsWalkerSetStepSize(CloudsWalker* walker, double step)
|
||||||
diff_length = v3Norm(diff);
|
|
||||||
|
|
||||||
if (diff_length < 0.000001)
|
|
||||||
{
|
{
|
||||||
return 0;
|
if (step > 0.0)
|
||||||
}
|
|
||||||
|
|
||||||
render_precision = 1.005 - 0.01 * (double)(renderer->render_quality * renderer->render_quality);
|
|
||||||
/*if (render_precision > max_total_length / 10.0)
|
|
||||||
{
|
{
|
||||||
render_precision = max_total_length / 10.0;
|
walker->step_size = step;
|
||||||
}
|
|
||||||
else if (render_precision < max_total_length / 10000.0)
|
|
||||||
{
|
|
||||||
render_precision = max_total_length / 10000.0;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
segment_count = 0;
|
|
||||||
segment_length = 0.0;
|
|
||||||
density = renderer->clouds->getLayerDensity(renderer, layer, start);
|
|
||||||
progress = 0.0;
|
|
||||||
step_length = render_precision;
|
|
||||||
inside = (density > 0.0);
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
progress += step_length;
|
|
||||||
walker = v3Add(start, v3Scale(diff, progress / diff_length));
|
|
||||||
|
|
||||||
if (progress >= diff_length)
|
|
||||||
{
|
|
||||||
density = 0.0;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
density = renderer->clouds->getLayerDensity(renderer, layer, walker);
|
/* TODO Automatic settings (using rendering quality and cloud feature size) */
|
||||||
|
walker->step_size = 1.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (density > 0.0)
|
static void _getPoint(CloudsWalker* walker, double cursor, CloudWalkerPoint* out_point)
|
||||||
{
|
{
|
||||||
if (inside)
|
out_point->distance_from_start = cursor;
|
||||||
|
out_point->location = v3Add(walker->start, v3Scale(walker->diff, out_point->distance_from_start / walker->max_length));
|
||||||
|
|
||||||
|
Renderer* renderer = walker->last_segment.renderer;
|
||||||
|
CloudsLayerDefinition* layer = walker->last_segment.layer;
|
||||||
|
out_point->global_density = renderer->clouds->getLayerDensity(renderer, layer, out_point->location);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _refineSegment(CloudsWalker* walker, double start_cursor, double start_density, double end_cursor, double end_density, double precision, CloudWalkerPoint* result)
|
||||||
{
|
{
|
||||||
/* inside the cloud */
|
CloudWalkerPoint middle;
|
||||||
segment_length += step_length;
|
|
||||||
|
_getPoint(walker, (start_cursor + end_cursor) / 2.0, &middle);
|
||||||
|
|
||||||
|
if (start_density == 0.0)
|
||||||
|
{
|
||||||
|
/* Looking for entry */
|
||||||
|
if (middle.distance_from_start - start_cursor < precision)
|
||||||
|
{
|
||||||
|
*result = middle;
|
||||||
|
}
|
||||||
|
else if (middle.global_density == 0.0)
|
||||||
|
{
|
||||||
|
_refineSegment(walker, middle.distance_from_start, middle.global_density, end_cursor, end_density, precision, result);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* entering the cloud */
|
_refineSegment(walker, start_cursor, start_density, middle.distance_from_start, middle.global_density, precision, result);
|
||||||
segment_length = step_length;
|
|
||||||
segment_start = v3Add(start, v3Scale(diff, (progress - step_length) / diff_length));
|
|
||||||
/* TODO Refine entry position */
|
|
||||||
|
|
||||||
inside = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (inside)
|
/* Looking for exit */
|
||||||
|
if (end_cursor - middle.distance_from_start < precision)
|
||||||
{
|
{
|
||||||
/* exiting the cloud */
|
*result = middle;
|
||||||
segment_length += step_length;
|
}
|
||||||
|
else if (middle.global_density == 0.0)
|
||||||
out_segments->enter = segment_start;
|
|
||||||
out_segments->exit = walker;
|
|
||||||
out_segments->length = segment_length;
|
|
||||||
out_segments++;
|
|
||||||
if (++segment_count >= max_segments)
|
|
||||||
{
|
{
|
||||||
break;
|
_refineSegment(walker, start_cursor, start_density, middle.distance_from_start, middle.global_density, precision, result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_refineSegment(walker, middle.distance_from_start, middle.global_density, end_cursor, end_density, precision, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* TODO Refine exit position */
|
|
||||||
|
|
||||||
inside = 0;
|
int cloudsWalkerPerformStep(CloudsWalker* walker)
|
||||||
|
{
|
||||||
|
if (!walker->started)
|
||||||
|
{
|
||||||
|
_getPoint(walker, 0.0, &walker->last_segment.end);
|
||||||
|
walker->started = 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
/* step = v3Scale(direction, (info.distance_to_edge < render_precision) ? render_precision : info.distance_to_edge); */
|
|
||||||
}
|
|
||||||
while (inside || (walker.y <= layer->lower_altitude + layer->thickness + 0.001 && walker.y >= layer->lower_altitude - 0.001 && progress < diff_length));
|
|
||||||
|
|
||||||
return segment_count;
|
if (walker->next_action.order == CLOUD_WALKING_STOP || walker->cursor >= walker->max_length)
|
||||||
|
{
|
||||||
|
walker->next_action.order = CLOUD_WALKING_STOP;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (walker->next_action.order == CLOUD_WALKING_CONTINUE)
|
||||||
|
{
|
||||||
|
/* TODO Limit to end */
|
||||||
|
walker->last_segment.start = walker->last_segment.end;
|
||||||
|
|
||||||
|
walker->cursor += walker->step_size;
|
||||||
|
|
||||||
|
_getPoint(walker, walker->cursor, &walker->last_segment.end);
|
||||||
|
walker->last_segment.length = walker->step_size;
|
||||||
|
walker->last_segment.refined = 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (walker->next_action.order == CLOUD_WALKING_REFINE)
|
||||||
|
{
|
||||||
|
/* Refine segment with dichotomy */
|
||||||
|
_refineSegment(walker,
|
||||||
|
walker->last_segment.start.distance_from_start,
|
||||||
|
walker->last_segment.start.global_density,
|
||||||
|
walker->last_segment.end.distance_from_start,
|
||||||
|
walker->last_segment.end.global_density,
|
||||||
|
walker->next_action.precision,
|
||||||
|
(walker->last_segment.start.global_density == 0.0) ? (&walker->last_segment.start) : (&walker->last_segment.end));
|
||||||
|
walker->last_segment.length = walker->last_segment.end.distance_from_start - walker->last_segment.start.distance_from_start;
|
||||||
|
walker->last_segment.refined = 1;
|
||||||
|
|
||||||
|
walker->next_action.order = CLOUD_WALKING_CONTINUE;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* TODO */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cloudsWalkerOrderStop(CloudsWalker* walker)
|
||||||
|
{
|
||||||
|
walker->next_action.order = CLOUD_WALKING_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cloudsWalkerOrderRefine(CloudsWalker* walker, double precision)
|
||||||
|
{
|
||||||
|
walker->next_action.order = CLOUD_WALKING_REFINE;
|
||||||
|
walker->next_action.precision = precision;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cloudsWalkerOrderSubdivide(CloudsWalker* walker, double max_segments)
|
||||||
|
{
|
||||||
|
walker->next_action.order = CLOUD_WALKING_SUBDIVIDE;
|
||||||
|
walker->next_action.max_segments = max_segments;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloudWalkerStepInfo* cloudsWalkerGetLastSegment(CloudsWalker* walker)
|
||||||
|
{
|
||||||
|
return &walker->last_segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cloudsStartWalking(CloudsWalker* walker, FuncCloudsWalkingCallback callback, void* data)
|
||||||
|
{
|
||||||
|
walker->last_segment.data = data;
|
||||||
|
while (cloudsWalkerPerformStep(walker))
|
||||||
|
{
|
||||||
|
callback(walker);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,33 @@ extern "C"
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
Vector3 enter;
|
double distance_from_start;
|
||||||
Vector3 exit;
|
Vector3 location;
|
||||||
|
double global_density;
|
||||||
|
} CloudWalkerPoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information on a segment yielded by walking.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Renderer* renderer;
|
||||||
|
CloudsLayerDefinition* layer;
|
||||||
|
|
||||||
|
CloudWalkerPoint start;
|
||||||
|
CloudWalkerPoint end;
|
||||||
double length;
|
double length;
|
||||||
} CloudPrimarySegment;
|
|
||||||
|
int refined;
|
||||||
|
/*int subdivision_level;
|
||||||
|
double precision_asked;*/
|
||||||
|
|
||||||
|
void* data;
|
||||||
|
} CloudWalkerStepInfo;
|
||||||
|
|
||||||
|
typedef struct CloudsWalker CloudsWalker;
|
||||||
|
|
||||||
|
typedef void (*FuncCloudsWalkingCallback)(CloudsWalker* walker);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optimize the search limits in a layer.
|
* Optimize the search limits in a layer.
|
||||||
|
@ -31,17 +54,81 @@ typedef struct
|
||||||
int cloudsOptimizeWalkingBounds(CloudsLayerDefinition* layer, Vector3* start, Vector3* end);
|
int cloudsOptimizeWalkingBounds(CloudsLayerDefinition* layer, Vector3* start, Vector3* end);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Go through the cloud layer to find segments (parts of the lookup that are likely to contain cloud).
|
* Create a cloud walker.
|
||||||
*
|
*
|
||||||
* @param renderer The renderer environment
|
* For better performance, the segment should by optimized using cloudsOptimizeWalkingBounds.
|
||||||
* @param layer The cloud layer
|
* @param renderer Renderer context
|
||||||
* @param start Start position of the lookup
|
* @param layer The cloud layer to traverse
|
||||||
* @param end End position of the lookup
|
* @param start Start of the walk
|
||||||
* @param max_segments Maximum number of segments to collect
|
* @param end End of the walk
|
||||||
* @param out_segments Allocated space to fill found segments
|
|
||||||
* @return Number of segments found
|
|
||||||
*/
|
*/
|
||||||
int cloudsGetLayerPrimarySegments(Renderer* renderer, CloudsLayerDefinition* layer, Vector3 start, Vector3 end, int max_segments, CloudPrimarySegment* out_segments);
|
CloudsWalker* cloudsCreateWalker(Renderer* renderer, CloudsLayerDefinition* layer, Vector3 start, Vector3 end);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a cloud walker.
|
||||||
|
*
|
||||||
|
* @param walker The walker to free
|
||||||
|
*/
|
||||||
|
void cloudsDeleteWalker(CloudsWalker* walker);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the segment size for next steps.
|
||||||
|
*
|
||||||
|
* @param walker The walker to configure
|
||||||
|
* @param step The step length, negative for automatic
|
||||||
|
*/
|
||||||
|
void cloudsWalkerSetStepSize(CloudsWalker* walker, double step);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a single step.
|
||||||
|
*
|
||||||
|
* @param walker The walker to use
|
||||||
|
* @return 1 to continue the loop, 0 to stop
|
||||||
|
*/
|
||||||
|
int cloudsWalkerPerformStep(CloudsWalker* walker);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Order the walker to stop.
|
||||||
|
*
|
||||||
|
* @param walker The walker to use
|
||||||
|
*/
|
||||||
|
void cloudsWalkerOrderStop(CloudsWalker* walker);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Order the walker to refine the search for cloud entry or exit.
|
||||||
|
*
|
||||||
|
* The refinement will next yield a shorter version of the segment, containing only the cloud-inside portion, with a
|
||||||
|
* tolerance fixed by precision. For an entry point, this will discard the part before cloud entry. For en exit point,
|
||||||
|
* the portion after this point will be part of the next step, as normal walking resumes.
|
||||||
|
* @param walker The walker to use
|
||||||
|
* @param precision Precision wanted for the refinement
|
||||||
|
*/
|
||||||
|
void cloudsWalkerOrderRefine(CloudsWalker* walker, double precision);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Order the walker to subdivide the previous segment in smaller segments.
|
||||||
|
*
|
||||||
|
* @param walker The walker to use
|
||||||
|
* @param max_segments Maximal number of segments
|
||||||
|
*/
|
||||||
|
void cloudsWalkerOrderSubdivide(CloudsWalker* walker, double max_segments);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the last segment information.
|
||||||
|
*
|
||||||
|
* @param walker The walker to use
|
||||||
|
*/
|
||||||
|
CloudWalkerStepInfo* cloudsWalkerGetLastSegment(CloudsWalker* walker);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start walking automatically through a segment.
|
||||||
|
*
|
||||||
|
* The callback will be called with each segment found, giving info and asking for desired alteration on walking.
|
||||||
|
* @param walker The walker to use
|
||||||
|
* @param callback Callback to be called with each found segment
|
||||||
|
* @param data User data that will be passed back in the callback
|
||||||
|
*/
|
||||||
|
void cloudsStartWalking(CloudsWalker* walker, FuncCloudsWalkingCallback callback, void* data);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,12 +80,6 @@ LayerType cloudsGetLayerType();
|
||||||
void cloudsAutoPreset(CloudsDefinition* definition, CloudsPreset preset);
|
void cloudsAutoPreset(CloudsDefinition* definition, CloudsPreset preset);
|
||||||
void cloudsLayerAutoPreset(CloudsLayerDefinition* definition, CloudsLayerPreset preset);
|
void cloudsLayerAutoPreset(CloudsLayerDefinition* definition, CloudsLayerPreset preset);
|
||||||
|
|
||||||
Renderer* cloudsCreatePreviewCoverageRenderer();
|
|
||||||
Color cloudsGetPreviewCoverage(Renderer* renderer, double x, double y, double scaling, int perspective);
|
|
||||||
|
|
||||||
Renderer* cloudsCreatePreviewColorRenderer();
|
|
||||||
Color cloudsGetPreviewColor(Renderer* renderer, double x, double y);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "auto.h"
|
#include "auto.h"
|
||||||
|
#include "tools/data.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "scenery.h"
|
#include "scenery.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
@ -13,6 +14,12 @@
|
||||||
void paysagesInit()
|
void paysagesInit()
|
||||||
{
|
{
|
||||||
systemInit();
|
systemInit();
|
||||||
|
if (!dataInit())
|
||||||
|
{
|
||||||
|
/* TODO Add error callback (for interface) */
|
||||||
|
fprintf(stderr, "ERROR : Can't locate data files.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
openclInit();
|
openclInit();
|
||||||
|
|
||||||
sceneryInit();
|
sceneryInit();
|
||||||
|
|
|
@ -202,17 +202,8 @@ void noiseValidate(NoiseGenerator* generator)
|
||||||
generator->_max_value = generator->height_offset;
|
generator->_max_value = generator->height_offset;
|
||||||
for (x = 0; x < generator->level_count; x++)
|
for (x = 0; x < generator->level_count; x++)
|
||||||
{
|
{
|
||||||
double min_value = generator->levels[x].minvalue;
|
generator->_min_value += generator->levels[x].minvalue;
|
||||||
double max_value = min_value + generator->levels[x].amplitude;
|
generator->_max_value += generator->levels[x].minvalue + generator->levels[x].amplitude;
|
||||||
|
|
||||||
if (min_value < generator->_min_value)
|
|
||||||
{
|
|
||||||
generator->_min_value = min_value;
|
|
||||||
}
|
|
||||||
if (max_value > generator->_max_value)
|
|
||||||
{
|
|
||||||
generator->_max_value = max_value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,14 +385,14 @@ void noiseNormalizeAmplitude(NoiseGenerator* generator, double minvalue, double
|
||||||
|
|
||||||
for (level = 0; level < generator->level_count; level++)
|
for (level = 0; level < generator->level_count; level++)
|
||||||
{
|
{
|
||||||
generator->levels[level].minvalue = minvalue + (generator->levels[level].minvalue - current_minvalue) * factor;
|
generator->levels[level].minvalue *= factor;
|
||||||
generator->levels[level].amplitude *= factor;
|
generator->levels[level].amplitude *= factor;
|
||||||
if (adjust_scaling)
|
if (adjust_scaling)
|
||||||
{
|
{
|
||||||
generator->levels[level].wavelength *= factor;
|
generator->levels[level].wavelength *= factor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*generator->height_offset = minvalue + (generator->height_offset - current_minvalue) * factor;*/
|
generator->height_offset = minvalue + (generator->height_offset - current_minvalue) * factor;
|
||||||
noiseValidate(generator);
|
noiseValidate(generator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,7 @@ typedef struct
|
||||||
|
|
||||||
/* Heightmap manipulation */
|
/* Heightmap manipulation */
|
||||||
int terrainIsPainted(TerrainHeightMap* heightmap, int x, int z);
|
int terrainIsPainted(TerrainHeightMap* heightmap, int x, int z);
|
||||||
|
void terrainClearPainting(TerrainHeightMap* heightmap);
|
||||||
void terrainBrushElevation(TerrainHeightMap* heightmap, TerrainBrush* brush, double value);
|
void terrainBrushElevation(TerrainHeightMap* heightmap, TerrainBrush* brush, double value);
|
||||||
void terrainBrushSmooth(TerrainHeightMap* heightmap, TerrainBrush* brush, double value);
|
void terrainBrushSmooth(TerrainHeightMap* heightmap, TerrainBrush* brush, double value);
|
||||||
void terrainBrushAddNoise(TerrainHeightMap* heightmap, TerrainBrush* brush, NoiseGenerator* generator, double value);
|
void terrainBrushAddNoise(TerrainHeightMap* heightmap, TerrainBrush* brush, NoiseGenerator* generator, double value);
|
||||||
|
|
|
@ -27,13 +27,13 @@ static TerrainDefinition* _createDefinition()
|
||||||
{
|
{
|
||||||
TerrainDefinition* definition = malloc(sizeof(TerrainDefinition));
|
TerrainDefinition* definition = malloc(sizeof(TerrainDefinition));
|
||||||
|
|
||||||
definition->height = 0.0;
|
definition->height = 1.0;
|
||||||
definition->scaling = 1.0;
|
definition->scaling = 1.0;
|
||||||
definition->shadow_smoothing = 0.0;
|
definition->shadow_smoothing = 0.0;
|
||||||
|
|
||||||
definition->height_map = terrainHeightMapCreate(definition);
|
definition->height_map = terrainHeightMapCreate(definition);
|
||||||
|
|
||||||
definition->water_height = -0.8;
|
definition->water_height = -0.3;
|
||||||
|
|
||||||
definition->_height_noise = noiseCreateGenerator();
|
definition->_height_noise = noiseCreateGenerator();
|
||||||
|
|
||||||
|
|
|
@ -454,6 +454,12 @@ int terrainIsPainted(TerrainHeightMap* heightmap, int x, int z)
|
||||||
return _getDataPointer(&heightmap->brush_data, x, z, NULL, NULL, 0) || _getDataPointer(&heightmap->merged_data, x, z, NULL, NULL, 0);
|
return _getDataPointer(&heightmap->brush_data, x, z, NULL, NULL, 0) || _getDataPointer(&heightmap->merged_data, x, z, NULL, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void terrainClearPainting(TerrainHeightMap* heightmap)
|
||||||
|
{
|
||||||
|
_clearData(&heightmap->merged_data);
|
||||||
|
_clearData(&heightmap->brush_data);
|
||||||
|
}
|
||||||
|
|
||||||
typedef double (*BrushCallback)(TerrainHeightMap* heightmap, TerrainBrush* brush, double x, double z, double basevalue, double influence, double force, void* data);
|
typedef double (*BrushCallback)(TerrainHeightMap* heightmap, TerrainBrush* brush, double x, double z, double basevalue, double influence, double force, void* data);
|
||||||
|
|
||||||
static inline void _applyBrush(TerrainHeightMap* heightmap, TerrainBrush* brush, double force, void* data, BrushCallback callback)
|
static inline void _applyBrush(TerrainHeightMap* heightmap, TerrainBrush* brush, double force, void* data, BrushCallback callback)
|
||||||
|
|
|
@ -19,7 +19,7 @@ void terrainAutoPreset(TerrainDefinition* definition, TerrainPreset preset)
|
||||||
noiseNormalizeAmplitude(definition->_height_noise, -1.0, 1.0, 0);
|
noiseNormalizeAmplitude(definition->_height_noise, -1.0, 1.0, 0);
|
||||||
noiseSetFunctionParams(definition->_height_noise, NOISE_FUNCTION_SIMPLEX, 0.0, 0.0);
|
noiseSetFunctionParams(definition->_height_noise, NOISE_FUNCTION_SIMPLEX, 0.0, 0.0);
|
||||||
definition->scaling = 1.0;
|
definition->scaling = 1.0;
|
||||||
definition->height = 15.0;
|
definition->height = 30.0;
|
||||||
definition->shadow_smoothing = 0.03;
|
definition->shadow_smoothing = 0.03;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
34
src/rendering/tools/data.c
Normal file
34
src/rendering/tools/data.c
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#include "data.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static const char* _datapath = NULL;
|
||||||
|
|
||||||
|
static int _tryDataPath(const char* path)
|
||||||
|
{
|
||||||
|
char* buffer;
|
||||||
|
|
||||||
|
buffer = malloc(sizeof (char) * (strlen(path) + 30));
|
||||||
|
strcpy(buffer, path);
|
||||||
|
strcat(buffer, "/.paysages_data");
|
||||||
|
|
||||||
|
FILE* f = fopen(buffer, "r");
|
||||||
|
free(buffer);
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
_datapath = path;
|
||||||
|
fclose(f);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int dataInit()
|
||||||
|
{
|
||||||
|
return _tryDataPath("./data");
|
||||||
|
}
|
10
src/rendering/tools/data.h
Normal file
10
src/rendering/tools/data.h
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef _PAYSAGES_TOOLS_DATA_H_
|
||||||
|
#define _PAYSAGES_TOOLS_DATA_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Data directory management.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int dataInit();
|
||||||
|
|
||||||
|
#endif
|
|
@ -29,6 +29,11 @@ static inline void _add_methods_to_case(TCase* tc, ...)
|
||||||
suite_add_tcase(s, tc); \
|
suite_add_tcase(s, tc); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***** Boolean assertions *****/
|
||||||
|
#define ck_assert_true(_X_) ck_assert_int_ne((_X_), 0)
|
||||||
|
#define ck_assert_false(_X_) ck_assert_int_eq((_X_), 0)
|
||||||
|
|
||||||
|
/***** Floating point assertions *****/
|
||||||
static inline int _double_equals(double x, double y)
|
static inline int _double_equals(double x, double y)
|
||||||
{
|
{
|
||||||
return fabs(x - y) < 0.00000000001;
|
return fabs(x - y) < 0.00000000001;
|
||||||
|
@ -39,7 +44,7 @@ static inline int _double_not_equals(double x, double y)
|
||||||
}
|
}
|
||||||
static inline int _double_greater(double x, double y)
|
static inline int _double_greater(double x, double y)
|
||||||
{
|
{
|
||||||
return _double_not_equals(x, y) || (x > y);
|
return _double_not_equals(x, y) && (x > y);
|
||||||
}
|
}
|
||||||
static inline int _double_greater_or_equal(double x, double y)
|
static inline int _double_greater_or_equal(double x, double y)
|
||||||
{
|
{
|
||||||
|
@ -47,7 +52,7 @@ static inline int _double_greater_or_equal(double x, double y)
|
||||||
}
|
}
|
||||||
static inline int _double_less(double x, double y)
|
static inline int _double_less(double x, double y)
|
||||||
{
|
{
|
||||||
return _double_not_equals(x, y) || (x < y);
|
return _double_not_equals(x, y) && (x < y);
|
||||||
}
|
}
|
||||||
static inline int _double_less_or_equal(double x, double y)
|
static inline int _double_less_or_equal(double x, double y)
|
||||||
{
|
{
|
||||||
|
@ -58,8 +63,8 @@ static inline int _double_less_or_equal(double x, double y)
|
||||||
#define ck_assert_double_eq(X, Y) _ck_assert_double(_double_equals, X, ==, Y)
|
#define ck_assert_double_eq(X, Y) _ck_assert_double(_double_equals, X, ==, Y)
|
||||||
#define ck_assert_double_ne(X, Y) _ck_assert_double(_double_not_equals, X, !=, Y)
|
#define ck_assert_double_ne(X, Y) _ck_assert_double(_double_not_equals, X, !=, Y)
|
||||||
#define ck_assert_double_gt(X, Y) _ck_assert_double(_double_greater, X, >, Y)
|
#define ck_assert_double_gt(X, Y) _ck_assert_double(_double_greater, X, >, Y)
|
||||||
#define ck_assert_double_lt(X, Y) _ck_assert_double(_double_greater_or_equal, X, >=, Y)
|
#define ck_assert_double_lt(X, Y) _ck_assert_double(_double_less, X, <, Y)
|
||||||
#define ck_assert_double_gte(X, Y) _ck_assert_double(_double_less, X, <, Y)
|
#define ck_assert_double_gte(X, Y) _ck_assert_double(_double_greater_or_equal, X, >=, Y)
|
||||||
#define ck_assert_double_lte(X, Y) _ck_assert_double(_double_less_or_equal, X, <=, Y)
|
#define ck_assert_double_lte(X, Y) _ck_assert_double(_double_less_or_equal, X, <=, Y)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ extern void test_euclid_case(Suite* s);
|
||||||
extern void test_camera_case(Suite* s);
|
extern void test_camera_case(Suite* s);
|
||||||
extern void test_clouds_case(Suite* s);
|
extern void test_clouds_case(Suite* s);
|
||||||
extern void test_render_case(Suite* s);
|
extern void test_render_case(Suite* s);
|
||||||
|
extern void test_noise_case(Suite* s);
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
|
@ -24,6 +25,7 @@ int main(int argc, char** argv)
|
||||||
test_camera_case(s);
|
test_camera_case(s);
|
||||||
test_clouds_case(s);
|
test_clouds_case(s);
|
||||||
test_render_case(s);
|
test_render_case(s);
|
||||||
|
test_noise_case(s);
|
||||||
|
|
||||||
SRunner *sr = srunner_create(s);
|
SRunner *sr = srunner_create(s);
|
||||||
srunner_run_all(sr, CK_NORMAL);
|
srunner_run_all(sr, CK_NORMAL);
|
||||||
|
|
|
@ -200,11 +200,9 @@ static double _getLayerDensitySinX(Renderer* renderer, CloudsLayerDefinition* la
|
||||||
return (density > 0.0) ? density : 0.0;
|
return (density > 0.0) ? density : 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
START_TEST(test_clouds_primary_segments)
|
START_TEST(test_clouds_walking)
|
||||||
{
|
{
|
||||||
int segment_count, i;
|
/* Init */
|
||||||
CloudPrimarySegment segments[10];
|
|
||||||
|
|
||||||
CloudsLayerDefinition* layer;
|
CloudsLayerDefinition* layer;
|
||||||
layer = cloudsGetLayerType().callback_create();
|
layer = cloudsGetLayerType().callback_create();
|
||||||
layer->lower_altitude = -1.0;
|
layer->lower_altitude = -1.0;
|
||||||
|
@ -217,36 +215,88 @@ START_TEST(test_clouds_primary_segments)
|
||||||
renderer->render_quality = 8;
|
renderer->render_quality = 8;
|
||||||
renderer->clouds->getLayerDensity = _getLayerDensitySinX;
|
renderer->clouds->getLayerDensity = _getLayerDensitySinX;
|
||||||
|
|
||||||
segment_count = cloudsGetLayerPrimarySegments(renderer, layer, v3(-0.4, 0.0, 0.0), v3(1.9, 0.0, 0.0), 10, segments);
|
CloudsWalker* walker = cloudsCreateWalker(renderer, layer, v3(-0.4, 0.0, 0.0), v3(10.0, 0.0, 0.0));
|
||||||
ck_assert_int_eq(segment_count, 2);
|
CloudWalkerStepInfo* segment;
|
||||||
for (i = 0; i < segment_count; i++)
|
int result;
|
||||||
{
|
|
||||||
ck_assert_double_eq(segments[i].enter.y, 0.0);
|
/* First step */
|
||||||
ck_assert_double_eq(segments[i].enter.z, 0.0);
|
cloudsWalkerSetStepSize(walker, 0.3);
|
||||||
ck_assert_double_eq(segments[i].exit.y, 0.0);
|
result = cloudsWalkerPerformStep(walker);
|
||||||
ck_assert_double_eq(segments[i].exit.z, 0.0);
|
segment = cloudsWalkerGetLastSegment(walker);
|
||||||
}
|
ck_assert_int_eq(result, 1);
|
||||||
ck_assert_double_in_range(segments[0].enter.x, -0.5, 0.0);
|
ck_assert_false(segment->refined);
|
||||||
ck_assert_double_in_range(segments[0].exit.x, 0.5, 1.0);
|
ck_assert_double_eq(segment->length, 0.3);
|
||||||
ck_assert_double_in_range(segments[0].length, 0.5, 1.5);
|
ck_assert_double_eq(segment->start.distance_from_start, 0.0);
|
||||||
ck_assert_double_gte(segments[1].enter.x, segments[0].exit.x);
|
ck_assert_vector_values(segment->start.location, -0.4, 0.0, 0.0);
|
||||||
ck_assert_double_in_range(segments[1].enter.x, 0.5, 1.0);
|
ck_assert_double_eq(segment->start.global_density, 0.0);
|
||||||
ck_assert_double_in_range(segments[1].exit.x, 1.5, 2.0);
|
ck_assert_double_eq(segment->end.distance_from_start, 0.3);
|
||||||
ck_assert_double_in_range(segments[1].length, 0.5, 1.5);
|
ck_assert_vector_values(segment->end.location, -0.1, 0.0, 0.0);
|
||||||
|
ck_assert_double_eq(segment->end.global_density, 0.0);
|
||||||
|
|
||||||
|
/* Second step */
|
||||||
|
result = cloudsWalkerPerformStep(walker);
|
||||||
|
segment = cloudsWalkerGetLastSegment(walker);
|
||||||
|
ck_assert_int_eq(result, 1);
|
||||||
|
ck_assert_false(segment->refined);
|
||||||
|
ck_assert_double_eq(segment->length, 0.3);
|
||||||
|
ck_assert_double_eq(segment->start.distance_from_start, 0.3);
|
||||||
|
ck_assert_vector_values(segment->start.location, -0.1, 0.0, 0.0);
|
||||||
|
ck_assert_double_eq(segment->start.global_density, 0.0);
|
||||||
|
ck_assert_double_eq(segment->end.distance_from_start, 0.6);
|
||||||
|
ck_assert_vector_values(segment->end.location, 0.2, 0.0, 0.0);
|
||||||
|
ck_assert_double_gt(segment->end.global_density, 0.9);
|
||||||
|
|
||||||
|
/* Order to refine second step around the entry point */
|
||||||
|
cloudsWalkerOrderRefine(walker, 0.01);
|
||||||
|
result = cloudsWalkerPerformStep(walker);
|
||||||
|
segment = cloudsWalkerGetLastSegment(walker);
|
||||||
|
ck_assert_int_eq(result, 1);
|
||||||
|
ck_assert_true(segment->refined);
|
||||||
|
ck_assert_double_in_range(segment->length, 0.19, 0.20);
|
||||||
|
ck_assert_double_in_range(segment->start.distance_from_start, 0.40, 0.41);
|
||||||
|
ck_assert_double_in_range(segment->start.location.x, 0.0, 0.01);
|
||||||
|
ck_assert_double_gt(segment->start.global_density, 0.0);
|
||||||
|
ck_assert_double_eq(segment->end.distance_from_start, 0.6);
|
||||||
|
ck_assert_vector_values(segment->end.location, 0.2, 0.0, 0.0);
|
||||||
|
ck_assert_double_gt(segment->end.global_density, 0.9);
|
||||||
|
|
||||||
|
/* Third step, change step size */
|
||||||
|
cloudsWalkerSetStepSize(walker, 0.4);
|
||||||
|
result = cloudsWalkerPerformStep(walker);
|
||||||
|
segment = cloudsWalkerGetLastSegment(walker);
|
||||||
|
ck_assert_int_eq(result, 1);
|
||||||
|
ck_assert_false(segment->refined);
|
||||||
|
ck_assert_double_eq(segment->length, 0.4);
|
||||||
|
ck_assert_double_eq(segment->start.distance_from_start, 0.6);
|
||||||
|
ck_assert_vector_values(segment->start.location, 0.2, 0.0, 0.0);
|
||||||
|
ck_assert_double_gt(segment->start.global_density, 0.9);
|
||||||
|
ck_assert_double_eq(segment->end.distance_from_start, 1.0);
|
||||||
|
ck_assert_vector_values(segment->end.location, 0.6, 0.0, 0.0);
|
||||||
|
ck_assert_double_eq(segment->end.global_density, 0.0);
|
||||||
|
|
||||||
|
/* Refine exit point */
|
||||||
|
cloudsWalkerOrderRefine(walker, 0.001);
|
||||||
|
result = cloudsWalkerPerformStep(walker);
|
||||||
|
segment = cloudsWalkerGetLastSegment(walker);
|
||||||
|
ck_assert_int_eq(result, 1);
|
||||||
|
ck_assert_true(segment->refined);
|
||||||
|
ck_assert_double_in_range(segment->length, 0.3, 0.301);
|
||||||
|
ck_assert_double_eq(segment->start.distance_from_start, 0.6);
|
||||||
|
ck_assert_vector_values(segment->start.location, 0.2, 0.0, 0.0);
|
||||||
|
ck_assert_double_gt(segment->start.global_density, 0.9);
|
||||||
|
ck_assert_double_in_range(segment->end.distance_from_start, 0.9, 0.901);
|
||||||
|
ck_assert_double_in_range(segment->end.location.x, 0.5, 0.501);
|
||||||
|
ck_assert_double_lt(segment->end.global_density, 0.1);
|
||||||
|
|
||||||
|
/* Clean up */
|
||||||
|
cloudsDeleteWalker(walker);
|
||||||
|
|
||||||
cloudsGetLayerType().callback_delete(layer);
|
cloudsGetLayerType().callback_delete(layer);
|
||||||
rendererDelete(renderer);
|
rendererDelete(renderer);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_clouds_preview_color)
|
TEST_CASE(clouds,
|
||||||
{
|
test_clouds_density,
|
||||||
Renderer* renderer = cloudsCreatePreviewColorRenderer();
|
test_clouds_walking_boundaries,
|
||||||
|
test_clouds_walking)
|
||||||
/* TODO Test the density overriding */
|
|
||||||
|
|
||||||
rendererDelete(renderer);
|
|
||||||
}
|
|
||||||
END_TEST
|
|
||||||
|
|
||||||
TEST_CASE(clouds, test_clouds_density, test_clouds_walking_boundaries, test_clouds_primary_segments, test_clouds_preview_color)
|
|
||||||
|
|
78
src/testing/test_noise.c
Normal file
78
src/testing/test_noise.c
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
#include "testing/common.h"
|
||||||
|
|
||||||
|
#include "rendering/noise.h"
|
||||||
|
|
||||||
|
START_TEST(test_noise_range)
|
||||||
|
{
|
||||||
|
NoiseGenerator* noise;
|
||||||
|
double minvalue, maxvalue;
|
||||||
|
|
||||||
|
noise = noiseCreateGenerator();
|
||||||
|
|
||||||
|
noiseAddLevelSimple(noise, 0.1, -1.0, 1.0);
|
||||||
|
noiseAddLevelSimple(noise, 0.2, -0.5, 0.2);
|
||||||
|
noiseAddLevelSimple(noise, 0.4, -0.3, 1.2);
|
||||||
|
noiseValidate(noise);
|
||||||
|
noiseGetRange(noise, &minvalue, &maxvalue);
|
||||||
|
|
||||||
|
ck_assert_double_eq(minvalue, -1.8);
|
||||||
|
ck_assert_double_eq(maxvalue, 2.4);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_noise_normalize)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
NoiseGenerator* noise;
|
||||||
|
|
||||||
|
noise = noiseCreateGenerator();
|
||||||
|
|
||||||
|
/* Symmetric case */
|
||||||
|
noiseAddLevelsSimple(noise, 10, 1.0, -4.0, 4.0, 0.5);
|
||||||
|
noiseValidate(noise);
|
||||||
|
noiseNormalizeAmplitude(noise, -1.0, 1.0, 0);
|
||||||
|
for (x = 0; x < 1000; x++)
|
||||||
|
{
|
||||||
|
double value = noiseGet1DTotal(noise, 0.01 * (double)x);
|
||||||
|
ck_assert_double_in_range(value, -1.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Target center differs from current center */
|
||||||
|
noiseClearLevels(noise);
|
||||||
|
noiseAddLevelsSimple(noise, 10, 1.0, -5.0, 5.0, 0.5);
|
||||||
|
noiseValidate(noise);
|
||||||
|
noiseNormalizeAmplitude(noise, 0.0, 1.0, 0);
|
||||||
|
for (x = 0; x < 1000; x++)
|
||||||
|
{
|
||||||
|
double value = noiseGet1DTotal(noise, 0.01 * (double)x);
|
||||||
|
ck_assert_double_in_range(value, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Asymmetric range */
|
||||||
|
noiseClearLevels(noise);
|
||||||
|
noiseAddLevelsSimple(noise, 10, 1.0, 0.0, 10.0, 0.0);
|
||||||
|
noiseValidate(noise);
|
||||||
|
noiseNormalizeAmplitude(noise, 0.0, 1.0, 0);
|
||||||
|
for (x = 0; x < 1000; x++)
|
||||||
|
{
|
||||||
|
double value = noiseGet1DTotal(noise, 0.01 * (double)x);
|
||||||
|
ck_assert_double_in_range(value, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Complex asymmetric case */
|
||||||
|
noiseClearLevels(noise);
|
||||||
|
noiseAddLevelsSimple(noise, 3, 1.0, -2.0, 8.0, 0.3);
|
||||||
|
noiseValidate(noise);
|
||||||
|
noiseNormalizeAmplitude(noise, -2.0, 4.0, 0.0);
|
||||||
|
for (x = 0; x < 1000; x++)
|
||||||
|
{
|
||||||
|
double value = noiseGet1DTotal(noise, 0.01 * (double)x);
|
||||||
|
ck_assert_double_in_range(value, -2.0, 4.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
noiseDeleteGenerator(noise);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
TEST_CASE(noise, test_noise_range, test_noise_normalize)
|
||||||
|
|
Loading…
Reference in a new issue