mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-07-02 22:34:52 -04:00
--User changes
-Add animation sequence creation to Fractorium. -Add two new options to EmberGenome which are used when generating an animation sequence.: --startcount: Add this number to the filename of each flame. --padding: Override the automatically calculated amount of padding zeroes added to each filename. --Bug fixes -Prevent filenames in command line programs from using scientific notation when rendering a large number of frames. -Fix tab orders to match newer GUI items which were overlooked in previous releases. -Re-render previews if transparency value in the options dialog was changed. Re-rendering was previously only done if early clip or y axis up was changed. -Use transparency when rendering thumbnail previews. --Code changes -Wrap EmberCommon.h in a namespace called EmberCommon. -Move FormatName() from EmberGenome to EmberCommon.h/cpp -Add a prefix parameter to EmberFile::DefaultFilename() to allow for creating a default filename for sequences. -When showing the final render dialog, allow specifying where it came from: the toolbar or the render sequence button. -Refactor all preview rendering code out into its own class hierarchy with overrides for the main window and the final render dialog. -Remove all preview render cancelling functions, they are now built into the new class hierarchy and a new render will not start until the previous one is stopped. -Add two new function ConstrainLow() and ConstrainHigh() which wrap constraining two min/max spinboxes to each others' values. -Add a bool to FractoriumEmberControllerBase::CopyEmberFile() to specify whether to copy the main file or the sequence file. This is somewhat of a hack and was done in a rush. -Add a bool to FractoriumEmberControllerBase::SetEmberFile() to specify whether to move the file rather than copy. This is used in FinalRenderEmberController and improves efficiency. -Add wrapper functions for variations filter dialog settings.
This commit is contained in:
@ -101,50 +101,7 @@ template<typename T>
|
||||
FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderDialog* finalRender)
|
||||
: FinalRenderEmberControllerBase(finalRender)
|
||||
{
|
||||
m_FinalPreviewRenderer = make_unique<EmberNs::Renderer<T, float>>();
|
||||
m_FinalPreviewRenderer->Callback(nullptr);
|
||||
m_FinalPreviewRenderer->NumChannels(4);
|
||||
m_FinalPreviewRenderFunc = [&]()
|
||||
{
|
||||
rlg l(m_PreviewCs);//Thread prep.
|
||||
m_PreviewRun = true;
|
||||
m_FinalPreviewRenderer->Abort();
|
||||
T scalePercentage;
|
||||
size_t maxDim = 100;
|
||||
QLabel* widget = m_FinalRenderDialog->ui.FinalRenderPreviewLabel;
|
||||
|
||||
//Determine how to scale the scaled ember to fit in the label with a max of 100x100.
|
||||
if (m_Ember->m_FinalRasW >= m_Ember->m_FinalRasH)
|
||||
scalePercentage = T(maxDim) / m_Ember->m_FinalRasW;
|
||||
else
|
||||
scalePercentage = T(maxDim) / m_Ember->m_FinalRasH;
|
||||
|
||||
m_PreviewEmber = *m_Ember;
|
||||
m_PreviewEmber.m_Quality = 100;
|
||||
m_PreviewEmber.m_TemporalSamples = 1;
|
||||
m_PreviewEmber.m_FinalRasW = std::max<size_t>(1, std::min<size_t>(maxDim, size_t(scalePercentage * m_Ember->m_FinalRasW)));//Ensure neither is zero.
|
||||
m_PreviewEmber.m_FinalRasH = std::max<size_t>(1, std::min<size_t>(maxDim, size_t(scalePercentage * m_Ember->m_FinalRasH)));
|
||||
m_PreviewEmber.m_PixelsPerUnit = scalePercentage * m_Ember->m_PixelsPerUnit;
|
||||
m_FinalPreviewRenderer->EarlyClip(m_FinalRenderDialog->EarlyClip());
|
||||
m_FinalPreviewRenderer->YAxisUp(m_FinalRenderDialog->YAxisUp());
|
||||
m_FinalPreviewRenderer->Transparency(m_FinalRenderDialog->Transparency());
|
||||
m_FinalPreviewRenderer->SetEmber(m_PreviewEmber);
|
||||
m_FinalPreviewRenderer->PrepFinalAccumVector(m_PreviewFinalImage);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run().
|
||||
auto strips = VerifyStrips(m_PreviewEmber.m_FinalRasH, m_FinalRenderDialog->Strips(),
|
||||
[&](const string & s) { }, [&](const string & s) { }, [&](const string & s) { });
|
||||
StripsRender<T>(m_FinalPreviewRenderer.get(), m_PreviewEmber, m_PreviewFinalImage, 0, strips, m_FinalRenderDialog->YAxisUp(),
|
||||
[&](size_t strip) { },//Pre strip.
|
||||
[&](size_t strip) { },//Post strip.
|
||||
[&](size_t strip) { },//Error.
|
||||
[&](Ember<T>& finalEmber)//Final strip.
|
||||
{
|
||||
QImage image(int(finalEmber.m_FinalRasW), int(finalEmber.m_FinalRasH), QImage::Format_RGBA8888);//The label wants RGBA.
|
||||
memcpy(image.scanLine(0), m_PreviewFinalImage.data(), finalEmber.m_FinalRasW * finalEmber.m_FinalRasH * 4);//Memcpy the data in.
|
||||
QPixmap pixmap(QPixmap::fromImage(image));
|
||||
QMetaObject::invokeMethod(widget, "setPixmap", Qt::QueuedConnection, Q_ARG(QPixmap, pixmap));
|
||||
});
|
||||
m_PreviewRun = false;
|
||||
};
|
||||
m_FinalPreviewRenderer = make_unique<FinalRenderPreviewRenderer<T>>(this);
|
||||
//The main rendering function which will be called in a Qt thread.
|
||||
//A backup Xml is made before the rendering process starts just in case it crashes before finishing.
|
||||
//If it finishes successfully, delete the backup file.
|
||||
@ -380,24 +337,24 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
/// These are used to preserve the current ember/file when switching between renderers.
|
||||
/// Note that some precision will be lost when going from double to float.
|
||||
/// </summary>
|
||||
template <typename T> void FinalRenderEmberController<T>::SetEmberFile(const EmberFile<float>& emberFile)
|
||||
template <typename T> void FinalRenderEmberController<T>::SetEmberFile(const EmberFile<float>& emberFile, bool move)
|
||||
{
|
||||
m_EmberFile = emberFile;
|
||||
move ? m_EmberFile = std::move(emberFile) : m_EmberFile = emberFile;
|
||||
m_Ember = m_EmberFile.Get(0);
|
||||
}
|
||||
template <typename T> void FinalRenderEmberController<T>::CopyEmberFile(EmberFile<float>& emberFile, std::function<void(Ember<float>& ember)> perEmberOperation)
|
||||
template <typename T> void FinalRenderEmberController<T>::CopyEmberFile(EmberFile<float>& emberFile, bool sequence, std::function<void(Ember<float>& ember)> perEmberOperation)
|
||||
{
|
||||
emberFile.m_Filename = m_EmberFile.m_Filename;
|
||||
CopyCont(emberFile.m_Embers, m_EmberFile.m_Embers, perEmberOperation);
|
||||
}
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
template <typename T> void FinalRenderEmberController<T>::SetEmberFile(const EmberFile<double>& emberFile)
|
||||
template <typename T> void FinalRenderEmberController<T>::SetEmberFile(const EmberFile<double>& emberFile, bool move)
|
||||
{
|
||||
m_EmberFile = emberFile;
|
||||
move ? m_EmberFile = std::move(emberFile) : m_EmberFile = emberFile;
|
||||
m_Ember = m_EmberFile.Get(0);
|
||||
}
|
||||
template <typename T> void FinalRenderEmberController<T>::CopyEmberFile(EmberFile<double>& emberFile, std::function<void(Ember<double>& ember)> perEmberOperation)
|
||||
template <typename T> void FinalRenderEmberController<T>::CopyEmberFile(EmberFile<double>& emberFile, bool sequence, std::function<void(Ember<double>& ember)> perEmberOperation)
|
||||
{
|
||||
emberFile.m_Filename = m_EmberFile.m_Filename;
|
||||
CopyCont(emberFile.m_Embers, m_EmberFile.m_Embers, perEmberOperation);
|
||||
@ -692,8 +649,7 @@ tuple<size_t, size_t, size_t> FinalRenderEmberController<T>::SyncAndComputeMemor
|
||||
m_Renderer->ComputeBounds();
|
||||
m_Renderer->ComputeQuality();
|
||||
m_Renderer->ComputeCamera();
|
||||
CancelPreviewRender();
|
||||
m_FinalPreviewRenderFunc();
|
||||
m_FinalPreviewRenderer->Render(UINT_MAX, UINT_MAX);
|
||||
p = m_Renderer->MemoryRequired(strips, true, m_FinalRenderDialog->DoSequence());
|
||||
iterCount = m_Renderer->TotalIterCount(strips);
|
||||
}
|
||||
@ -710,8 +666,7 @@ tuple<size_t, size_t, size_t> FinalRenderEmberController<T>::SyncAndComputeMemor
|
||||
renderer->ComputeCamera();
|
||||
}
|
||||
|
||||
CancelPreviewRender();
|
||||
m_FinalPreviewRenderFunc();
|
||||
m_FinalPreviewRenderer->Render(UINT_MAX, UINT_MAX);
|
||||
strips = 1;
|
||||
p = m_Renderers[0]->MemoryRequired(1, true, m_FinalRenderDialog->DoSequence());
|
||||
iterCount = m_Renderers[0]->TotalIterCount(strips);
|
||||
@ -759,22 +714,6 @@ EmberNs::Renderer<T, float>* FinalRenderEmberController<T>::FirstOrDefaultRender
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop the preview renderer.
|
||||
/// This is meant to only be called programatically and never by the user.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
void FinalRenderEmberController<T>::CancelPreviewRender()
|
||||
{
|
||||
m_FinalPreviewRenderer->Abort();
|
||||
|
||||
while (m_FinalPreviewRenderer->InRender()) { QApplication::processEvents(); }
|
||||
|
||||
while (m_PreviewRun) { QApplication::processEvents(); }
|
||||
|
||||
while (m_FinalPreviewResult.isRunning()) { QApplication::processEvents(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save the output of the render.
|
||||
/// </summary>
|
||||
@ -1017,6 +956,56 @@ QString FinalRenderEmberController<T>::CheckMemory(const tuple<size_t, size_t, s
|
||||
return s;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Thin derivation to handle preview rendering that is specific to the final render dialog.
|
||||
/// This differs from the preview renderers on the main window because they render multiple embers
|
||||
/// to a tree, whereas this renders a single preview.
|
||||
/// </summary>
|
||||
/// <param name="start">Ignored</param>
|
||||
/// <param name="end">Ignored</param>
|
||||
template <typename T>
|
||||
void FinalRenderPreviewRenderer<T>::PreviewRenderFunc(uint start, uint end)
|
||||
{
|
||||
T scalePercentage;
|
||||
size_t maxDim = 100;
|
||||
auto d = m_Controller->m_FinalRenderDialog;
|
||||
QLabel* widget = d->ui.FinalRenderPreviewLabel;
|
||||
//Determine how to scale the scaled ember to fit in the label with a max of 100x100.
|
||||
auto e = m_Controller->m_Ember;
|
||||
|
||||
if (e->m_FinalRasW >= e->m_FinalRasH)
|
||||
scalePercentage = T(maxDim) / e->m_FinalRasW;
|
||||
else
|
||||
scalePercentage = T(maxDim) / e->m_FinalRasH;
|
||||
|
||||
m_PreviewEmber = *e;
|
||||
m_PreviewEmber.m_Quality = 100;
|
||||
m_PreviewEmber.m_TemporalSamples = 1;
|
||||
m_PreviewEmber.m_FinalRasW = std::max<size_t>(1, std::min<size_t>(maxDim, size_t(scalePercentage * e->m_FinalRasW)));//Ensure neither is zero.
|
||||
m_PreviewEmber.m_FinalRasH = std::max<size_t>(1, std::min<size_t>(maxDim, size_t(scalePercentage * e->m_FinalRasH)));
|
||||
m_PreviewEmber.m_PixelsPerUnit = scalePercentage * e->m_PixelsPerUnit;
|
||||
m_PreviewRenderer.EarlyClip(d->EarlyClip());
|
||||
m_PreviewRenderer.YAxisUp(d->YAxisUp());
|
||||
m_PreviewRenderer.Transparency(d->Transparency());
|
||||
m_PreviewRenderer.Callback(nullptr);
|
||||
m_PreviewRenderer.NumChannels(4);
|
||||
m_PreviewRenderer.SetEmber(m_PreviewEmber);
|
||||
m_PreviewRenderer.PrepFinalAccumVector(m_PreviewFinalImage);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run().
|
||||
auto strips = VerifyStrips(m_PreviewEmber.m_FinalRasH, d->Strips(),
|
||||
[&](const string & s) {}, [&](const string & s) {}, [&](const string & s) {});
|
||||
StripsRender<T>(&m_PreviewRenderer, m_PreviewEmber, m_PreviewFinalImage, 0, strips, d->YAxisUp(),
|
||||
[&](size_t strip) {},//Pre strip.
|
||||
[&](size_t strip) {},//Post strip.
|
||||
[&](size_t strip) {},//Error.
|
||||
[&](Ember<T>& finalEmber)//Final strip.
|
||||
{
|
||||
QImage image(int(finalEmber.m_FinalRasW), int(finalEmber.m_FinalRasH), QImage::Format_RGBA8888);//The label wants RGBA.
|
||||
memcpy(image.scanLine(0), m_PreviewFinalImage.data(), finalEmber.m_FinalRasW * finalEmber.m_FinalRasH * 4);//Memcpy the data in.
|
||||
QPixmap pixmap(QPixmap::fromImage(image));
|
||||
QMetaObject::invokeMethod(widget, "setPixmap", Qt::QueuedConnection, Q_ARG(QPixmap, pixmap));
|
||||
});
|
||||
}
|
||||
|
||||
template class FinalRenderEmberController<float>;
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
|
Reference in New Issue
Block a user