fractorium/Source/Fractorium/FinalRenderEmberController.h

189 lines
7.6 KiB
C
Raw Normal View History

#pragma once
#include "FractoriumSettings.h"
#include "FractoriumEmberController.h"
/// <summary>
/// FinalRenderEmberControllerBase and FinalRenderEmberController<T> classes.
/// </summary>
/// <summary>
/// FractoriumEmberController and Fractorium need each other, but each can't include the other.
/// So Fractorium includes this file, and Fractorium is declared as a forward declaration here.
/// </summary>
class Fractorium;
class FractoriumFinalRenderDialog;
template <typename T> class FinalRenderPreviewRenderer;
/// <summary>
/// Used to hold the options specified in the current state of the Gui for performing the final render.
/// </summary>
struct FinalRenderGuiState
{
bool m_EarlyClip;
bool m_YAxisUp;
bool m_AlphaChannel;
bool m_Transparency;
bool m_OpenCL;
bool m_Double;
bool m_SaveXml;
bool m_DoAll;
bool m_Png16Bit;
bool m_DoSequence;
bool m_KeepAspect;
eScaleType m_Scale;
QString m_Path;
QString m_Ext;
QString m_Prefix;
QString m_Suffix;
QList<QVariant> m_Devices;
uint m_ThreadCount;
int m_ThreadPriority;
double m_SubBatchPct;
double m_WidthScale;
double m_HeightScale;
double m_Quality;
uint m_TemporalSamples;
uint m_Supersample;
size_t m_Strips;
};
/// <summary>
/// FinalRenderEmberControllerBase serves as a non-templated base class with virtual
/// functions which will be overridden in a derived class that takes a template parameter.
/// Although not meant to be used as an interactive renderer, it derives from FractoriumEmberControllerBase
/// to access a few of its members to avoid having to redefine them here.
/// </summary>
class FinalRenderEmberControllerBase : public FractoriumEmberControllerBase
{
friend FractoriumFinalRenderDialog;
public:
FinalRenderEmberControllerBase(FractoriumFinalRenderDialog* finalRenderDialog);
virtual ~FinalRenderEmberControllerBase() { }
virtual void SyncCurrentToGui() { }
virtual void SyncGuiToEmbers(size_t widthOverride = 0, size_t heightOverride = 0, bool dowidth = true, bool doheight = true) { }
virtual void SyncCurrentToSizeSpinners(bool scale, bool size, bool doWidth = true, bool doHeight = true) { }
virtual void ResetProgress(bool total = true) { }
virtual tuple<size_t, size_t, size_t> SyncAndComputeMemory() { return tuple<size_t, size_t, size_t>(0, 0, 0); }
virtual double OriginalAspect() { return 1; }
virtual QString ComposePath(const QString& name, bool unique = true) { return ""; }
virtual bool BumpQualityRender(double d) { return false; }
virtual QString SaveCurrentAgain() { return ""; }
virtual void CancelRender() { }
virtual QString CheckMemory(const tuple<size_t, size_t, size_t>& p) { return ""; }
bool Running() { return m_Result.isRunning(); }
bool CreateRendererFromGUI();
void Output(const QString& s);
protected:
bool m_Run = false;
bool m_IsQualityBump = false;
size_t m_ImageCount = 0;
std::atomic<size_t> m_FinishedImageCount;
QFuture<void> m_Result;
std::function<void (void)> m_FinalRenderFunc;
shared_ptr<FractoriumSettings> m_Settings;
FractoriumFinalRenderDialog* m_FinalRenderDialog;
FinalRenderGuiState m_GuiState;
std::recursive_mutex m_ProgressCs;
Timing m_RenderTimer;
Timing m_TotalTimer;
};
/// <summary>
/// Templated derived class which implements all interaction functionality between the embers
/// of a specific template type and the final render dialog.
/// </summary>
template<typename T>
class FinalRenderEmberController : public FinalRenderEmberControllerBase
{
friend FinalRenderPreviewRenderer<T>;
public:
FinalRenderEmberController(FractoriumFinalRenderDialog* finalRender);
--User changes -Remove the Type field from the variations tree and instead just put the type indicator icon next to the variation name. -Double clicking to toggle variation parameter spinners now resets the value to the default if there is one, else it uses zero. If it is already using the default, it is toggled to 0. -Add a new button to toggle xaos on and off. -When duplicating a flame, insert it immediately after the one being duplicated instead of at the end of the file. -When switching between flames in a file, keep the same xform index selected rather than resetting it to the first xform each time. -Create a threaded writer for the final render and EmberAnimate so the rendering process does not get delayed by file saving which may take a long time. -Remove warning which said "Frames per rot cannot be greater than one while Rotations is zero" when generating a sequence. -Add the Circle_Rand variation from Chaotica. -Add tool tips to clarify the following items: --Auto Unique Filenames checkbox in the options dialog. --Xaos table headers. --Bug fixes -Generating sequences using the following variations would be done incorrectly: circletrans1, collideoscope, crob, curlsp, glynnsim1, glynnsim2, hypercrop, julian, julian, mobiusn, nblur, waves2, wavesn. -Adding/removing nodes from the color curve had accidentally been disabled. -The applied xaos weight table was not showing normalized weight values. -Changing the size of a flame was not observing the Apply To All checkbox. -Do not clamp the Rotate field to +/-180, because this causes the rotation to switch from CW to CCW during sequence generation. Instead, leave it exactly as the user entered it so the rotations proceed in the same direction.
2023-11-22 00:58:22 -05:00
virtual ~FinalRenderEmberController();
//Virtual functions overridden from FractoriumEmberControllerBase.
void SetEmberFile(const EmberFile<float>& emberFile, bool move) override;
void CopyEmberFile(EmberFile<float>& emberFile, bool sequence, std::function<void(Ember<float>& ember)> perEmberOperation/* = [&](Ember<float>& ember) { }*/) override;
#ifdef DO_DOUBLE
void SetEmberFile(const EmberFile<double>& emberFile, bool move) override;
void CopyEmberFile(EmberFile<double>& emberFile, bool sequence, std::function<void(Ember<double>& ember)> perEmberOperation/* = [&](Ember<double>& ember) { }*/) override;
#endif
void SetEmber(size_t index, bool verbatim) override;
void SaveCurrentAsXml(QString filename = "") override;
bool Render() override;
bool BumpQualityRender(double d) override;
bool CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool updatePreviews, bool shared = true) override;
int ProgressFunc(Ember<T>& ember, void* foo, double fraction, int stage, double etaMs) override;
size_t Index() const noexcept override { return m_Ember->m_Index; }
uint SizeOfT() const noexcept override { return sizeof(T); }
//Virtual functions overridden from FinalRenderEmberControllerBase.
void SyncCurrentToGui() override;
void SyncGuiToEmbers(size_t widthOverride = 0, size_t heightOverride = 0, bool dowidth = true, bool doheight = true) override;
void SyncCurrentToSizeSpinners(bool scale, bool size, bool doWidth = true, bool doHeight = true) override;
void ResetProgress(bool total = true) override;
tuple<size_t, size_t, size_t> SyncAndComputeMemory() override;
double OriginalAspect() override { return double(m_Ember->m_OrigFinalRasW) / m_Ember->m_OrigFinalRasH; }
QString Name() const override { return QString::fromStdString(m_Ember->m_Name); }
QString ComposePath(const QString& name, bool unique = true) override;
QString SaveCurrentAgain() override;
void CancelRender() override;
QString CheckMemory(const tuple<size_t, size_t, size_t>& p) override;
//Non Virtual functions.
EmberNs::Renderer<T, float>* FirstOrDefaultRenderer();
protected:
void Pause(bool pause) override;
bool Paused() override;
void HandleFinishedProgress();
QString SaveCurrentRender(Ember<T>& ember);
QString SaveCurrentRender(Ember<T>& ember, const EmberImageComments& comments, vector<v4F>& pixels, size_t width, size_t height, bool png16Bit, bool transparency);
void RenderComplete(Ember<T>& ember);
void RenderComplete(Ember<T>& ember, const EmberStats& stats, Timing& renderTimer);
void SyncGuiToEmber(Ember<T>& ember, size_t widthOverride = 0, size_t heightOverride = 0, bool dowidth = true, bool doheight = true);
bool SyncGuiToRenderer();
void SetProgressComplete(int val);
bool RenderSingleEmber(Ember<T>& ember, bool fullRender, size_t& stripForProgress);
bool RenderSingleEmberFromSeries(std::atomic<size_t>* atomfTime, size_t index);
Ember<T>* m_Ember;
EmberFile<T> m_EmberFile;
EmberToXml<T> m_XmlWriter;
unique_ptr<FinalRenderPreviewRenderer<T>> m_FinalPreviewRenderer;
vector<unique_ptr<EmberNs::Renderer<T, float>>> m_Renderers;
--User changes -Remove the Type field from the variations tree and instead just put the type indicator icon next to the variation name. -Double clicking to toggle variation parameter spinners now resets the value to the default if there is one, else it uses zero. If it is already using the default, it is toggled to 0. -Add a new button to toggle xaos on and off. -When duplicating a flame, insert it immediately after the one being duplicated instead of at the end of the file. -When switching between flames in a file, keep the same xform index selected rather than resetting it to the first xform each time. -Create a threaded writer for the final render and EmberAnimate so the rendering process does not get delayed by file saving which may take a long time. -Remove warning which said "Frames per rot cannot be greater than one while Rotations is zero" when generating a sequence. -Add the Circle_Rand variation from Chaotica. -Add tool tips to clarify the following items: --Auto Unique Filenames checkbox in the options dialog. --Xaos table headers. --Bug fixes -Generating sequences using the following variations would be done incorrectly: circletrans1, collideoscope, crob, curlsp, glynnsim1, glynnsim2, hypercrop, julian, julian, mobiusn, nblur, waves2, wavesn. -Adding/removing nodes from the color curve had accidentally been disabled. -The applied xaos weight table was not showing normalized weight values. -Changing the size of a flame was not observing the Apply To All checkbox. -Do not clamp the Rotate field to +/-180, because this causes the rotation to switch from CW to CCW during sequence generation. Instead, leave it exactly as the user entered it so the rotations proceed in the same direction.
2023-11-22 00:58:22 -05:00
ThreadedWriter m_ThreadedWriter;
};
/// <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>
template <typename T>
class FinalRenderPreviewRenderer : public PreviewRenderer<T>
{
public:
using PreviewRenderer<T>::m_PreviewRun;
using PreviewRenderer<T>::m_PreviewVec;
using PreviewRenderer<T>::m_PreviewEmber;
using PreviewRenderer<T>::m_PreviewRenderer;
using PreviewRenderer<T>::m_PreviewFinalImage;
FinalRenderPreviewRenderer(FinalRenderEmberController<T>* controller) : m_Controller(controller), PreviewRenderer<T>(nullptr)
{
}
void PreviewRenderFunc(uint start, uint end) override;
private:
FinalRenderEmberController<T>* m_Controller;
};