mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-01-21 21:20:07 -05:00
e4a29f56cb
-K2 adjustments were not being applied properly.
906 lines
40 KiB
C++
906 lines
40 KiB
C++
#include "FractoriumPch.h"
|
|
#include "Fractorium.h"
|
|
|
|
/// <summary>
|
|
/// Initialize the parameters UI.
|
|
/// </summary>
|
|
void Fractorium::InitParamsUI()
|
|
{
|
|
int row = 0;
|
|
int spinHeight = 20;
|
|
double dmax = numeric_limits<double>::max();
|
|
vector<string> comboVals;
|
|
QTableWidget* table = ui.ColorTable;
|
|
//Because QTableWidget does not allow for a single title bar/header
|
|
//at the top of a multi-column table, the workaround hack is to just
|
|
//make another single column table with no rows, and use the single
|
|
//column header as the title bar. Then positioning it right above the table
|
|
//that holds the data. Disallow selecting and resizing of the title bar.
|
|
SetFixedTableHeader(ui.ColorTableHeader->horizontalHeader());
|
|
SetFixedTableHeader(ui.GeometryTableHeader->horizontalHeader());
|
|
SetFixedTableHeader(ui.FilterTableHeader->horizontalHeader());
|
|
SetFixedTableHeader(ui.IterationTableHeader->horizontalHeader());
|
|
SetFixedTableHeader(ui.AnimationTableHeader->horizontalHeader());
|
|
//Color.
|
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_BrightnessSpin, spinHeight, 0.01, dmax, 1, SIGNAL(valueChanged(double)), SLOT(OnBrightnessChanged(double)), true, 4.0, 4.0, 4.0);
|
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_GammaSpin, spinHeight, 1, dmax, 0.5, SIGNAL(valueChanged(double)), SLOT(OnGammaChanged(double)), true, 4.0, 4.0, 4.0);
|
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_GammaThresholdSpin, spinHeight, 0, dmax, 0.01, SIGNAL(valueChanged(double)), SLOT(OnGammaThresholdChanged(double)), true, 0.1, 0.1, 0.0);
|
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_VibrancySpin, spinHeight, 0, dmax, 0.01, SIGNAL(valueChanged(double)), SLOT(OnVibrancyChanged(double)), true, 1.0, 1.0, 0.0);
|
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_HighlightSpin, spinHeight, -1.0, 10, 0.1, SIGNAL(valueChanged(double)), SLOT(OnHighlightPowerChanged(double)), true, 1.0, 1.0, -1.0);
|
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_K2Spin, spinHeight, 0, 99.0, 0.0001, SIGNAL(valueChanged(double)), SLOT(OnK2Changed(double)), true, 0, 0.0001, 0);
|
|
m_HighlightSpin->DoubleClickLowVal(-1.0);
|
|
int dec = 6;
|
|
m_BrightnessSpin->setDecimals(dec);
|
|
m_GammaSpin->setDecimals(dec);
|
|
m_GammaThresholdSpin->setDecimals(dec);
|
|
m_VibrancySpin->setDecimals(dec);
|
|
m_HighlightSpin->setDecimals(dec);
|
|
m_K2Spin->setDecimals(dec);
|
|
m_BgRow = row;
|
|
m_BackgroundColorButton = new QPushButton("...", table);
|
|
m_BackgroundColorButton->setMinimumWidth(21);
|
|
m_BackgroundColorButton->setMaximumWidth(21);
|
|
table->setCellWidget(row, 1, m_BackgroundColorButton);
|
|
table->item(row, 1)->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
|
connect(m_BackgroundColorButton, SIGNAL(clicked(bool)), this, SLOT(OnBackgroundColorButtonClicked(bool)), Qt::QueuedConnection);
|
|
row++;
|
|
comboVals.push_back("Step");
|
|
comboVals.push_back("Linear");
|
|
SetupCombo(table, this, row, 1, m_PaletteModeCombo, comboVals, SIGNAL(currentIndexChanged(int)), SLOT(OnPaletteModeComboCurrentIndexChanged(int)));
|
|
m_PaletteModeCombo->SetCurrentIndexStealth(int(ePaletteMode::PALETTE_LINEAR));
|
|
table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
|
|
//Geometry.
|
|
row = 0;
|
|
table = ui.GeometryTable;
|
|
SetupSpinner<SpinBox, int> (table, this, row, 1, m_WidthSpin, spinHeight, 10, 2048, 50, SIGNAL(valueChanged(int)), SLOT(OnWidthChanged(int)), true, width(), width(), width());
|
|
SetupSpinner<SpinBox, int> (table, this, row, 1, m_HeightSpin, spinHeight, 10, 2048, 50, SIGNAL(valueChanged(int)), SLOT(OnHeightChanged(int)), true, height(), height(), height());
|
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_CenterXSpin, spinHeight, -dmax, dmax, 0.05, SIGNAL(valueChanged(double)), SLOT(OnCenterXChanged(double)), true, 0, 0, 0);
|
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_CenterYSpin, spinHeight, -dmax, dmax, 0.05, SIGNAL(valueChanged(double)), SLOT(OnCenterYChanged(double)), true, 0, 0, 0);
|
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_ScaleSpin, spinHeight, 10, dmax, 20, SIGNAL(valueChanged(double)), SLOT(OnScaleChanged(double)), true, 240, 240, 240);
|
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_ZoomSpin, spinHeight, 0, 25, 0.2, SIGNAL(valueChanged(double)), SLOT(OnZoomChanged(double)), true, 0, 0, 0);
|
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_RotateSpin, spinHeight, -180, 180, 10, SIGNAL(valueChanged(double)), SLOT(OnRotateChanged(double)), true, 0, 0, 0);
|
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_ZPosSpin, spinHeight, -1000, 1000, 1, SIGNAL(valueChanged(double)), SLOT(OnZPosChanged(double)), true, 0, 1, 0);
|
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_PerspectiveSpin, spinHeight, -500, 500, 0.01, SIGNAL(valueChanged(double)), SLOT(OnPerspectiveChanged(double)), true, 0, 1, 0);
|
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_PitchSpin, spinHeight, -dmax, dmax, 1, SIGNAL(valueChanged(double)), SLOT(OnPitchChanged(double)), true, 0, 45, 0);
|
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_YawSpin, spinHeight, -dmax, dmax, 1, SIGNAL(valueChanged(double)), SLOT(OnYawChanged(double)), true, 0, 45, 0);
|
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_DepthBlurSpin, spinHeight, -dmax, dmax, 0.01, SIGNAL(valueChanged(double)), SLOT(OnDepthBlurChanged(double)), true, 0, 1, 0);
|
|
m_WidthSpin->m_DoubleClickNonZeroEvent = [&](SpinBox * sb, int val)
|
|
{
|
|
m_Controller->ResizeAndScale(val, m_HeightSpin->DoubleClickNonZero(), eScaleType::SCALE_WIDTH);
|
|
m_HeightSpin->SetValueStealth(m_HeightSpin->DoubleClickNonZero());
|
|
};
|
|
m_HeightSpin->m_DoubleClickNonZeroEvent = [&](SpinBox * sb, int val)
|
|
{
|
|
m_Controller->ResizeAndScale(m_WidthSpin->DoubleClickNonZero(), val, eScaleType::SCALE_HEIGHT);
|
|
m_WidthSpin->SetValueStealth(m_WidthSpin->DoubleClickNonZero());
|
|
};
|
|
dec = 4;
|
|
m_CenterXSpin->setDecimals(dec);
|
|
m_CenterYSpin->setDecimals(dec);
|
|
m_ZPosSpin->setDecimals(dec);
|
|
m_PerspectiveSpin->setDecimals(dec);
|
|
m_DepthBlurSpin->setDecimals(dec);
|
|
table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
|
|
//Filter.
|
|
row = 0;
|
|
table = ui.FilterTable;
|
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_SpatialFilterWidthSpin, spinHeight, 0, 2, 0.1, SIGNAL(valueChanged(double)), SLOT(OnSpatialFilterWidthChanged(double)), true, 1.0, 1.0, 0);
|
|
comboVals = SpatialFilterCreator<float>::FilterTypes();
|
|
SetupCombo(table, this, row, 1, m_SpatialFilterTypeCombo, comboVals, SIGNAL(currentIndexChanged(const QString&)), SLOT(OnSpatialFilterTypeComboCurrentIndexChanged(const QString&)));
|
|
m_SpatialFilterTypeCombo->SetCurrentIndexStealth(0);
|
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_DEFilterMinRadiusSpin, spinHeight, 0, 25, 1, SIGNAL(valueChanged(double)), SLOT(OnDEFilterMinRadiusWidthChanged(double)), true, 0, 0, 0);
|
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_DEFilterMaxRadiusSpin, spinHeight, 0, 25, 1, SIGNAL(valueChanged(double)), SLOT(OnDEFilterMaxRadiusWidthChanged(double)), true, 0.0, 9.0, 0);
|
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_DECurveSpin, spinHeight, 0.15, 5, 0.1, SIGNAL(valueChanged(double)), SLOT(OnDEFilterCurveWidthChanged(double)), true, 0.4, 0.4, 0.4);
|
|
table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
|
|
//Iteration.
|
|
row = 0;
|
|
table = ui.IterationTable;
|
|
auto quality = m_Settings->OpenCL() ? m_Settings->OpenClQuality() : m_Settings->CpuQuality();
|
|
SetupSpinner<SpinBox, int>( table, this, row, 1, m_SbsSpin, spinHeight, 1000, 100000, 100, SIGNAL(valueChanged(int)), SLOT(OnSbsChanged(int)), true, DEFAULT_SBS, DEFAULT_SBS, DEFAULT_SBS);
|
|
SetupSpinner<SpinBox, int>( table, this, row, 1, m_FuseSpin, spinHeight, 1, 1000, 5, SIGNAL(valueChanged(int)), SLOT(OnFuseChanged(int)), true, 15, 100, 15);
|
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_RandRangeSpin, spinHeight, 0.01, 1000, 0.1, SIGNAL(valueChanged(double)), SLOT(OnRandRangeChanged(double)), true, 1, 10, 1);
|
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_QualitySpin, spinHeight, 1, dmax, 50, SIGNAL(valueChanged(double)), SLOT(OnQualityChanged(double)), true, quality, 10, 10);
|
|
SetupSpinner<SpinBox, int>( table, this, row, 1, m_SupersampleSpin, spinHeight, 1, 4, 1, SIGNAL(valueChanged(int)), SLOT(OnSupersampleChanged(int)), true, 1, 2, 1);
|
|
m_RandRangeSpin->DoubleClickLowVal(1);
|
|
m_RandRangeSpin->setDecimals(4);
|
|
m_FuseSpin->DoubleClickLowVal(15);
|
|
m_SupersampleSpin->DoubleClickLowVal(1);
|
|
table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
|
|
//Animation.
|
|
row = 0;
|
|
table = ui.AnimationTable;
|
|
comboVals.clear();
|
|
comboVals.push_back("Linear");
|
|
comboVals.push_back("Smooth");
|
|
SetupCombo(table, this, row, 1, m_InterpTypeCombo, comboVals, SIGNAL(currentIndexChanged(int)), SLOT(OnInterpTypeComboCurrentIndexChanged(int)));
|
|
m_InterpTypeCombo->SetCurrentIndexStealth(int(eInterp::EMBER_INTERP_SMOOTH));
|
|
comboVals.clear();
|
|
comboVals.push_back("Linear");
|
|
comboVals.push_back("Log");
|
|
SetupCombo( table, this, row, 1, m_AffineInterpTypeCombo, comboVals, SIGNAL(currentIndexChanged(int)), SLOT(OnAffineInterpTypeComboCurrentIndexChanged(int)));
|
|
m_AffineInterpTypeCombo->SetCurrentIndexStealth(int(eAffineInterp::AFFINE_INTERP_LOG));
|
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_TemporalFilterWidthSpin, spinHeight, 1, 10, 1, SIGNAL(valueChanged(double)), SLOT(OnTemporalFilterWidthChanged(double)), true, 1);
|
|
comboVals = TemporalFilterCreator<float>::FilterTypes();
|
|
SetupCombo( table, this, row, 1, m_TemporalFilterTypeCombo, comboVals, SIGNAL(currentIndexChanged(const QString&)), SLOT(OnTemporalFilterTypeComboCurrentIndexChanged(const QString&)));
|
|
m_TemporalFilterTypeCombo->SetCurrentIndexStealth(int(eTemporalFilterType::GAUSSIAN_TEMPORAL_FILTER));
|
|
table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Return whether the apply all checkbox is checked.
|
|
/// </summary>
|
|
/// <returns>True if checked, else false.</returns>
|
|
bool Fractorium::ApplyAll()
|
|
{
|
|
return ui.ApplyAllParamsCheckBox->isChecked();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Color.
|
|
/// </summary>
|
|
|
|
/// <summary>
|
|
/// Set the brightness to be used for calculating K1 and K2 for filtering and final accum.
|
|
/// Called when brightness spinner is changed.
|
|
/// Resets the rendering process to the filtering stage.
|
|
/// </summary>
|
|
/// <param name="d">The brightness</param>
|
|
template <typename T>
|
|
void FractoriumEmberController<T>::BrightnessChanged(double d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_Brightness = d;
|
|
}, true, eProcessAction::FILTER_AND_ACCUM, m_Fractorium->ApplyAll());
|
|
}
|
|
|
|
void Fractorium::OnBrightnessChanged(double d) { m_Controller->BrightnessChanged(d); }
|
|
|
|
/// <summary>
|
|
/// Set the gamma to be used for final accum.
|
|
/// Called when gamma spinner is changed.
|
|
/// Resets the rendering process if temporal samples is greater than 1,
|
|
/// else if early clip is true, filter and accum, else final accum only.
|
|
/// </summary>
|
|
/// <param name="d">The gamma value</param>
|
|
template <typename T> void FractoriumEmberController<T>::GammaChanged(double d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_Gamma = d;
|
|
}, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY, m_Fractorium->ApplyAll());
|
|
}
|
|
void Fractorium::OnGammaChanged(double d) { m_Controller->GammaChanged(d); }
|
|
|
|
/// <summary>
|
|
/// Set the gamma threshold to be used for final accum.
|
|
/// Called when gamma threshold spinner is changed.
|
|
/// Resets the rendering process to the final accumulation stage.
|
|
/// </summary>
|
|
/// <param name="d">The gamma threshold</param>
|
|
template <typename T> void FractoriumEmberController<T>::GammaThresholdChanged(double d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_GammaThresh = d;
|
|
}, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY, m_Fractorium->ApplyAll());
|
|
}
|
|
void Fractorium::OnGammaThresholdChanged(double d) { m_Controller->GammaThresholdChanged(d); }
|
|
|
|
/// <summary>
|
|
/// Set the vibrancy to be used for final accum.
|
|
/// Called when vibrancy spinner is changed.
|
|
/// Resets the rendering process to the final accumulation stage if temporal samples is 1, else full reset.
|
|
/// </summary>
|
|
/// <param name="d">The vibrancy</param>
|
|
template <typename T> void FractoriumEmberController<T>::VibrancyChanged(double d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_Vibrancy = d;
|
|
}, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY, m_Fractorium->ApplyAll());
|
|
}
|
|
void Fractorium::OnVibrancyChanged(double d) { m_Controller->VibrancyChanged(d); }
|
|
|
|
/// <summary>
|
|
/// Set the highlight power to be used for final accum.
|
|
/// Called when highlight power spinner is changed.
|
|
/// Resets the rendering process to the final accumulation stage.
|
|
/// </summary>
|
|
/// <param name="d">The highlight power</param>
|
|
template <typename T> void FractoriumEmberController<T>::HighlightPowerChanged(double d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_HighlightPower = d;
|
|
}, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY, m_Fractorium->ApplyAll());
|
|
}
|
|
void Fractorium::OnHighlightPowerChanged(double d) { m_Controller->HighlightPowerChanged(d); }
|
|
|
|
/// <summary>
|
|
/// Set the k2 brightness value to be used for final accum.
|
|
/// Called when k2 is changed.
|
|
/// Resets the rendering process to the final accumulation stage.
|
|
/// </summary>
|
|
/// <param name="d">The k2 value</param>
|
|
template <typename T> void FractoriumEmberController<T>::K2Changed(double d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_K2 = d;
|
|
}, true, eProcessAction::FILTER_AND_ACCUM, m_Fractorium->ApplyAll());
|
|
}
|
|
|
|
void Fractorium::OnK2Changed(double d) { m_Controller->K2Changed(d); }
|
|
|
|
/// <summary>
|
|
/// Show the color selection dialog.
|
|
/// Called when background color button is clicked.
|
|
/// </summary>
|
|
/// <param name="checked">Ignored</param>
|
|
void Fractorium::OnBackgroundColorButtonClicked(bool checked)
|
|
{
|
|
m_ColorDialog->exec();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set a new ember background color when the user accepts the color dialog.
|
|
/// Also change the background and foreground colors of the color cell in the
|
|
/// color params table.
|
|
/// Resets the rendering process.
|
|
/// </summary>
|
|
/// <param name="color">The color to set, RGB in the 0-255 range</param>
|
|
template <typename T>
|
|
void FractoriumEmberController<T>::BackgroundChanged(const QColor& color)
|
|
{
|
|
auto itemRow = m_Fractorium->m_BgRow;
|
|
auto colorTable = m_Fractorium->ui.ColorTable;
|
|
colorTable->item(itemRow, 1)->setBackgroundColor(color);
|
|
auto r = ToString(color.red());
|
|
auto g = ToString(color.green());
|
|
auto b = ToString(color.blue());
|
|
colorTable->item(itemRow, 1)->setTextColor(VisibleColor(color));
|
|
colorTable->item(itemRow, 1)->setText("rgb(" + r + ", " + g + ", " + b + ")");
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
//Color is 0-255, normalize to 0-1.
|
|
ember.m_Background.r = color.red() / 255.0;
|
|
ember.m_Background.g = color.green() / 255.0;
|
|
ember.m_Background.b = color.blue() / 255.0;
|
|
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
|
|
}
|
|
|
|
void Fractorium::OnColorSelected(const QColor& color) { m_Controller->BackgroundChanged(color); }
|
|
|
|
/// <summary>
|
|
/// Set the palette index interpolation mode.
|
|
/// Called when palette mode combo box index is changed.
|
|
/// Resets the rendering process.
|
|
/// </summary>
|
|
/// <param name="index">The index of the palette mode combo box</param>
|
|
template <typename T> void FractoriumEmberController<T>::PaletteModeChanged(uint i)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_PaletteMode = i == 0 ? ePaletteMode::PALETTE_STEP : ePaletteMode::PALETTE_LINEAR;
|
|
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
|
|
}
|
|
void Fractorium::OnPaletteModeComboCurrentIndexChanged(int index) { m_Controller->PaletteModeChanged(index); }
|
|
|
|
/// <summary>
|
|
/// Geometry.
|
|
/// </summary>
|
|
|
|
/// <summary>
|
|
/// Set the width of the ember in pixels to the passed in value.
|
|
/// Called when the width spinner is changed in a manner other than double clicking.
|
|
/// Resets the rendering process.
|
|
/// </summary>
|
|
/// <param name="i">The width value in pixels to set</param>
|
|
template <typename T> void FractoriumEmberController<T>::WidthChanged(uint i)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_FinalRasW = i;
|
|
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
|
|
}
|
|
|
|
void Fractorium::OnWidthChanged(int i) { m_Controller->WidthChanged(i); }
|
|
|
|
/// <summary>
|
|
/// Set the height of the ember in pixels to the passed in value.
|
|
/// Called when the height spinner is changed in a manner other than double clicking.
|
|
/// Resets the rendering process.
|
|
/// </summary>
|
|
/// <param name="i">The height value in pixels to set</param>
|
|
template <typename T> void FractoriumEmberController<T>::HeightChanged(uint i)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_FinalRasH = i;
|
|
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
|
|
}
|
|
|
|
void Fractorium::OnHeightChanged(int i) { m_Controller->HeightChanged(i); }
|
|
|
|
/// <summary>
|
|
/// Set the width and height of the ember in pixels to the passed in values.
|
|
/// Called when either the width or height spinners are double clicked.
|
|
/// Because this will change the scale value, the scale spinner gets a stealth update.
|
|
/// For this reason, the affine scales are reset, even though they are not when doing a manual
|
|
/// height or width adjustment.
|
|
/// Resets the rendering process.
|
|
/// </summary>
|
|
/// <param name="width">The width value in pixels to set</param>
|
|
/// <param name="height">The height value in pixels to set</param>
|
|
/// <param name="scaleType">The height value in pixels to set</param>
|
|
template <typename T>
|
|
void FractoriumEmberController<T>::ResizeAndScale(int width, int height, eScaleType scaleType)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
m_Ember.SetSizeAndAdjustScale(width, height, false, scaleType);
|
|
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
|
|
m_Fractorium->m_ScaleSpin->SetValueStealth(m_Ember.m_PixelsPerUnit);
|
|
m_Fractorium->OnActionResetScale(true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the x offset applied to the center of the image.
|
|
/// Resets the rendering process.
|
|
/// </summary>
|
|
/// <param name="d">The x offset value</param>
|
|
template <typename T> void FractoriumEmberController<T>::CenterXChanged(double d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_CenterX = d;
|
|
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
|
|
}
|
|
void Fractorium::OnCenterXChanged(double d) { m_Controller->CenterXChanged(d); }
|
|
|
|
/// <summary>
|
|
/// Set the y offset applied to the center of the image.
|
|
/// Resets the rendering process.
|
|
/// </summary>
|
|
/// <param name="d">The y offset value</param>
|
|
template <typename T> void FractoriumEmberController<T>::CenterYChanged(double d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_CenterY = ember.m_RotCenterY = d;
|
|
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
|
|
}
|
|
void Fractorium::OnCenterYChanged(double d) { m_Controller->CenterYChanged(d); }
|
|
|
|
/// <summary>
|
|
/// Set the scale (pixels per unit) value of the image.
|
|
/// Note this will not increase the number of iters ran, but will degrade quality.
|
|
/// To preserve quality, but exponentially increase iters, use zoom.
|
|
/// Called when scale spinner is changed.
|
|
/// Resets the rendering process.
|
|
/// </summary>
|
|
/// <param name="d">The scale value</param>
|
|
template <typename T> void FractoriumEmberController<T>::ScaleChanged(double d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_PixelsPerUnit = d;
|
|
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
|
|
}
|
|
void Fractorium::OnScaleChanged(double d) { m_Controller->ScaleChanged(d); }
|
|
|
|
/// <summary>
|
|
/// Set the zoom value of the image.
|
|
/// Note this will increase the number of iters ran exponentially.
|
|
/// To zoom in without increasing iters, but sacrifice quality, use scale.
|
|
/// Called when zoom spinner is changed.
|
|
/// Resets the rendering process.
|
|
/// </summary>
|
|
/// <param name="d">The zoom value</param>
|
|
template <typename T> void FractoriumEmberController<T>::ZoomChanged(double d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_Zoom = d;
|
|
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
|
|
}
|
|
void Fractorium::OnZoomChanged(double d) { m_Controller->ZoomChanged(d); }
|
|
|
|
/// <summary>
|
|
/// Set the angular rotation of the image.
|
|
/// Called when rotate spinner is changed.
|
|
/// Resets the rendering process.
|
|
/// </summary>
|
|
/// <param name="d">The rotation in angles</param>
|
|
template <typename T> void FractoriumEmberController<T>::RotateChanged(double d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_Rotate = d;
|
|
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
|
|
}
|
|
void Fractorium::OnRotateChanged(double d) { m_Controller->RotateChanged(d); }
|
|
|
|
template <typename T> void FractoriumEmberController<T>::ZPosChanged(double d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_CamZPos = d;
|
|
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
|
|
}
|
|
void Fractorium::OnZPosChanged(double d) { m_Controller->ZPosChanged(d); }
|
|
|
|
template <typename T> void FractoriumEmberController<T>::PerspectiveChanged(double d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_CamPerspective = d;
|
|
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
|
|
}
|
|
void Fractorium::OnPerspectiveChanged(double d) { m_Controller->PerspectiveChanged(d); }
|
|
|
|
template <typename T> void FractoriumEmberController<T>::PitchChanged(double d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_CamPitch = d * DEG_2_RAD;
|
|
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
|
|
}
|
|
void Fractorium::OnPitchChanged(double d) { m_Controller->PitchChanged(d); }
|
|
|
|
template <typename T> void FractoriumEmberController<T>::YawChanged(double d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_CamYaw = d * DEG_2_RAD;
|
|
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
|
|
}
|
|
void Fractorium::OnYawChanged(double d) { m_Controller->YawChanged(d); }
|
|
|
|
template <typename T> void FractoriumEmberController<T>::DepthBlurChanged(double d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_CamDepthBlur = d;
|
|
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
|
|
}
|
|
void Fractorium::OnDepthBlurChanged(double d) { m_Controller->DepthBlurChanged(d); }
|
|
|
|
/// <summary>
|
|
/// Filter.
|
|
/// </summary>
|
|
|
|
/// <summary>
|
|
/// Set the spatial filter width.
|
|
/// Called when the spatial filter width spinner is changed.
|
|
/// Resets the rendering process to density filtering if early clip is used, else to final accumulation.
|
|
/// </summary>
|
|
/// <param name="d">The spatial filter width</param>
|
|
template <typename T> void FractoriumEmberController<T>::SpatialFilterWidthChanged(double d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_SpatialFilterRadius = d;
|
|
}, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY, m_Fractorium->ApplyAll());
|
|
}
|
|
|
|
void Fractorium::OnSpatialFilterWidthChanged(double d) { m_Controller->SpatialFilterWidthChanged(d); }
|
|
|
|
/// <summary>
|
|
/// Set the spatial filter type.
|
|
/// Called when the spatial filter type combo box index is changed.
|
|
/// Resets the rendering process to density filtering if early clip is used, else to final accumulation.
|
|
/// </summary>
|
|
/// <param name="text">The spatial filter type</param>
|
|
template <typename T> void FractoriumEmberController<T>::SpatialFilterTypeChanged(const QString& text)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_SpatialFilterType = SpatialFilterCreator<T>::FromString(text.toStdString());
|
|
}, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY, m_Fractorium->ApplyAll());
|
|
}
|
|
|
|
void Fractorium::OnSpatialFilterTypeComboCurrentIndexChanged(const QString& text) { m_Controller->SpatialFilterTypeChanged(text); }
|
|
|
|
/// <summary>
|
|
/// Set the density estimation filter min radius value.
|
|
/// Resets the rendering process to density filtering.
|
|
/// </summary>
|
|
/// <param name="d">The min radius value</param>
|
|
template <typename T>
|
|
void FractoriumEmberController<T>::DEFilterMinRadiusWidthChanged(double d)
|
|
{
|
|
if (m_Ember.m_MinRadDE != d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_MinRadDE = d;
|
|
}, true, eProcessAction::FILTER_AND_ACCUM, m_Fractorium->ApplyAll());
|
|
}
|
|
}
|
|
|
|
void Fractorium::OnDEFilterMinRadiusWidthChanged(double d)
|
|
{
|
|
ConstrainLow(m_DEFilterMinRadiusSpin, m_DEFilterMaxRadiusSpin);
|
|
m_Controller->DEFilterMinRadiusWidthChanged(m_DEFilterMinRadiusSpin->value());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the density estimation filter max radius value.
|
|
/// Resets the rendering process to density filtering.
|
|
/// </summary>
|
|
/// <param name="d">The max radius value</param>
|
|
template <typename T>
|
|
void FractoriumEmberController<T>::DEFilterMaxRadiusWidthChanged(double d)
|
|
{
|
|
if (m_Ember.m_MaxRadDE != d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_MaxRadDE = d;
|
|
}, true, eProcessAction::FILTER_AND_ACCUM, m_Fractorium->ApplyAll());
|
|
}
|
|
}
|
|
|
|
void Fractorium::OnDEFilterMaxRadiusWidthChanged(double d)
|
|
{
|
|
ConstrainHigh(m_DEFilterMinRadiusSpin, m_DEFilterMaxRadiusSpin);
|
|
m_Controller->DEFilterMaxRadiusWidthChanged(m_DEFilterMaxRadiusSpin->value());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the density estimation filter curve value.
|
|
/// Resets the rendering process to density filtering.
|
|
/// </summary>
|
|
/// <param name="d">The curve value</param>
|
|
template <typename T> void FractoriumEmberController<T>::DEFilterCurveWidthChanged(double d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_CurveDE = d;
|
|
}, true, eProcessAction::FILTER_AND_ACCUM, m_Fractorium->ApplyAll());
|
|
}
|
|
|
|
void Fractorium::OnDEFilterCurveWidthChanged(double d) { m_Controller->DEFilterCurveWidthChanged(d); }
|
|
|
|
/// <summary>
|
|
/// Iteration.
|
|
/// </summary>
|
|
|
|
/// <summary>
|
|
/// Set the iteration depth.
|
|
/// Called when the sub batch size spinner is changed.
|
|
/// Resets the rendering process.
|
|
/// </summary>
|
|
/// <param name="d">The sub batch size value to set</param>
|
|
template <typename T> void FractoriumEmberController<T>::SbsChanged(int d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_SubBatchSize = d;
|
|
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
|
|
}
|
|
void Fractorium::OnSbsChanged(int d) { m_Controller->SbsChanged(d); }
|
|
|
|
/// <summary>
|
|
/// Set the range from which to chose the starting random points, as well as point resets due to bad points.
|
|
/// Called when the rand range spinner is changed.
|
|
/// Resets the rendering process.
|
|
/// </summary>
|
|
/// <param name="d">The sub batch size value to set</param>
|
|
template <typename T> void FractoriumEmberController<T>::RandRangeChanged(double d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_RandPointRange = d;
|
|
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
|
|
}
|
|
|
|
void Fractorium::OnRandRangeChanged(double d) { m_Controller->RandRangeChanged(d); }
|
|
|
|
/// <summary>
|
|
/// Set the number of samples to disregard for each sub batch.
|
|
/// Called when the fuse count spinner is changed.
|
|
/// Resets the rendering process.
|
|
/// </summary>
|
|
/// <param name="d">The fuse count value to set</param>
|
|
template <typename T> void FractoriumEmberController<T>::FuseChanged(int d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_FuseCount = d;
|
|
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
|
|
}
|
|
void Fractorium::OnFuseChanged(int d) { m_Controller->FuseChanged(d); }
|
|
|
|
/// <summary>
|
|
/// Set the quality.
|
|
/// 10 is good for interactive rendering on the CPU.
|
|
/// 20-50 is good for OpenCL.
|
|
/// Above 500 seems to offer little additional value for final renders.
|
|
/// Called when the quality spinner is changed.
|
|
/// If rendering is done, and the value is greater than the last value,
|
|
/// the rendering process is continued, else it's reset.
|
|
/// </summary>
|
|
/// <param name="d">The quality in terms of iterations per pixel</param>
|
|
template <typename T> void FractoriumEmberController<T>::QualityChanged(double d) { }
|
|
void Fractorium::OnQualityChanged(double d) { m_Controller->QualityChanged(d); }
|
|
|
|
/// <summary>
|
|
/// Set the supersample.
|
|
/// Note this will dramatically degrade performance, especially in
|
|
/// OpenCL, while only giving a minor improvement in visual quality.
|
|
/// Values above 2 add no noticeable difference.
|
|
/// The user should only use this for a final render, or a quick preview, and then
|
|
/// reset it back to 1 when done.
|
|
/// Called when the supersample spinner is changed.
|
|
/// Resets the rendering process.
|
|
/// </summary>
|
|
/// <param name="d">The supersample value to set</param>
|
|
template <typename T> void FractoriumEmberController<T>::SupersampleChanged(int d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_Supersample = d;
|
|
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
|
|
}
|
|
void Fractorium::OnSupersampleChanged(int d) { m_Controller->SupersampleChanged(d); }
|
|
|
|
/// <summary>
|
|
/// Set the affine interpolation type.
|
|
/// Does not reset anything because this is only used for animation.
|
|
/// In the future, when animation is implemented, this will have an effect.
|
|
/// Called when the affine interp type combo box index is changed.
|
|
/// </summary>
|
|
/// <param name="index">The index</param>
|
|
template <typename T>
|
|
void FractoriumEmberController<T>::AffineInterpTypeChanged(int i)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
eAffineInterp interp;
|
|
|
|
if (i == 0)
|
|
interp = eAffineInterp::AFFINE_INTERP_LINEAR;
|
|
else if (i == 1)
|
|
interp = eAffineInterp::AFFINE_INTERP_LOG;
|
|
else
|
|
interp = eAffineInterp::AFFINE_INTERP_LINEAR;
|
|
|
|
ember.m_AffineInterp = interp;
|
|
|
|
if (!m_Fractorium->ApplyAll())
|
|
if (m_EmberFilePointer)
|
|
m_EmberFilePointer->m_AffineInterp = interp;
|
|
}, false, eProcessAction::NOTHING, m_Fractorium->ApplyAll());
|
|
}
|
|
|
|
void Fractorium::OnAffineInterpTypeComboCurrentIndexChanged(int index) { m_Controller->AffineInterpTypeChanged(index); }
|
|
|
|
/// <summary>
|
|
/// Set the interpolation type.
|
|
/// Does not reset anything because this is only used for animation.
|
|
/// Called when the interp type combo box index is changed.
|
|
/// </summary>
|
|
/// <param name="i">The index</param>
|
|
template <typename T>
|
|
void FractoriumEmberController<T>::InterpTypeChanged(int i)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
eInterp interp;
|
|
|
|
if (i == 0)
|
|
interp = eInterp::EMBER_INTERP_LINEAR;
|
|
else if (i == 1)
|
|
interp = eInterp::EMBER_INTERP_SMOOTH;
|
|
else
|
|
interp = eInterp::EMBER_INTERP_LINEAR;
|
|
|
|
ember.m_Interp = interp;
|
|
|
|
if (!m_Fractorium->ApplyAll())
|
|
if (m_EmberFilePointer)
|
|
m_EmberFilePointer->m_Interp = interp;
|
|
}, false, eProcessAction::NOTHING, m_Fractorium->ApplyAll());
|
|
}
|
|
|
|
void Fractorium::OnInterpTypeComboCurrentIndexChanged(int index) { m_Controller->InterpTypeChanged(index); }
|
|
|
|
/// <summary>
|
|
/// Set the temporal filter width to be used with animation.
|
|
/// Called when the temporal filter width spinner is changed.
|
|
/// Does not reset anything because this is only used for animation.
|
|
/// </summary>
|
|
/// <param name="d">The temporal filter width</param>
|
|
template <typename T>
|
|
void FractoriumEmberController<T>::TemporalFilterWidthChanged(double d)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_TemporalFilterWidth = d;
|
|
|
|
if (!m_Fractorium->ApplyAll())
|
|
if (m_EmberFilePointer)
|
|
m_EmberFilePointer->m_TemporalFilterWidth = d;
|
|
}, false, eProcessAction::NOTHING, m_Fractorium->ApplyAll());//Don't do anything until animation is implemented.
|
|
}
|
|
void Fractorium::OnTemporalFilterWidthChanged(double d) { m_Controller->TemporalFilterWidthChanged(d); }
|
|
|
|
/// <summary>
|
|
/// Set the temporal filter type to be used with animation.
|
|
/// Called when the temporal filter combo box index is changed.
|
|
/// Does not reset anything because this is only used for animation.
|
|
/// </summary>
|
|
/// <param name="text">The name of the temporal filter</param>
|
|
template <typename T>
|
|
void FractoriumEmberController<T>::TemporalFilterTypeChanged(const QString& text)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
auto filter = TemporalFilterCreator<T>::FromString(text.toStdString());
|
|
ember.m_TemporalFilterType = filter;
|
|
|
|
if (!m_Fractorium->ApplyAll())
|
|
if (m_EmberFilePointer)
|
|
m_EmberFilePointer->m_TemporalFilterType = filter;
|
|
}, false, eProcessAction::NOTHING, m_Fractorium->ApplyAll());//Don't do anything until animation is implemented.
|
|
}
|
|
void Fractorium::OnTemporalFilterTypeComboCurrentIndexChanged(const QString& text) { m_Controller->TemporalFilterTypeChanged(text); }
|
|
|
|
/// <summary>
|
|
/// Set the center.
|
|
/// This updates the spinners as well as the current ember center.
|
|
/// Resets the renering process.
|
|
/// </summary>
|
|
/// <param name="x">The x offset</param>
|
|
/// <param name="y">The y offset</param>
|
|
template <typename T>
|
|
void FractoriumEmberController<T>::SetCenter(double x, double y)
|
|
{
|
|
UpdateAll([&](Ember<T>& ember, bool isMain)
|
|
{
|
|
ember.m_CenterX = x;
|
|
ember.m_CenterY = ember.m_RotCenterY = y;
|
|
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
|
|
m_Fractorium->m_CenterXSpin->SetValueStealth(x);//Don't trigger a redraw twice.
|
|
m_Fractorium->m_CenterYSpin->SetValueStealth(y);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Fill the parameter tables and palette widgets with values from the current ember.
|
|
/// This takes ~1-2ms.
|
|
/// </summary>
|
|
template <typename T>
|
|
void FractoriumEmberController<T>::FillParamTablesAndPalette()
|
|
{
|
|
m_Fractorium->m_BrightnessSpin->SetValueStealth(m_Ember.m_Brightness);//Color.
|
|
m_Fractorium->m_GammaSpin->SetValueStealth(m_Ember.m_Gamma);
|
|
m_Fractorium->m_GammaThresholdSpin->SetValueStealth(m_Ember.m_GammaThresh);
|
|
m_Fractorium->m_VibrancySpin->SetValueStealth(m_Ember.m_Vibrancy);
|
|
m_Fractorium->m_HighlightSpin->SetValueStealth(m_Ember.m_HighlightPower);
|
|
m_Fractorium->m_K2Spin->SetValueStealth(m_Ember.m_K2);
|
|
m_Fractorium->m_ColorDialog->setCurrentColor(QColor(m_Ember.m_Background.r * 255, m_Ember.m_Background.g * 255, m_Ember.m_Background.b * 255));
|
|
m_Fractorium->ui.ColorTable->item(m_Fractorium->m_BgRow, 1)->setBackgroundColor(m_Fractorium->m_ColorDialog->currentColor());
|
|
BackgroundChanged(m_Fractorium->m_ColorDialog->currentColor());
|
|
m_Fractorium->m_PaletteModeCombo->SetCurrentIndexStealth(int(m_Ember.m_PaletteMode));
|
|
m_Fractorium->m_WidthSpin->SetValueStealth(m_Ember.m_FinalRasW);//Geometry.
|
|
m_Fractorium->m_HeightSpin->SetValueStealth(m_Ember.m_FinalRasH);
|
|
m_Fractorium->m_CenterXSpin->SetValueStealth(m_Ember.m_CenterX);
|
|
m_Fractorium->m_CenterYSpin->SetValueStealth(m_Ember.m_CenterY);
|
|
m_Fractorium->m_ScaleSpin->SetValueStealth(m_Ember.m_PixelsPerUnit);
|
|
m_Fractorium->m_ZoomSpin->SetValueStealth(m_Ember.m_Zoom);
|
|
m_Fractorium->m_RotateSpin->SetValueStealth(m_Ember.m_Rotate);
|
|
m_Fractorium->m_ZPosSpin->SetValueStealth(m_Ember.m_CamZPos);
|
|
m_Fractorium->m_PerspectiveSpin->SetValueStealth(m_Ember.m_CamPerspective);
|
|
m_Fractorium->m_PitchSpin->SetValueStealth(m_Ember.m_CamPitch * RAD_2_DEG_T);
|
|
m_Fractorium->m_YawSpin->SetValueStealth(m_Ember.m_CamYaw * RAD_2_DEG_T);
|
|
m_Fractorium->m_DepthBlurSpin->SetValueStealth(m_Ember.m_CamDepthBlur);
|
|
m_Fractorium->m_SpatialFilterWidthSpin->SetValueStealth(m_Ember.m_SpatialFilterRadius);//Filter.
|
|
m_Fractorium->m_SpatialFilterTypeCombo->SetCurrentIndexStealth(int(m_Ember.m_SpatialFilterType));
|
|
m_Fractorium->m_TemporalFilterWidthSpin->SetValueStealth(m_Ember.m_TemporalFilterWidth);
|
|
m_Fractorium->m_TemporalFilterTypeCombo->SetCurrentIndexStealth(int(m_Ember.m_TemporalFilterType));
|
|
m_Fractorium->m_DEFilterMinRadiusSpin->SetValueStealth(m_Ember.m_MinRadDE);
|
|
m_Fractorium->m_DEFilterMaxRadiusSpin->SetValueStealth(m_Ember.m_MaxRadDE);
|
|
m_Fractorium->m_DECurveSpin->SetValueStealth(m_Ember.m_CurveDE);
|
|
m_Fractorium->m_SbsSpin->SetValueStealth(m_Ember.m_SubBatchSize);//Iteration.
|
|
m_Fractorium->m_FuseSpin->SetValueStealth(m_Ember.m_FuseCount);
|
|
m_Fractorium->m_RandRangeSpin->SetValueStealth(m_Ember.m_RandPointRange);
|
|
m_Fractorium->m_QualitySpin->SetValueStealth(m_Ember.m_Quality);
|
|
m_Fractorium->m_SupersampleSpin->SetValueStealth(m_Ember.m_Supersample);
|
|
m_Fractorium->m_AffineInterpTypeCombo->SetCurrentIndexStealth(int(m_Ember.m_AffineInterp));
|
|
m_Fractorium->m_InterpTypeCombo->SetCurrentIndexStealth(int(m_Ember.m_Interp));
|
|
auto temp = m_Ember.m_Palette.m_Filename;
|
|
|
|
if (temp.get())
|
|
m_Fractorium->SetPaletteFileComboIndex(*temp.get());
|
|
|
|
//Update the palette preview widget.
|
|
m_Fractorium->ResetPaletteControls();
|
|
//Since the controls were cleared above, the adjusted palette will be identical to the base palette.
|
|
//Callers can set, apply and display palette adjustments after this function exits if needed.
|
|
SetBasePaletteAndAdjust(m_Ember.m_Palette);//Updating the palette GUI will trigger a full render.
|
|
InitLockedScale();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy all GUI widget values on the parameters tab to the passed in ember.
|
|
/// </summary>
|
|
/// <param name="ember">The ember to copy values to.</param>
|
|
template <typename T>
|
|
void FractoriumEmberController<T>::ParamsToEmber(Ember<T>& ember)
|
|
{
|
|
auto color = m_Fractorium->ui.ColorTable->item(5, 1)->backgroundColor();
|
|
ember.m_Brightness = m_Fractorium->m_BrightnessSpin->value();//Color.
|
|
ember.m_Gamma = m_Fractorium->m_GammaSpin->value();
|
|
ember.m_GammaThresh = m_Fractorium->m_GammaThresholdSpin->value();
|
|
ember.m_Vibrancy = m_Fractorium->m_VibrancySpin->value();
|
|
ember.m_HighlightPower = m_Fractorium->m_HighlightSpin->value();
|
|
ember.m_K2 = m_Fractorium->m_K2Spin->value();
|
|
ember.m_Background.r = color.red() / 255.0;
|
|
ember.m_Background.g = color.green() / 255.0;
|
|
ember.m_Background.b = color.blue() / 255.0;
|
|
ember.m_PaletteMode = ePaletteMode(m_Fractorium->m_PaletteModeCombo->currentIndex());
|
|
ember.m_FinalRasW = m_Fractorium->m_WidthSpin->value();//Geometry.
|
|
ember.m_FinalRasH = m_Fractorium->m_HeightSpin->value();
|
|
ember.m_CenterX = m_Fractorium->m_CenterXSpin->value();
|
|
ember.m_CenterY = ember.m_RotCenterY = m_Fractorium->m_CenterYSpin->value();
|
|
ember.m_PixelsPerUnit = m_Fractorium->m_ScaleSpin->value();
|
|
ember.m_Zoom = m_Fractorium->m_ZoomSpin->value();
|
|
ember.m_Rotate = m_Fractorium->m_RotateSpin->value();
|
|
ember.m_CamZPos = m_Fractorium->m_ZPosSpin->value();
|
|
ember.m_CamPerspective = m_Fractorium->m_PerspectiveSpin->value();
|
|
ember.m_CamPitch = m_Fractorium->m_PitchSpin->value() * DEG_2_RAD_T;
|
|
ember.m_CamYaw = m_Fractorium->m_YawSpin->value() * DEG_2_RAD_T;
|
|
ember.m_CamDepthBlur = m_Fractorium->m_DepthBlurSpin->value();
|
|
ember.m_SpatialFilterRadius = m_Fractorium->m_SpatialFilterWidthSpin->value();//Filter.
|
|
ember.m_SpatialFilterType = eSpatialFilterType(m_Fractorium->m_SpatialFilterTypeCombo->currentIndex());
|
|
ember.m_TemporalFilterWidth = m_Fractorium->m_TemporalFilterWidthSpin->value();
|
|
ember.m_TemporalFilterType = eTemporalFilterType(m_Fractorium->m_TemporalFilterTypeCombo->currentIndex());
|
|
ember.m_MinRadDE = m_Fractorium->m_DEFilterMinRadiusSpin->value();
|
|
ember.m_MaxRadDE = m_Fractorium->m_DEFilterMaxRadiusSpin->value();
|
|
ember.m_CurveDE = m_Fractorium->m_DECurveSpin->value();
|
|
ember.m_SubBatchSize = m_Fractorium->m_SbsSpin->value();
|
|
ember.m_FuseCount = m_Fractorium->m_FuseSpin->value();
|
|
ember.m_RandPointRange = m_Fractorium->m_RandRangeSpin->value();
|
|
ember.m_Quality = m_Fractorium->m_QualitySpin->value();
|
|
ember.m_Supersample = m_Fractorium->m_SupersampleSpin->value();
|
|
ember.m_AffineInterp = eAffineInterp(m_Fractorium->m_AffineInterpTypeCombo->currentIndex());
|
|
ember.m_Interp = eInterp(m_Fractorium->m_InterpTypeCombo->currentIndex());
|
|
ember.SyncSize();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the rotation.
|
|
/// This updates the spinner, optionally stealth.
|
|
/// </summary>
|
|
/// <param name="rot">The rotation value in angles to set</param>
|
|
/// <param name="stealth">True if stealth to skip re-rendering, else false to trigger a new render</param>
|
|
void Fractorium::SetRotation(double rot, bool stealth)
|
|
{
|
|
if (stealth)
|
|
m_RotateSpin->SetValueStealth(rot);
|
|
else
|
|
m_RotateSpin->setValue(rot);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the scale.
|
|
/// This is the number of raster pixels that correspond to the distance
|
|
/// between 0-1 in the cartesian plane. The higher the number, the more
|
|
/// zoomed in the image is.
|
|
/// Resets the rendering process.
|
|
/// </summary>
|
|
/// <param name="scale">The scale value</param>
|
|
void Fractorium::SetScale(double scale)
|
|
{
|
|
m_ScaleSpin->setValue(scale);
|
|
}
|
|
|
|
template class FractoriumEmberController<float>;
|
|
|
|
#ifdef DO_DOUBLE
|
|
template class FractoriumEmberController<double>;
|
|
#endif
|