mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-07-01 05:46:06 -04:00
--User changes
-Support 4k monitors, and in general, properly scale any monitor that is not HD. -Allow for a spatial filter of radius zero, which means do not use a spatial filter. -Add new variations: concentric, cpow3, helicoid, helix, rand_cubes, sphereblur. -Use a new method for computing elliptic which is more precise. Developed by Discord user Claude. -Remove the 8 variation per xform limitation on the GPU. -Allow for loading the last flame file on startup, rather than randoms. -Use two different default quality values in the interactive renderer, one each for CPU and GPU. -Creating linked xforms was using non-standard behavior. Make it match Apo and also support creating multiple linked xforms at once. --Bug fixes -No variations in an xform used to have the same behavior as a single linear variation with weight 1. While sensible, this breaks backward compatibility. No variations now sets the output point to zeroes. -Prevent crashing the program when adjusting a value on the main window while a final render is in progress. -The xaos table was inverted. --Code changes -Convert projects to Visual Studio 2017. -Change bad vals from +- 1e10 to +-1e20. -Reintroduce the symmetry tag in xforms for legacy support in programs that do not use color_speed. -Compiler will not let us use default values in templated member functions anymore.
This commit is contained in:
@ -58,7 +58,7 @@
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p align="center">Fractorium 1.0.0.6</p><p align="center"><span style=" font-size:10pt;">A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.</span></p><p align="center"><a href="http://fractorium.com"><span style=" text-decoration: underline; color:#0000ff;">fractorium.com</span></a><span style=" font-size:10pt;"><br/>Lead: Matt Feemster<br/>Contributors: Simon Detheridge, Michel Mastriani</span></p></body></html></string>
|
||||
<string><html><head/><body><p align="center">Fractorium 1.0.0.7</p><p align="center"><span style=" font-size:10pt;">A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.</span></p><p align="center"><a href="http://fractorium.com"><span style=" text-decoration: underline; color:#0000ff;">fractorium.com</span></a><span style=" font-size:10pt;"><br/>Lead: Matt Feemster<br/>Contributors: Simon Detheridge, Michel Mastriani</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
|
@ -118,9 +118,9 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
|
||||
//Save backup Xml.
|
||||
if (doAll)
|
||||
m_XmlWriter.Save(backup.toStdString().c_str(), m_EmberFile.m_Embers, 0, true, false, true);
|
||||
m_XmlWriter.Save(backup.toStdString().c_str(), m_EmberFile.m_Embers, 0, true, false, true, false, false);
|
||||
else
|
||||
m_XmlWriter.Save(backup.toStdString().c_str(), *m_Ember, 0, true, false, true);
|
||||
m_XmlWriter.Save(backup.toStdString().c_str(), *m_Ember, 0, true, false, true, false, false);
|
||||
|
||||
m_FinishedImageCount.store(0);
|
||||
SyncGuiToRenderer();
|
||||
|
@ -112,10 +112,10 @@ Fractorium::Fractorium(QWidget* p)
|
||||
m_Controller->SetupVariationsTree();
|
||||
m_Controller->FilteredVariations();
|
||||
|
||||
if (m_Info->Ok() && m_Settings->OpenCL() && m_QualitySpin->value() < (30 * m_Settings->Devices().size()))
|
||||
m_QualitySpin->setValue(30 * m_Settings->Devices().size());
|
||||
if (m_Info->Ok() && m_Settings->OpenCL() && m_QualitySpin->value() < (m_Settings->OpenClQuality() * m_Settings->Devices().size()))
|
||||
m_QualitySpin->setValue(m_Settings->OpenClQuality() * m_Settings->Devices().size());
|
||||
|
||||
int statusBarHeight = 20 * devicePixelRatio();
|
||||
int statusBarHeight = 20;// *devicePixelRatio();
|
||||
ui.StatusBar->setMinimumHeight(statusBarHeight);
|
||||
ui.StatusBar->setMaximumHeight(statusBarHeight);
|
||||
m_RenderStatusLabel = new QLabel(this);
|
||||
@ -222,6 +222,9 @@ Fractorium::~Fractorium()
|
||||
m_Settings->ShowGrid(ui.ActionDrawGrid->isChecked());
|
||||
m_Settings->setValue("windowState", saveState());
|
||||
m_Settings->sync();
|
||||
|
||||
if (m_Settings->LoadLast())
|
||||
m_Controller->SaveCurrentFileOnShutdown();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -330,8 +333,8 @@ bool Fractorium::eventFilter(QObject* o, QEvent* e)
|
||||
{
|
||||
if (o == ui.GLParentScrollArea && e->type() == QEvent::Resize)
|
||||
{
|
||||
m_WidthSpin->DoubleClickNonZero(ui.GLParentScrollArea->width());
|
||||
m_HeightSpin->DoubleClickNonZero(ui.GLParentScrollArea->height());
|
||||
m_WidthSpin->DoubleClickNonZero(ui.GLParentScrollArea->width() * ui.GLDisplay->devicePixelRatioF());
|
||||
m_HeightSpin->DoubleClickNonZero(ui.GLParentScrollArea->height() * ui.GLDisplay->devicePixelRatioF());
|
||||
}
|
||||
else if (auto ke = dynamic_cast<QKeyEvent*>(e))
|
||||
{
|
||||
@ -368,8 +371,8 @@ bool Fractorium::eventFilter(QObject* o, QEvent* e)
|
||||
/// <param name="e">The event</param>
|
||||
void Fractorium::resizeEvent(QResizeEvent* e)
|
||||
{
|
||||
m_WidthSpin->DoubleClickNonZero(ui.GLParentScrollArea->width());
|
||||
m_HeightSpin->DoubleClickNonZero(ui.GLParentScrollArea->height());
|
||||
m_WidthSpin->DoubleClickNonZero(ui.GLParentScrollArea->width() * ui.GLDisplay->devicePixelRatioF());
|
||||
m_HeightSpin->DoubleClickNonZero(ui.GLParentScrollArea->height() * ui.GLDisplay->devicePixelRatioF());
|
||||
QMainWindow::resizeEvent(e);
|
||||
}
|
||||
|
||||
|
@ -310,6 +310,7 @@ public slots:
|
||||
void OnXformsSelectAllButtonClicked(bool checked);
|
||||
void OnXformsSelectNoneButtonClicked(bool checked);
|
||||
bool IsXformSelected(size_t i);
|
||||
int SelectedXformCount(bool includeFinal);
|
||||
|
||||
//Xaos.
|
||||
void OnXaosChanged(double d);
|
||||
|
@ -74,8 +74,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1269</width>
|
||||
<height>987</height>
|
||||
<width>1259</width>
|
||||
<height>980</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -2007,14 +2007,14 @@
|
||||
<rect>
|
||||
<x>770</x>
|
||||
<y>0</y>
|
||||
<width>294</width>
|
||||
<width>295</width>
|
||||
<height>881</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>294</width>
|
||||
<height>617</height>
|
||||
<width>295</width>
|
||||
<height>624</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="features">
|
||||
@ -2689,13 +2689,13 @@
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>60</width>
|
||||
<width>65</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>60</width>
|
||||
<width>65</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -3700,8 +3700,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>263</width>
|
||||
<height>722</height>
|
||||
<width>128</width>
|
||||
<height>686</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
@ -5786,8 +5786,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>259</width>
|
||||
<height>652</height>
|
||||
<width>136</width>
|
||||
<height>58</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -5920,7 +5920,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>291</width>
|
||||
<height>851</height>
|
||||
<height>854</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -7027,8 +7027,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>432</width>
|
||||
<height>589</height>
|
||||
<width>442</width>
|
||||
<height>587</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
@ -344,7 +344,7 @@ void FractoriumEmberController<T>::SetEmberPrivate(const Ember<U>& ember, bool v
|
||||
dir.mkpath(".");
|
||||
|
||||
string filename = path.toStdString() + "/last.flame";
|
||||
writer.Save(filename.c_str(), m_Ember, 0, true, true, false, true, true);
|
||||
writer.Save(filename, m_Ember, 0, true, true, false, true, true);
|
||||
m_GLController->ResetMouseState();
|
||||
FillXforms();//Must do this first because the palette setup in FillParamTablesAndPalette() uses the xforms combo.
|
||||
FillParamTablesAndPalette();
|
||||
|
@ -100,6 +100,7 @@ public:
|
||||
virtual void SaveCurrentAsXml() { }
|
||||
virtual void SaveEntireFileAsXml() { }
|
||||
virtual uint SaveCurrentToOpenedFile(bool render = true) { return 0; }
|
||||
virtual void SaveCurrentFileOnShutdown() { }
|
||||
virtual void Undo() { }//Edit.
|
||||
virtual void Redo() { }
|
||||
virtual void CopyXml() { }
|
||||
@ -362,6 +363,7 @@ public:
|
||||
virtual void SaveCurrentAsXml() override;
|
||||
virtual void SaveEntireFileAsXml() override;
|
||||
virtual uint SaveCurrentToOpenedFile(bool render = true) override;
|
||||
virtual void SaveCurrentFileOnShutdown() override;
|
||||
virtual void Undo() override;
|
||||
virtual void Redo() override;
|
||||
virtual void CopyXml() override;
|
||||
|
@ -768,7 +768,7 @@ void FractoriumEmberController<T>::SequenceSaveButtonClicked()
|
||||
for (auto& ember : m_SequenceFile.m_Embers)
|
||||
ApplyXmlSavingTemplate(ember);
|
||||
|
||||
if (writer.Save(filename.toStdString().c_str(), m_SequenceFile.m_Embers, 0, true, true))
|
||||
if (writer.Save(filename.toStdString().c_str(), m_SequenceFile.m_Embers, 0, true, true, false, false, false))
|
||||
s->SaveFolder(fileInfo.canonicalPath());
|
||||
else
|
||||
m_Fractorium->ShowCritical("Save Failed", "Could not save sequence file, try saving to a different folder.");
|
||||
@ -800,7 +800,7 @@ void FractoriumEmberController<T>::SequenceOpenButtonClicked()
|
||||
{
|
||||
embers.clear();
|
||||
|
||||
if (parser.Parse(filename.toStdString().c_str(), embers) && !embers.empty())
|
||||
if (parser.Parse(filename.toStdString().c_str(), embers, true) && !embers.empty())
|
||||
{
|
||||
for (i = 0; i < embers.size(); i++)
|
||||
if (embers[i].m_Name == "" || embers[i].m_Name == "No name")//Ensure it has a name.
|
||||
|
@ -77,7 +77,7 @@ void FractoriumEmberController<T>::NewFlock(size_t count)
|
||||
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
m_SheepTools->Random(ember, filteredVariationsRef, static_cast<intmax_t>(QTIsaac<ISAAC_SIZE, ISAAC_INT>::LockedFrand<T>(-2, 2)), 0, MAX_CL_VARS);
|
||||
m_SheepTools->Random(ember, filteredVariationsRef, static_cast<intmax_t>(QTIsaac<ISAAC_SIZE, ISAAC_INT>::LockedFrand<T>(-2, 2)), 0, 8);
|
||||
ParamsToEmber(ember);
|
||||
ember.m_Index = i;
|
||||
ember.m_Name = m_EmberFile.m_Filename.toStdString() + "_" + ToString(i + 1ULL).toStdString();
|
||||
@ -114,6 +114,7 @@ void FractoriumEmberController<T>::NewEmptyFlameInCurrentFile()
|
||||
ParamsToEmber(ember);
|
||||
xform.m_Weight = T(0.25);
|
||||
xform.m_ColorX = m_Rand.Frand01<T>();
|
||||
xform.AddVariation(m_VariationList->GetVariationCopy(eVariationId::VAR_LINEAR));
|
||||
ember.AddXform(xform);
|
||||
ember.m_Palette = *m_PaletteList->GetRandomPalette();
|
||||
ember.m_Name = EmberFile<T>::DefaultEmberName(m_EmberFile.Size() + 1).toStdString();
|
||||
@ -136,7 +137,7 @@ void FractoriumEmberController<T>::NewRandomFlameInCurrentFile()
|
||||
{
|
||||
Ember<T> ember;
|
||||
StopAllPreviewRenderers();
|
||||
m_SheepTools->Random(ember, m_FilteredVariations, static_cast<int>(QTIsaac<ISAAC_SIZE, ISAAC_INT>::LockedFrand<T>(-2, 2)), 0, MAX_CL_VARS);
|
||||
m_SheepTools->Random(ember, m_FilteredVariations, static_cast<int>(QTIsaac<ISAAC_SIZE, ISAAC_INT>::LockedFrand<T>(-2, 2)), 0, 8);
|
||||
ParamsToEmber(ember);
|
||||
ember.m_Name = EmberFile<T>::DefaultEmberName(m_EmberFile.Size() + 1).toStdString();
|
||||
ember.m_Index = m_EmberFile.Size();
|
||||
@ -198,7 +199,7 @@ void FractoriumEmberController<T>::OpenAndPrepFiles(const QStringList& filenames
|
||||
{
|
||||
embers.clear();
|
||||
|
||||
if (parser.Parse(filename.toStdString().c_str(), embers) && !embers.empty())
|
||||
if (parser.Parse(filename.toStdString().c_str(), embers, true) && !embers.empty())
|
||||
{
|
||||
for (i = 0; i < embers.size(); i++)
|
||||
{
|
||||
@ -235,6 +236,12 @@ void FractoriumEmberController<T>::OpenAndPrepFiles(const QStringList& filenames
|
||||
}
|
||||
else if (emberFile.Size() > 0)//Ensure at least something was read.
|
||||
m_EmberFile = std::move(emberFile);//Move the temp to avoid creating dupes because we no longer need it.
|
||||
else if (!m_EmberFile.Size())
|
||||
{
|
||||
//Loading failed, so fill it with a dummy.
|
||||
Ember<T> ember;
|
||||
m_EmberFile.m_Embers.push_back(ember);
|
||||
}
|
||||
|
||||
//Resync indices and names.
|
||||
i = 0;
|
||||
@ -343,7 +350,7 @@ void FractoriumEmberController<T>::SaveEntireFileAsXml()
|
||||
for (auto& ember : emberFile.m_Embers)
|
||||
ApplyXmlSavingTemplate(ember);
|
||||
|
||||
if (writer.Save(filename.toStdString().c_str(), emberFile.m_Embers, 0, true, true))
|
||||
if (writer.Save(filename.toStdString().c_str(), emberFile.m_Embers, 0, true, true, false, false, false))
|
||||
{
|
||||
if (!s->SaveAutoUnique() || m_LastSaveAll == "")//Only save filename on first time through when doing auto unique names.
|
||||
m_LastSaveAll = filename;
|
||||
@ -357,6 +364,20 @@ void FractoriumEmberController<T>::SaveEntireFileAsXml()
|
||||
|
||||
void Fractorium::OnActionSaveEntireFileAsXml(bool checked) { m_Controller->SaveEntireFileAsXml(); }
|
||||
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::SaveCurrentFileOnShutdown()
|
||||
{
|
||||
EmberToXml<T> writer;
|
||||
auto path = GetDefaultUserPath();
|
||||
QDir dir(path);
|
||||
|
||||
if (!dir.exists())
|
||||
dir.mkpath(".");
|
||||
|
||||
string filename = path.toStdString() + "/lastonshutdown.flame";
|
||||
writer.Save(filename, m_EmberFile.m_Embers, 0, true, true, false, false, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show a file save dialog and save what is currently shown in the render window to disk as an image.
|
||||
/// </summary>
|
||||
@ -557,7 +578,7 @@ void FractoriumEmberController<T>::PasteXmlAppend()
|
||||
|
||||
b.clear();
|
||||
StopAllPreviewRenderers();
|
||||
parser.Parse(reinterpret_cast<byte*>(const_cast<char*>(s.c_str())), "", embers);
|
||||
parser.Parse(reinterpret_cast<byte*>(const_cast<char*>(s.c_str())), "", embers, true);
|
||||
errors = parser.ErrorReportString();
|
||||
|
||||
if (errors != "")
|
||||
@ -598,7 +619,8 @@ void FractoriumEmberController<T>::PasteXmlOver()
|
||||
size_t i = 0;
|
||||
string s, errors;
|
||||
XmlToEmber<T> parser;
|
||||
auto backupEmber = m_EmberFile.m_Embers.begin();
|
||||
list<Ember<T>> embers;
|
||||
auto backupEmber = *m_EmberFile.m_Embers.begin();
|
||||
auto codec = QTextCodec::codecForName("UTF-8");
|
||||
auto b = codec->fromUnicode(QApplication::clipboard()->text());
|
||||
s.reserve(b.size());
|
||||
@ -611,8 +633,7 @@ void FractoriumEmberController<T>::PasteXmlOver()
|
||||
|
||||
b.clear();
|
||||
StopAllPreviewRenderers();
|
||||
m_EmberFile.m_Embers.clear();//Will invalidate the pointers contained in the EmberTreeWidgetItems, UpdateLibraryTree() will resync.
|
||||
parser.Parse(reinterpret_cast<byte*>(const_cast<char*>(s.c_str())), "", m_EmberFile.m_Embers);
|
||||
parser.Parse(reinterpret_cast<byte*>(const_cast<char*>(s.c_str())), "", embers, true);
|
||||
errors = parser.ErrorReportString();
|
||||
|
||||
if (errors != "")
|
||||
@ -620,8 +641,10 @@ void FractoriumEmberController<T>::PasteXmlOver()
|
||||
m_Fractorium->ShowCritical("Paste Error", QString::fromStdString(errors));
|
||||
}
|
||||
|
||||
if (m_EmberFile.Size())
|
||||
if (embers.size())
|
||||
{
|
||||
m_EmberFile.m_Embers = std::move(embers);//Will invalidate the pointers contained in the EmberTreeWidgetItems, UpdateLibraryTree() will resync.
|
||||
|
||||
for (auto it : m_EmberFile.m_Embers)
|
||||
{
|
||||
it.m_Index = i++;
|
||||
@ -631,16 +654,11 @@ void FractoriumEmberController<T>::PasteXmlOver()
|
||||
if (it.m_Name == "" || it.m_Name == "No name")
|
||||
it.m_Name = ToString<qulonglong>(it.m_Index).toStdString();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
backupEmber->m_Index = 0;
|
||||
m_EmberFile.m_Embers.push_back(*backupEmber);
|
||||
}
|
||||
|
||||
m_EmberFile.MakeNamesUnique();
|
||||
FillLibraryTree();
|
||||
SetEmber(0, false);
|
||||
m_EmberFile.MakeNamesUnique();
|
||||
FillLibraryTree();
|
||||
SetEmber(0, false);
|
||||
}
|
||||
}
|
||||
|
||||
void Fractorium::OnActionPasteXmlOver(bool checked) { m_Controller->PasteXmlOver(); }
|
||||
@ -856,6 +874,7 @@ void FractoriumEmberController<T>::ClearFlame()
|
||||
if (auto xform = m_Ember.GetXform(0))
|
||||
{
|
||||
xform->Clear();
|
||||
xform->AddVariation(m_VariationList->GetVariationCopy(eVariationId::VAR_LINEAR));
|
||||
xform->ParentEmber(&m_Ember);
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ void Fractorium::InitParamsUI()
|
||||
//Filter.
|
||||
row = 0;
|
||||
table = ui.FilterTable;
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_SpatialFilterWidthSpin, spinHeight, 0.1, 2, 0.1, SIGNAL(valueChanged(double)), SLOT(OnSpatialFilterWidthChanged(double)), true, 1.0, 1.0, 0.1);
|
||||
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);
|
||||
m_SpatialFilterWidthSpin->DoubleClickLowVal(0.1);
|
||||
comboVals = SpatialFilterCreator<float>::FilterTypes();
|
||||
SetupCombo(table, this, row, 1, m_SpatialFilterTypeCombo, comboVals, SIGNAL(currentIndexChanged(const QString&)), SLOT(OnSpatialFilterTypeComboCurrentIndexChanged(const QString&)));
|
||||
@ -74,10 +74,11 @@ void Fractorium::InitParamsUI()
|
||||
//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, 15, 15);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_QualitySpin, spinHeight, 1, dmax, 50, SIGNAL(valueChanged(double)), SLOT(OnQualityChanged(double)), true, 10, 10, 10);
|
||||
SetupSpinner<SpinBox, int>( table, this, row, 1, m_SupersampleSpin, spinHeight, 1, 4, 1, SIGNAL(valueChanged(int)), SLOT(OnSupersampleChanged(int)), true, 1, 1, 1);
|
||||
SetupSpinner<SpinBox, int>( table, this, row, 1, m_FuseSpin, spinHeight, 1, 1000, 5, SIGNAL(valueChanged(int)), SLOT(OnFuseChanged(int)), true, 15, 15, 15);
|
||||
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, 1, 1);
|
||||
//Animation.
|
||||
row = 0;
|
||||
table = ui.AnimationTable;
|
||||
|
@ -97,7 +97,7 @@ void FractoriumEmberControllerBase::UpdateRender(eProcessAction action)
|
||||
void FractoriumEmberControllerBase::DeleteRenderer()
|
||||
{
|
||||
Shutdown();
|
||||
m_Renderer.reset();
|
||||
m_Renderer = make_unique<EmberNs::Renderer<float, float>>();
|
||||
|
||||
if (GLController())
|
||||
GLController()->ClearWindow();
|
||||
@ -299,6 +299,9 @@ bool FractoriumEmberController<T>::SyncSizes()
|
||||
template <typename T>
|
||||
bool FractoriumEmberController<T>::Render()
|
||||
{
|
||||
if (!m_Renderer.get())
|
||||
return false;
|
||||
|
||||
m_Rendering = true;
|
||||
bool success = true;
|
||||
auto gl = m_Fractorium->ui.GLDisplay;
|
||||
@ -567,7 +570,7 @@ bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, cons
|
||||
|
||||
if (m_RenderType == eRendererType::OPENCL_RENDERER)
|
||||
{
|
||||
auto val = 30 * m_Fractorium->m_Settings->Devices().size();
|
||||
auto val = m_Fractorium->m_Settings->OpenClQuality() * m_Fractorium->m_Settings->Devices().size();
|
||||
m_Fractorium->m_QualitySpin->DoubleClickZero(val);
|
||||
m_Fractorium->m_QualitySpin->DoubleClickNonZero(val);
|
||||
|
||||
@ -576,11 +579,12 @@ bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, cons
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Fractorium->m_QualitySpin->DoubleClickZero(10);
|
||||
m_Fractorium->m_QualitySpin->DoubleClickNonZero(10);
|
||||
auto quality = m_Fractorium->m_Settings->CpuQuality();
|
||||
m_Fractorium->m_QualitySpin->DoubleClickZero(quality);
|
||||
m_Fractorium->m_QualitySpin->DoubleClickNonZero(quality);
|
||||
|
||||
if (m_Fractorium->m_QualitySpin->value() > 10)
|
||||
m_Fractorium->m_QualitySpin->setValue(10);
|
||||
if (m_Fractorium->m_QualitySpin->value() > quality)
|
||||
m_Fractorium->m_QualitySpin->setValue(quality);
|
||||
}
|
||||
|
||||
m_Renderer->Callback(this);
|
||||
|
@ -57,6 +57,12 @@ void FractoriumSettings::EnsureDefaults()
|
||||
OpenCLSubBatch(std::max(1u, OpenCLSubBatch()));
|
||||
RandomCount(std::max(1u, RandomCount()));
|
||||
|
||||
if (CpuQuality() == 0)
|
||||
CpuQuality(10);
|
||||
|
||||
if (OpenClQuality() == 0)
|
||||
OpenClQuality(30);
|
||||
|
||||
if (FinalScale() > int(eScaleType::SCALE_HEIGHT))
|
||||
FinalScale(0);
|
||||
|
||||
@ -72,7 +78,11 @@ void FractoriumSettings::EnsureDefaults()
|
||||
if (SaveImageExt() == "")
|
||||
SaveImageExt(".png");
|
||||
|
||||
if (FinalExt() != "jpg" && FinalExt() != "png")
|
||||
if (FinalExt() != "jpg" && FinalExt() != "png" && FinalExt() != "exr"
|
||||
#ifdef _WIN32
|
||||
&& FinalExt() != "bmp"
|
||||
#endif
|
||||
)
|
||||
FinalExt("png");
|
||||
|
||||
auto s = SaveFolder();
|
||||
@ -148,6 +158,15 @@ void FractoriumSettings::OpenCLSubBatch(uint i) { setValue(OPENCLSUBBATCH,
|
||||
uint FractoriumSettings::RandomCount() { return value(RANDOMCOUNT).toUInt(); }
|
||||
void FractoriumSettings::RandomCount(uint i) { setValue(RANDOMCOUNT, i); }
|
||||
|
||||
uint FractoriumSettings::CpuQuality() { return value(CPU_QUALITY).toUInt(); }
|
||||
void FractoriumSettings::CpuQuality(uint i) { setValue(CPU_QUALITY, i); }
|
||||
|
||||
uint FractoriumSettings::OpenClQuality() { return value(OPENCL_QUALITY).toUInt(); }
|
||||
void FractoriumSettings::OpenClQuality(uint i) { setValue(OPENCL_QUALITY, i); }
|
||||
|
||||
bool FractoriumSettings::LoadLast() { return value(LOAD_LAST).toBool(); }
|
||||
void FractoriumSettings::LoadLast(bool b) { setValue(LOAD_LAST, b); }
|
||||
|
||||
/// <summary>
|
||||
/// Sequence generation settings.
|
||||
/// </summary>
|
||||
|
@ -24,6 +24,9 @@
|
||||
#define CPUSUBBATCH "render/cpusubbatch"
|
||||
#define OPENCLSUBBATCH "render/openclsubbatch"
|
||||
#define RANDOMCOUNT "render/randomcount"
|
||||
#define CPU_QUALITY "render/cpuquality"
|
||||
#define OPENCL_QUALITY "render/openclquality"
|
||||
#define LOAD_LAST "render/loadlastonstart"
|
||||
|
||||
#define STAGGER "sequence/stagger"
|
||||
#define STAGGERMAX "sequence/staggermax"
|
||||
@ -153,6 +156,15 @@ public:
|
||||
uint RandomCount();
|
||||
void RandomCount(uint i);
|
||||
|
||||
uint CpuQuality();
|
||||
void CpuQuality(uint i);
|
||||
|
||||
uint OpenClQuality();
|
||||
void OpenClQuality(uint i);
|
||||
|
||||
bool LoadLast();
|
||||
void LoadLast(bool b);
|
||||
|
||||
double Stagger();
|
||||
void Stagger(double i);
|
||||
|
||||
|
@ -32,13 +32,13 @@ void Fractorium::InitXaosUI()
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::FillXaos()
|
||||
{
|
||||
for (int i = 0, count = int(XformCount()); i < count; i++)
|
||||
for (int i = 0, count = int(XformCount()); i < count; i++)//Column.
|
||||
{
|
||||
if (auto xform = m_Ember.GetXform(i))
|
||||
{
|
||||
for (int j = 0; j < count; j++)
|
||||
for (int j = 0; j < count; j++)//Row.
|
||||
{
|
||||
QModelIndex index = m_Fractorium->m_XaosTableModel->index(i, j, QModelIndex());
|
||||
QModelIndex index = m_Fractorium->m_XaosTableModel->index(j, i, QModelIndex());//j and i are intentionally swapped here.
|
||||
m_Fractorium->m_XaosTableModel->setData(index, xform->Xaos(j));
|
||||
}
|
||||
}
|
||||
@ -57,7 +57,9 @@ void FractoriumEmberController<T>::FillXaos()
|
||||
/// xaos value.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="sender">The DoubleSpinBox that triggered this event</param>
|
||||
/// <param name="x">The index of the xform whose xaos value was changed (column)</param>
|
||||
/// <param name="y">The index of the to value that was changed for the xform (row)</param>
|
||||
/// <param name="val">The changed value of the xaos element</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::XaosChanged(int x, int y, double val)
|
||||
{
|
||||
@ -73,13 +75,13 @@ void Fractorium::OnXaosChanged(double d)
|
||||
if (auto senderSpinBox = qobject_cast<DoubleSpinBox*>(sender()))
|
||||
{
|
||||
auto p = senderSpinBox->property("tableindex").toPoint();
|
||||
m_Controller->XaosChanged(p.x(), p.y(), d);
|
||||
m_Controller->XaosChanged(p.y(), p.x(), d);//Intentionally switched, column is the from xform, row is the to xform.
|
||||
}
|
||||
}
|
||||
|
||||
void Fractorium::OnXaosTableModelDataChanged(const QModelIndex& indexA, const QModelIndex& indexB)
|
||||
{
|
||||
m_Controller->XaosChanged(indexA.row(), indexA.column(), indexA.data().toDouble());
|
||||
m_Controller->XaosChanged(indexA.column(), indexA.row(), indexA.data().toDouble());//Intentionally switched, column is the from xform, row is the to xform.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -190,5 +192,5 @@ void Fractorium::OnXaosColDoubleClicked(int logicalIndex)
|
||||
template class FractoriumEmberController<float>;
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
template class FractoriumEmberController<double>;
|
||||
template class FractoriumEmberController<double>;
|
||||
#endif
|
||||
|
@ -104,6 +104,7 @@ void FractoriumEmberController<T>::AddXform()
|
||||
Xform<T> newXform;
|
||||
newXform.m_Weight = 0.25;
|
||||
newXform.m_ColorX = m_Rand.Frand01<T>();
|
||||
newXform.AddVariation(m_VariationList->GetVariationCopy(eVariationId::VAR_LINEAR));
|
||||
m_Ember.AddXform(newXform);
|
||||
int index = int(m_Ember.TotalXformCount(forceFinal) - (forceFinal ? 2 : 1));//Set index to the last item before final.
|
||||
FillXforms(index);
|
||||
@ -115,7 +116,12 @@ void Fractorium::OnAddXformButtonClicked(bool checked) { m_Controller->AddXform(
|
||||
/// <summary>
|
||||
/// Add a new linked xform in the current ember and set it as the current xform.
|
||||
/// Linked means:
|
||||
///
|
||||
/// Add an xform whose xaos values are:
|
||||
/// From: All xaos values from the current xform are zero when going to any xform but the new one added, which is 1.
|
||||
/// To: The xaos value coming from the current xform is 1 and the xaos values from all other xforms are 0, when going to the newly added xform.
|
||||
/// Take different action when a single xform is selected vs. multiple.
|
||||
/// Single: Copy current xform's xaos values to the new one.
|
||||
/// Multiple: Set new xform's xaos values to 1, and except the last entry which is 0.
|
||||
/// Called when the add xform button is clicked.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
@ -123,40 +129,71 @@ void Fractorium::OnAddXformButtonClicked(bool checked) { m_Controller->AddXform(
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::AddLinkedXform()
|
||||
{
|
||||
bool hasAdded = false;
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
auto selCount = m_Fractorium->SelectedXformCount(false);
|
||||
|
||||
if (!selCount)//If none explicitly selected, use current.
|
||||
selCount = 1;
|
||||
|
||||
Ember<T> ember = m_Ember;
|
||||
m_Ember.Reserve(m_Ember.XformCount() + 1);//Doing this ahead of time ensures pointers remain valid.
|
||||
auto iterCount = 0;
|
||||
UpdateXform([&](Xform<T>* xform)
|
||||
{
|
||||
size_t i, count = m_Ember.XformCount();
|
||||
Xform<T> newXform;
|
||||
newXform.m_Weight = 0.5;
|
||||
newXform.m_Opacity = 1;
|
||||
newXform.m_ColorSpeed = 1;
|
||||
newXform.m_ColorX = xform->m_ColorX;
|
||||
//newXform.m_ColorY = xform->m_ColorY;
|
||||
|
||||
//Set all of the new xform's xaos values to the selected xform's xaos values,
|
||||
//then set the selected xform's xaos values to 0.
|
||||
for (i = 0; i < count; i++)
|
||||
//Covers very strange case where final is selected, but initially not considered because final is excluded,
|
||||
//but after adding the new xform, it thinks its selected index is non-final.
|
||||
if (iterCount < selCount)
|
||||
{
|
||||
newXform.SetXaos(i, xform->Xaos(i));
|
||||
xform->SetXaos(i, 0);
|
||||
size_t i, count = m_Ember.XformCount();
|
||||
|
||||
if (!hasAdded)
|
||||
{
|
||||
Xform<T> newXform;
|
||||
newXform.m_Weight = 0.5;
|
||||
newXform.m_Opacity = xform->m_Opacity;
|
||||
newXform.m_ColorSpeed = 0;
|
||||
newXform.m_ColorX = 0;
|
||||
//newXform.m_ColorY = xform->m_ColorY;
|
||||
newXform.AddVariation(m_VariationList->GetVariationCopy(eVariationId::VAR_LINEAR));
|
||||
|
||||
//Set all of the new xform's xaos values to the selected xform's xaos values,
|
||||
//then set the selected xform's xaos values to 0.
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (selCount == 1)
|
||||
newXform.SetXaos(i, xform->Xaos(i));
|
||||
else
|
||||
newXform.SetXaos(i, 1);
|
||||
}
|
||||
|
||||
//Add the new xform and update the total count.
|
||||
m_Ember.AddXform(newXform);
|
||||
count = m_Ember.XformCount();
|
||||
|
||||
//Set the xaos for all xforms pointing to the new one to zero.
|
||||
//Will set the last element of all linking and non-linking xforms, including the one we just added.
|
||||
//Linking xforms will have their last xaos element set to 1 below.
|
||||
for (i = 0; i < count; i++)
|
||||
if (auto xf = m_Ember.GetXform(i))
|
||||
xf->SetXaos(count - 1, 0);
|
||||
|
||||
hasAdded = true;
|
||||
}
|
||||
|
||||
//Linking xform, so set all xaos elements to 0, except the last.
|
||||
for (i = 0; i < count - 1; i++)
|
||||
xform->SetXaos(i, 0);
|
||||
|
||||
xform->SetXaos(count - 1, 1);//Set the xaos value for the linking xform pointing to the new one to one.
|
||||
xform->m_Opacity = 0;//Clear the opacity of the all linking xform.
|
||||
iterCount++;
|
||||
}
|
||||
|
||||
//Add the new xform and update the total count.
|
||||
m_Ember.AddXform(newXform);
|
||||
count = m_Ember.XformCount();
|
||||
|
||||
//Set the xaos for all xforms pointing to the new one to zero.
|
||||
for (i = 0; i < count; i++)
|
||||
if (auto xf = m_Ember.GetXform(i))
|
||||
xf->SetXaos(count - 1, 0);
|
||||
|
||||
xform->SetXaos(count - 1, 1);//Set the xaos value for the previous xform pointing to the new one to one.
|
||||
xform->m_Opacity = 0;//Clear the opacity of the previous xform.
|
||||
int index = int(m_Ember.TotalXformCount(forceFinal) - (forceFinal ? 2 : 1));//Set index to the last item before final.
|
||||
FillXforms(index);
|
||||
FillXaos();
|
||||
}, eXformUpdate::UPDATE_CURRENT);
|
||||
}, eXformUpdate::UPDATE_SELECTED_EXCEPT_FINAL);
|
||||
//Now update the GUI.
|
||||
int index = int(m_Ember.TotalXformCount(forceFinal) - (forceFinal ? 2 : 1));//Set index to the last item before final.
|
||||
FillXforms(index);
|
||||
FillXaos();
|
||||
}
|
||||
|
||||
void Fractorium::OnAddLinkedXformButtonClicked(bool checked) { m_Controller->AddLinkedXform(); }
|
||||
|
@ -38,6 +38,25 @@ bool Fractorium::IsXformSelected(size_t i)
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the number of xforms selected, optionally counting the final xform.
|
||||
/// </summary>
|
||||
/// <param name="includeFinal">Whether to include the final in the count if selected.</param>
|
||||
/// <returns>The caption string</returns>
|
||||
int Fractorium::SelectedXformCount(bool includeFinal)
|
||||
{
|
||||
int selCount = 0;
|
||||
ForEachXformCheckbox([&](int index, QCheckBox * cb, bool isFinal)
|
||||
{
|
||||
if (cb->isChecked())
|
||||
{
|
||||
if (!isFinal || includeFinal)
|
||||
selCount++;
|
||||
}
|
||||
});
|
||||
return selCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear all of the dynamically created xform checkboxes.
|
||||
/// </summary>
|
||||
@ -81,7 +100,7 @@ QString FractoriumEmberController<T>::MakeXformCaption(size_t i)
|
||||
/// <summary>
|
||||
/// Function to perform the specified operation on every dynamically created xform selection checkbox.
|
||||
/// </summary>
|
||||
/// <param name="func">The operation to perform</param>
|
||||
/// <param name="func">The operation to perform which is a function taking the index of the xform, its checkbox, and a bool specifying whether it's final.</param>
|
||||
void Fractorium::ForEachXformCheckbox(std::function<void(int, QCheckBox*, bool)> func)
|
||||
{
|
||||
int i = 0;
|
||||
|
@ -32,13 +32,36 @@ void GLWidget::InitGL()
|
||||
{
|
||||
if (!m_Init)
|
||||
{
|
||||
int w = m_Fractorium->ui.GLParentScrollArea->width();
|
||||
int h = m_Fractorium->ui.GLParentScrollArea->height();
|
||||
int w = std::ceil(m_Fractorium->ui.GLParentScrollArea->width() * devicePixelRatioF());
|
||||
int h = std::ceil(m_Fractorium->ui.GLParentScrollArea->height() * devicePixelRatioF());
|
||||
SetDimensions(w, h);
|
||||
m_Fractorium->m_WidthSpin->setValue(w);
|
||||
m_Fractorium->m_HeightSpin->setValue(h);
|
||||
//Start with a flock of random embers. Can't do this until now because the window wasn't maximized yet, so the sizes would have been off.
|
||||
m_Fractorium->OnActionNewFlock(false);
|
||||
//Start with either a flock of random embers, or the last flame from the previous run.
|
||||
//Can't do this until now because the window wasn't maximized yet, so the sizes would have been off.
|
||||
bool b = m_Fractorium->m_Settings->LoadLast();
|
||||
|
||||
if (b)
|
||||
{
|
||||
auto path = GetDefaultUserPath();
|
||||
QDir dir(path);
|
||||
QString filename = path + "/lastonshutdown.flame";
|
||||
|
||||
if (dir.exists(filename))
|
||||
{
|
||||
QStringList ql;
|
||||
ql << filename;
|
||||
m_Fractorium->m_Controller->OpenAndPrepFiles(ql, false);
|
||||
}
|
||||
else
|
||||
b = false;
|
||||
}
|
||||
|
||||
if (!b)
|
||||
{
|
||||
m_Fractorium->OnActionNewFlock(false);
|
||||
m_Fractorium->m_WidthSpin->setValue(w);
|
||||
m_Fractorium->m_HeightSpin->setValue(h);
|
||||
}
|
||||
|
||||
m_Fractorium->m_Controller->DelayedStartRenderTimer();
|
||||
m_Init = true;
|
||||
}
|
||||
@ -61,9 +84,14 @@ void GLWidget::DrawQuad()
|
||||
if (m_OutputTexID != 0 && finalImage && !finalImage->empty())
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, m_OutputTexID);//The texture to draw to.
|
||||
auto scaledW = std::ceil(width() * devicePixelRatioF());
|
||||
auto scaledH = std::ceil(height() * devicePixelRatioF());
|
||||
|
||||
//Only draw if the dimensions match exactly.
|
||||
if (m_TexWidth == width() && m_TexHeight == height() && ((m_TexWidth * m_TexHeight) == GLint(finalImage->size())))
|
||||
if (m_TexWidth == m_Fractorium->m_Controller->FinalRasW() &&
|
||||
m_TexHeight == m_Fractorium->m_Controller->FinalRasH() &&
|
||||
((m_TexWidth * m_TexHeight) == GLint(finalImage->size())))
|
||||
//if (m_TexWidth == scaledW && m_TexHeight == scaledH && ((m_TexWidth * m_TexHeight) == GLint(finalImage->size())))
|
||||
{
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
@ -337,16 +365,16 @@ void GLEmberController<T>::DrawAffines(bool pre, bool post)
|
||||
|
||||
if (dragging)//Draw large yellow dot on select or drag.
|
||||
{
|
||||
m_GL->glPointSize(6.0f);
|
||||
m_GL->glPointSize(6.0f * m_GL->devicePixelRatioF());
|
||||
m_GL->glBegin(GL_POINTS);
|
||||
m_GL->glColor4f(1.0f, 1.0f, 0.5f, 1.0f);
|
||||
m_GL->glVertex2f(m_DragHandlePos.x, m_DragHandlePos.y);
|
||||
m_GL->glEnd();
|
||||
m_GL->glPointSize(1.0f);//Restore point size.
|
||||
m_GL->glPointSize(1.0f * m_GL->devicePixelRatioF());//Restore point size.
|
||||
}
|
||||
else if (m_DragState == eDragState::DragSelect)
|
||||
{
|
||||
m_GL->glLineWidth(2.0f);
|
||||
m_GL->glLineWidth(2.0f * m_GL->devicePixelRatioF());
|
||||
m_GL->glBegin(GL_LINES);
|
||||
m_GL->glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
m_GL->glVertex2f(m_MouseDownWorldPos.x, m_MouseDownWorldPos.y);//UL->UR
|
||||
@ -358,16 +386,16 @@ void GLEmberController<T>::DrawAffines(bool pre, bool post)
|
||||
m_GL->glVertex2f(m_MouseWorldPos.x, m_MouseDownWorldPos.y);//UR->LR
|
||||
m_GL->glVertex2f(m_MouseWorldPos.x, m_MouseWorldPos.y);
|
||||
m_GL->glEnd();
|
||||
m_GL->glLineWidth(1.0f);
|
||||
m_GL->glLineWidth(1.0f * m_GL->devicePixelRatioF());
|
||||
}
|
||||
else if (m_HoverType != eHoverType::HoverNone && m_HoverXform == m_SelectedXform)//Draw large turquoise dot on hover if they are hovering over the selected xform.
|
||||
{
|
||||
m_GL->glPointSize(6.0f);
|
||||
m_GL->glPointSize(6.0f * m_GL->devicePixelRatioF());
|
||||
m_GL->glBegin(GL_POINTS);
|
||||
m_GL->glColor4f(0.5f, 1.0f, 1.0f, 1.0f);
|
||||
m_GL->glVertex2f(m_HoverHandlePos.x, m_HoverHandlePos.y);
|
||||
m_GL->glEnd();
|
||||
m_GL->glPointSize(1.0f);
|
||||
m_GL->glPointSize(1.0f * m_GL->devicePixelRatioF());
|
||||
}
|
||||
}
|
||||
|
||||
@ -435,7 +463,7 @@ void GLWidget::keyReleaseEvent(QKeyEvent* e)
|
||||
template <typename T>
|
||||
void GLEmberController<T>::MousePress(QMouseEvent* e)
|
||||
{
|
||||
v3T mouseFlipped(e->x() * m_GL->devicePixelRatio(), m_Viewport[3] - e->y() * m_GL->devicePixelRatio(), 0);//Must flip y because in OpenGL, 0,0 is bottom left, but in windows, it's top left.
|
||||
v3T mouseFlipped(e->x() * m_GL->devicePixelRatioF(), m_Viewport[3] - e->y() * m_GL->devicePixelRatioF(), 0);//Must flip y because in OpenGL, 0,0 is bottom left, but in windows, it's top left.
|
||||
auto ember = m_FractoriumEmberController->CurrentEmber();
|
||||
auto renderer = m_FractoriumEmberController->Renderer();
|
||||
|
||||
@ -443,7 +471,7 @@ void GLEmberController<T>::MousePress(QMouseEvent* e)
|
||||
if (!renderer)
|
||||
return;
|
||||
|
||||
m_MouseDownPos = glm::ivec2(e->x() * m_GL->devicePixelRatio(), e->y() * m_GL->devicePixelRatio());//Capture the raster coordinates of where the mouse was clicked.
|
||||
m_MouseDownPos = glm::ivec2(e->x() * m_GL->devicePixelRatioF(), e->y() * m_GL->devicePixelRatioF());//Capture the raster coordinates of where the mouse was clicked.
|
||||
m_MouseWorldPos = WindowToWorld(mouseFlipped, false);//Capture the world cartesian coordinates of where the mouse is.
|
||||
m_BoundsDown.w = renderer->LowerLeftX(false);//Need to capture these because they'll be changing if scaling.
|
||||
m_BoundsDown.x = renderer->LowerLeftY(false);
|
||||
@ -530,7 +558,7 @@ void GLWidget::mousePressEvent(QMouseEvent* e)
|
||||
template <typename T>
|
||||
void GLEmberController<T>::MouseRelease(QMouseEvent* e)
|
||||
{
|
||||
v3T mouseFlipped(e->x() * m_GL->devicePixelRatio(), m_Viewport[3] - e->y() * m_GL->devicePixelRatio(), 0);//Must flip y because in OpenGL, 0,0 is bottom left, but in windows, it's top left.
|
||||
v3T mouseFlipped(e->x() * m_GL->devicePixelRatioF(), m_Viewport[3] - e->y() * m_GL->devicePixelRatioF(), 0);//Must flip y because in OpenGL, 0,0 is bottom left, but in windows, it's top left.
|
||||
m_MouseWorldPos = WindowToWorld(mouseFlipped, false);
|
||||
|
||||
if (m_DragState == eDragState::DragDragging && (e->button() & Qt::LeftButton))
|
||||
@ -567,8 +595,8 @@ template <typename T>
|
||||
void GLEmberController<T>::MouseMove(QMouseEvent* e)
|
||||
{
|
||||
bool draw = true;
|
||||
glm::ivec2 mouse(e->x() * m_GL->devicePixelRatio(), e->y() * m_GL->devicePixelRatio());
|
||||
v3T mouseFlipped(e->x() * m_GL->devicePixelRatio(), m_Viewport[3] - e->y() * m_GL->devicePixelRatio(), 0);//Must flip y because in OpenGL, 0,0 is bottom left, but in windows, it's top left.
|
||||
glm::ivec2 mouse(e->x() * m_GL->devicePixelRatioF(), e->y() * m_GL->devicePixelRatioF());
|
||||
v3T mouseFlipped(e->x() * m_GL->devicePixelRatioF(), m_Viewport[3] - e->y() * m_GL->devicePixelRatioF(), 0);//Must flip y because in OpenGL, 0,0 is bottom left, but in windows, it's top left.
|
||||
auto ember = m_FractoriumEmberController->CurrentEmber();
|
||||
|
||||
//First check to see if the mouse actually moved.
|
||||
@ -580,7 +608,7 @@ void GLEmberController<T>::MouseMove(QMouseEvent* e)
|
||||
|
||||
//Update status bar on main window, regardless of whether anything is being dragged.
|
||||
if (m_Fractorium->m_Controller->RenderTimerRunning())
|
||||
m_Fractorium->SetCoordinateStatus(e->x() * m_GL->devicePixelRatio(), e->y() * m_GL->devicePixelRatio(), m_MouseWorldPos.x, m_MouseWorldPos.y);
|
||||
m_Fractorium->SetCoordinateStatus(e->x() * m_GL->devicePixelRatioF(), e->y() * m_GL->devicePixelRatioF(), m_MouseWorldPos.x, m_MouseWorldPos.y);
|
||||
|
||||
if (m_SelectedXform && m_DragState == eDragState::DragDragging)//Dragging and affine.
|
||||
{
|
||||
@ -723,7 +751,9 @@ void GLWidget::wheelEvent(QWheelEvent* e)
|
||||
/// <param name="h">Height in pixels</param>
|
||||
void GLWidget::SetDimensions(int w, int h)
|
||||
{
|
||||
setFixedSize(w, h);
|
||||
auto downscaledW = std::ceil(w / devicePixelRatioF());
|
||||
auto downscaledH = std::ceil(h / devicePixelRatioF());
|
||||
setFixedSize(downscaledW, downscaledH);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -736,13 +766,18 @@ void GLWidget::SetDimensions(int w, int h)
|
||||
bool GLWidget::Allocate(bool force)
|
||||
{
|
||||
bool alloc = false;
|
||||
bool doResize = force || m_TexWidth != width() || m_TexHeight != height();
|
||||
//auto scaledW = std::ceil(width() * devicePixelRatioF());
|
||||
auto w = m_Fractorium->m_Controller->FinalRasW();
|
||||
auto h = m_Fractorium->m_Controller->FinalRasH();
|
||||
bool doResize = force || m_TexWidth != w || m_TexHeight != h;
|
||||
bool doIt = doResize || m_OutputTexID == 0;
|
||||
|
||||
if (doIt)
|
||||
{
|
||||
m_TexWidth = width();
|
||||
m_TexHeight = height();
|
||||
//m_TexWidth = scaledW;
|
||||
//m_TexHeight = scaledH;
|
||||
m_TexWidth = GLint(w);
|
||||
m_TexHeight = GLint(h);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
|
||||
@ -811,12 +846,12 @@ void GLWidget::SetViewport()
|
||||
template <typename T>
|
||||
bool GLEmberController<T>::SizesMatch()
|
||||
{
|
||||
//auto scaledW = std::ceil(m_GL->width() * m_GL->devicePixelRatioF());
|
||||
//auto scaledH = std::ceil(m_GL->height() * m_GL->devicePixelRatioF());
|
||||
auto ember = m_FractoriumEmberController->CurrentEmber();
|
||||
return (ember &&
|
||||
ember->m_FinalRasW == m_GL->width() &&
|
||||
ember->m_FinalRasH == m_GL->height() &&
|
||||
m_GL->width() == m_GL->m_TexWidth &&
|
||||
m_GL->height() == m_GL->m_TexHeight &&
|
||||
ember->m_FinalRasW == m_GL->m_TexWidth &&
|
||||
ember->m_FinalRasH == m_GL->m_TexHeight &&
|
||||
m_GL->m_TexWidth == m_GL->m_ViewWidth &&
|
||||
m_GL->m_TexHeight == m_GL->m_ViewHeight);
|
||||
}
|
||||
@ -826,7 +861,7 @@ bool GLEmberController<T>::SizesMatch()
|
||||
/// </summary>
|
||||
void GLWidget::DrawUnitSquare()
|
||||
{
|
||||
glLineWidth(1.0f);
|
||||
glLineWidth(1.0f * devicePixelRatioF());
|
||||
glBegin(GL_LINES);
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 0.25f);
|
||||
glVertex2f(-1, -1);
|
||||
@ -868,7 +903,7 @@ void GLEmberController<T>::DrawGrid()
|
||||
m_GL->glPushMatrix();
|
||||
m_GL->glLoadIdentity();
|
||||
MultMatrix(mat);
|
||||
m_GL->glLineWidth(1.0f);
|
||||
m_GL->glLineWidth(1.0f * m_GL->devicePixelRatioF());
|
||||
m_GL->glBegin(GL_LINES);
|
||||
m_GL->glColor4f(0.5f, 0.5f, 0.5f, alpha);
|
||||
|
||||
@ -924,24 +959,24 @@ void GLEmberController<T>::DrawAffine(Xform<T>* xform, bool pre, bool selected)
|
||||
m_GL->glPushMatrix();
|
||||
m_GL->glLoadIdentity();
|
||||
MultMatrix(mat);
|
||||
m_GL->glLineWidth(3.0f);//One 3px wide, colored black, except green on x axis for post affine.
|
||||
m_GL->glLineWidth(3.0f * m_GL->devicePixelRatioF());//One 3px wide, colored black, except green on x axis for post affine.
|
||||
m_GL->DrawAffineHelper(index, selected, pre, final, true);
|
||||
m_GL->glLineWidth(1.0f);//Again 1px wide, colored white, to give a white middle with black outline effect.
|
||||
m_GL->glLineWidth(1.0f * m_GL->devicePixelRatioF());//Again 1px wide, colored white, to give a white middle with black outline effect.
|
||||
m_GL->DrawAffineHelper(index, selected, pre, final, false);
|
||||
m_GL->glPointSize(5.0f);//Three black points, one in the center and two on the circle. Drawn big 5px first to give a black outline.
|
||||
m_GL->glPointSize(5.0f * m_GL->devicePixelRatioF());//Three black points, one in the center and two on the circle. Drawn big 5px first to give a black outline.
|
||||
m_GL->glBegin(GL_POINTS);
|
||||
m_GL->glColor4f(0.0f, 0.0f, 0.0f, selected ? 1.0f : 0.5f);
|
||||
m_GL->glVertex2f(0.0f, 0.0f);
|
||||
m_GL->glVertex2f(1.0f, 0.0f);
|
||||
m_GL->glVertex2f(0.0f, 1.0f);
|
||||
m_GL->glEnd();
|
||||
m_GL->glLineWidth(2.0f);//Draw lines again for y axis only, without drawing the circle, using the color of the selected xform.
|
||||
m_GL->glLineWidth(2.0f * m_GL->devicePixelRatioF());//Draw lines again for y axis only, without drawing the circle, using the color of the selected xform.
|
||||
m_GL->glBegin(GL_LINES);
|
||||
m_GL->glColor4f(color.r, color.g, color.b, 1.0f);
|
||||
m_GL->glVertex2f(0.0f, 0.0f);
|
||||
m_GL->glVertex2f(0.0f, 1.0f);
|
||||
m_GL->glEnd();
|
||||
m_GL->glPointSize(3.0f);//Draw smaller white points, to give a black outline effect.
|
||||
m_GL->glPointSize(3.0f * m_GL->devicePixelRatioF());//Draw smaller white points, to give a black outline effect.
|
||||
m_GL->glBegin(GL_POINTS);
|
||||
m_GL->glColor4f(1.0f, 1.0f, 1.0f, selected ? 1.0f : 0.5f);
|
||||
m_GL->glVertex2f(0.0f, 0.0f);
|
||||
|
@ -11,6 +11,7 @@
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int rv = -1;
|
||||
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
QApplication a(argc, argv);
|
||||
#ifdef TEST_CL
|
||||
QMessageBox::critical(QApplication::desktop(), "Error", "Fractorium cannot be run in test mode, undefine TEST_CL first.");
|
||||
|
@ -46,6 +46,7 @@ FractoriumOptionsDialog::FractoriumOptionsDialog(QWidget* p, Qt::WindowFlags f)
|
||||
ui.OpenCLCheckBox->setChecked(false);
|
||||
ui.OpenCLCheckBox->setEnabled(false);
|
||||
ui.OpenCLSubBatchSpin->setEnabled(false);
|
||||
ui.OpenCLQualitySpin->setEnabled(false);
|
||||
ui.OpenCLFilteringDERadioButton->setEnabled(false);
|
||||
ui.OpenCLFilteringLogRadioButton->setEnabled(false);
|
||||
ui.InteraciveGpuFilteringGroupBox->setEnabled(false);
|
||||
@ -69,8 +70,11 @@ bool FractoriumOptionsDialog::ShowAllXforms() { return ui.ShowAllXformsCheckBox-
|
||||
bool FractoriumOptionsDialog::ToggleType() { return ui.ToggleTypeCheckBox->isChecked(); }
|
||||
bool FractoriumOptionsDialog::Png16Bit() { return ui.Png16BitCheckBox->isChecked(); }
|
||||
bool FractoriumOptionsDialog::AutoUnique() { return ui.AutoUniqueCheckBox->isChecked(); }
|
||||
bool FractoriumOptionsDialog::LoadLast() { return ui.LoadLastOnStartCheckBox->isChecked(); }
|
||||
uint FractoriumOptionsDialog::ThreadCount() { return ui.ThreadCountSpin->value(); }
|
||||
uint FractoriumOptionsDialog::RandomCount() { return ui.RandomCountSpin->value(); }
|
||||
uint FractoriumOptionsDialog::CpuQuality() { return ui.CpuQualitySpin->value(); }
|
||||
uint FractoriumOptionsDialog::OpenClQuality() { return ui.OpenCLQualitySpin->value(); }
|
||||
|
||||
/// <summary>
|
||||
/// The check state of one of the OpenCL devices was changed.
|
||||
@ -122,6 +126,8 @@ void FractoriumOptionsDialog::OnOpenCLCheckBoxStateChanged(int state)
|
||||
ui.ThreadCountSpin->setEnabled(!checked);
|
||||
ui.CpuSubBatchSpin->setEnabled(!checked);
|
||||
ui.OpenCLSubBatchSpin->setEnabled(checked);
|
||||
ui.OpenCLQualitySpin->setEnabled(checked);
|
||||
ui.CpuQualitySpin->setEnabled(!checked);
|
||||
ui.CpuFilteringDERadioButton->setEnabled(!checked);
|
||||
ui.CpuFilteringLogRadioButton->setEnabled(!checked);
|
||||
ui.OpenCLFilteringDERadioButton->setEnabled(checked);
|
||||
@ -178,6 +184,9 @@ void FractoriumOptionsDialog::GuiToData()
|
||||
m_Settings->Png16Bit(Png16Bit());
|
||||
m_Settings->ThreadCount(ThreadCount());
|
||||
m_Settings->RandomCount(RandomCount());
|
||||
m_Settings->LoadLast(LoadLast());
|
||||
m_Settings->CpuQuality(CpuQuality());
|
||||
m_Settings->OpenClQuality(OpenClQuality());
|
||||
m_Settings->CpuSubBatch(ui.CpuSubBatchSpin->value());
|
||||
m_Settings->OpenCLSubBatch(ui.OpenCLSubBatchSpin->value());
|
||||
m_Settings->CpuDEFilter(ui.CpuFilteringDERadioButton->isChecked());
|
||||
@ -212,6 +221,9 @@ void FractoriumOptionsDialog::DataToGui()
|
||||
ui.Png16BitCheckBox->setChecked(m_Settings->Png16Bit());
|
||||
ui.ThreadCountSpin->setValue(m_Settings->ThreadCount());
|
||||
ui.RandomCountSpin->setValue(m_Settings->RandomCount());
|
||||
ui.LoadLastOnStartCheckBox->setChecked(m_Settings->LoadLast());
|
||||
ui.CpuQualitySpin->setValue(m_Settings->CpuQuality());
|
||||
ui.OpenCLQualitySpin->setValue(m_Settings->OpenClQuality());
|
||||
ui.CpuSubBatchSpin->setValue(m_Settings->CpuSubBatch());
|
||||
ui.OpenCLSubBatchSpin->setValue(m_Settings->OpenCLSubBatch());
|
||||
SettingsToDeviceTable(ui.DeviceTable, devices);
|
||||
|
@ -47,8 +47,11 @@ private:
|
||||
bool ToggleType();
|
||||
bool Png16Bit();
|
||||
bool AutoUnique();
|
||||
bool LoadLast();
|
||||
uint ThreadCount();
|
||||
uint RandomCount();
|
||||
uint CpuQuality();
|
||||
uint OpenClQuality();
|
||||
void DataToGui();
|
||||
void GuiToData();
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>427</width>
|
||||
<height>487</height>
|
||||
<height>475</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -169,6 +169,26 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="ToggleTypeCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Checked: right clicking toggles spin boxes, right button dragging disabled.</p><p>Unchecked: double clicking toggles spin boxes, right button dragging enabled.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Right Click Toggles Spinboxes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="Png16BitCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Save each RGBA component as 16-bits when saving Png files.</p><p>This leads to greater color precision for use in high end rendering and display on HDR monitors, however it makes the file size larger.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save 16-bit Png</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QTableWidget" name="DeviceTable">
|
||||
<property name="sizePolicy">
|
||||
@ -257,180 +277,212 @@
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QSpinBox" name="ThreadCountSpin">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The number of threads to use with CPU rendering.</p><p>Decrease for more responsive editing, increase for better performance.</p></body></html></string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>Threads </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>64</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QSpinBox" name="CpuSubBatchSpin">
|
||||
<property name="toolTip">
|
||||
<string>The number of 10,000 iteration chunks ran per thread on the CPU
|
||||
<item row="15" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="InteractiveRenderingTabGridLayout">
|
||||
<item row="3" column="1">
|
||||
<widget class="QGroupBox" name="InteraciveGpuFilteringGroupBox">
|
||||
<property name="title">
|
||||
<string>OpenCL Filtering</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="OpenCLFilteringLogRadioButton">
|
||||
<property name="toolTip">
|
||||
<string>Use log scale filtering for interactive editing using OpenCL.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Log Scale</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="OpenCLFilteringDERadioButton">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Use full density estimation filtering for interactive editing using OpenCL.</p><p>This is slower, but gives better feedback.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Full DE</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QGroupBox" name="InteraciveCpuFilteringGroupBox">
|
||||
<property name="title">
|
||||
<string>CPU Filtering</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="CpuFilteringLogRadioButton">
|
||||
<property name="toolTip">
|
||||
<string>Use log scale filtering for interactive editing on the CPU.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Log Scale</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="CpuFilteringDERadioButton">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Use full density estimation filtering for interactive editing on the CPU.</p><p>This is slower, but gives better feedback.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Full DE</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QSpinBox" name="OpenCLSubBatchSpin">
|
||||
<property name="toolTip">
|
||||
<string>The number of ~8M iteration chunks ran using OpenCL
|
||||
in interactive mode for each mouse movement</string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>CPU Sub Batch </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QSpinBox" name="OpenCLSubBatchSpin">
|
||||
<property name="toolTip">
|
||||
<string>The number of ~8M iteration chunks ran using OpenCL
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>OpenCL Sub Batch </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="OpenCLQualitySpin">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The default quality to use for the interactive renderer when using OpenCL.</p><p>30 is a good number for this, but you can use a larger value if you have a faster GPU.</p></body></html></string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>OpenCL Quality </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>30</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="CpuQualitySpin">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The default quality to use for the interactive renderer when using the CPU.</p><p>10 is a good number for this, but you can use a larger value if you have a faster system.</p></body></html></string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>CPU Quality </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="CpuSubBatchSpin">
|
||||
<property name="toolTip">
|
||||
<string>The number of 10,000 iteration chunks ran per thread on the CPU
|
||||
in interactive mode for each mouse movement</string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>OpenCL Sub Batch </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>CPU Sub Batch </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QSpinBox" name="RandomCountSpin">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The number of random flames to generate on startup.</p><p>These are usually of low quality, so leave the count as 1 unless you are searching for good randoms.</p></body></html></string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>Randoms </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QSpinBox" name="ThreadCountSpin">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The number of threads to use with CPU rendering.</p><p>Decrease for more responsive editing, increase for better performance.</p></body></html></string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>Threads </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>64</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QGroupBox" name="InteraciveCpuFilteringGroupBox">
|
||||
<property name="title">
|
||||
<string>CPU Filtering</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="CpuFilteringLogRadioButton">
|
||||
<property name="toolTip">
|
||||
<string>Use log scale filtering for interactive editing on the CPU.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Log Scale</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="CpuFilteringDERadioButton">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Use full density estimation filtering for interactive editing on the CPU.</p><p>This is slower, but gives better feedback.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Full DE</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QGroupBox" name="InteraciveGpuFilteringGroupBox">
|
||||
<property name="title">
|
||||
<string>OpenCL Filtering</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="OpenCLFilteringLogRadioButton">
|
||||
<property name="toolTip">
|
||||
<string>Use log scale filtering for interactive editing using OpenCL.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Log Scale</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="OpenCLFilteringDERadioButton">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Use full density estimation filtering for interactive editing using OpenCL.</p><p>This is slower, but gives better feedback.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Full DE</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QSpinBox" name="RandomCountSpin">
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="LoadLastOnStartCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The number of random flames to generate on startup.</p><p>These are usually of low quality, so leave the count as 1 unless you are searching for good randoms.</p></body></html></string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>Randoms </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="ToggleTypeCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Checked: right clicking toggles spin boxes, right button dragging disabled.</p><p>Unchecked: double clicking toggles spin boxes, right button dragging enabled.</p></body></html></string>
|
||||
<string><html><head/><body><p>Checked: load the flame from the previous run on startup.</p><p>Unchecked: create randoms on startup.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Right Click Toggles Spinboxes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="Png16BitCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Save each RGBA component as 16-bits when saving Png files.</p><p>This leads to greater color precision for use in high end rendering and display on HDR monitors, however it makes the file size larger.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save 16-bit Png</string>
|
||||
<string>Load Last on Start</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -858,10 +910,13 @@ in interactive mode for each mouse movement</string>
|
||||
<tabstop>ContinuousUpdateCheckBox</tabstop>
|
||||
<tabstop>ToggleTypeCheckBox</tabstop>
|
||||
<tabstop>Png16BitCheckBox</tabstop>
|
||||
<tabstop>RandomCountSpin</tabstop>
|
||||
<tabstop>LoadLastOnStartCheckBox</tabstop>
|
||||
<tabstop>ThreadCountSpin</tabstop>
|
||||
<tabstop>CpuSubBatchSpin</tabstop>
|
||||
<tabstop>RandomCountSpin</tabstop>
|
||||
<tabstop>OpenCLQualitySpin</tabstop>
|
||||
<tabstop>OpenCLSubBatchSpin</tabstop>
|
||||
<tabstop>CpuQualitySpin</tabstop>
|
||||
<tabstop>CpuFilteringLogRadioButton</tabstop>
|
||||
<tabstop>CpuFilteringDERadioButton</tabstop>
|
||||
<tabstop>OpenCLFilteringLogRadioButton</tabstop>
|
||||
|
Reference in New Issue
Block a user