From 745f06d29d951e1b7cd87d8dd28c3de8039dfefe Mon Sep 17 00:00:00 2001 From: Person Date: Tue, 21 Nov 2023 22:58:22 -0700 Subject: [PATCH] --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. --- .../Installer/FractoriumInstaller.wixproj | 2 +- Builds/MSVC/Installer/Product.wxs | 4 +- Builds/MSVC/Solution/Ember.rc | Bin 4530 -> 4546 bytes Builds/MSVC/Solution/EmberAnimate.rc | 8 +- Builds/MSVC/Solution/EmberCL.rc | Bin 4556 -> 4572 bytes Builds/MSVC/Solution/EmberGenome.rc | 8 +- Builds/MSVC/Solution/EmberRender.rc | 8 +- Builds/MSVC/Solution/Fractorium.rc | Bin 4498 -> 4514 bytes Builds/MSVC/Solution/Fractorium.sln | 6 +- Data/Version History.txt | 2 +- Source/Ember/Ember.cpp | 1 + Source/Ember/EmberDefines.h | 2 +- Source/Ember/Variation.h | 14 +-- Source/Ember/VariationList.cpp | 1 + Source/Ember/Variations01.h | 96 +++++++------- Source/Ember/Variations02.h | 4 +- Source/Ember/Variations03.h | 10 +- Source/Ember/Variations04.h | 22 ++-- Source/Ember/Variations05.h | 10 +- Source/Ember/Variations06.h | 14 +-- Source/Ember/Variations07.h | 18 +-- Source/Ember/Variations08.h | 117 ++++++++++++++++++ Source/Ember/VariationsDC.h | 50 ++++---- Source/Ember/XmlToEmber.cpp | 8 +- Source/EmberAnimate/EmberAnimate.cpp | 17 +-- Source/EmberCommon/EmberCommon.h | 45 +++++++ Source/EmberCommon/JpegUtils.h | 53 ++++---- Source/Fractorium/AboutDialog.ui | 2 +- Source/Fractorium/CurvesGraphicsView.cpp | 2 +- .../Fractorium/FinalRenderEmberController.cpp | 114 ++++++++++------- .../Fractorium/FinalRenderEmberController.h | 3 +- Source/Fractorium/Fractorium.cpp | 20 +-- Source/Fractorium/Fractorium.h | 5 +- Source/Fractorium/Fractorium.ui | 23 ++-- .../Fractorium/FractoriumEmberController.cpp | 20 ++- Source/Fractorium/FractoriumEmberController.h | 22 +++- Source/Fractorium/FractoriumInfo.cpp | 2 + Source/Fractorium/FractoriumLibrary.cpp | 18 +-- Source/Fractorium/FractoriumMenus.cpp | 15 +-- Source/Fractorium/FractoriumParams.cpp | 7 +- Source/Fractorium/FractoriumRender.cpp | 4 + Source/Fractorium/FractoriumXaos.cpp | 67 ++++++++-- Source/Fractorium/FractoriumXforms.cpp | 6 +- .../Fractorium/FractoriumXformsVariations.cpp | 83 ++++++++----- Source/Fractorium/GLEmberController.cpp | 4 +- Source/Fractorium/GLWidget.cpp | 2 +- Source/Fractorium/OptionsDialog.ui | 3 + 47 files changed, 616 insertions(+), 326 deletions(-) diff --git a/Builds/MSVC/Installer/FractoriumInstaller.wixproj b/Builds/MSVC/Installer/FractoriumInstaller.wixproj index b017940..0325688 100644 --- a/Builds/MSVC/Installer/FractoriumInstaller.wixproj +++ b/Builds/MSVC/Installer/FractoriumInstaller.wixproj @@ -1,7 +1,7 @@ 3.7 - Fractorium_23.23.8.1 + Fractorium_23.23.8.100 $(SolutionDir)..\..\..\Bin\$(Platform)\$(Configuration)\ diff --git a/Builds/MSVC/Installer/Product.wxs b/Builds/MSVC/Installer/Product.wxs index c3b116c..0bf0fc9 100644 --- a/Builds/MSVC/Installer/Product.wxs +++ b/Builds/MSVC/Installer/Product.wxs @@ -1,5 +1,5 @@  - + @@ -12,7 +12,7 @@ - + diff --git a/Builds/MSVC/Solution/Ember.rc b/Builds/MSVC/Solution/Ember.rc index 71c1484f18141ff1b27c1fabb2eb6e49fb4e0687..40d4bc5a93c41e61cac40e60ebe21af9f3332c17 100644 GIT binary patch delta 46 ucmdm_d`Nl2FAin{27}2zIc!1nW>e17OkjbFJmQ7^$hm_ delta 29 lcmX@4yh(Y(FOJFoIBYiCah_tDtj8_3S&3&3IQ4LrC delta 37 vcmV+=0NVfDBg`YP_z08y2s{G~01A`A2^F(c3Bm%C@C+8SFbt>xqudPy73dA0 diff --git a/Builds/MSVC/Solution/EmberGenome.rc b/Builds/MSVC/Solution/EmberGenome.rc index 08a6df7..2181e92 100644 --- a/Builds/MSVC/Solution/EmberGenome.rc +++ b/Builds/MSVC/Solution/EmberGenome.rc @@ -49,8 +49,8 @@ // VS_VERSION_INFO VERSIONINFO - FILEVERSION 23, 23, 8, 1 - PRODUCTVERSION 23, 23, 8, 1 + FILEVERSION 23, 23, 8, 100 + PRODUCTVERSION 23, 23, 8, 100 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -67,12 +67,12 @@ BEGIN VALUE "CompanyName", "Open Source" VALUE "FileDescription", "Manipulates fractal flame parameter files" - VALUE "FileVersion", "23, 23, 8, 1" + VALUE "FileVersion", "23, 23, 8, 100" VALUE "InternalName", "EmberGenome.exe" VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2021, GPL v3" VALUE "OriginalFilename", "EmberGenome.exe" VALUE "ProductName", "Ember Genome" - VALUE "ProductVersion", "23, 23, 8, 1" + VALUE "ProductVersion", "23, 23, 8, 100" END END BLOCK "VarFileInfo" diff --git a/Builds/MSVC/Solution/EmberRender.rc b/Builds/MSVC/Solution/EmberRender.rc index 688f8c9..4ce4541 100644 --- a/Builds/MSVC/Solution/EmberRender.rc +++ b/Builds/MSVC/Solution/EmberRender.rc @@ -49,8 +49,8 @@ // VS_VERSION_INFO VERSIONINFO - FILEVERSION 23, 23, 8, 1 - PRODUCTVERSION 23, 23, 8, 1 + FILEVERSION 23, 23, 8, 100 + PRODUCTVERSION 23, 23, 8, 100 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -67,12 +67,12 @@ BEGIN VALUE "CompanyName", "Open Source" VALUE "FileDescription", "Renders fractal flames as single images" - VALUE "FileVersion", "23, 23, 8, 1" + VALUE "FileVersion", "23, 23, 8, 100" VALUE "InternalName", "EmberRender.exe" VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2021, GPL v3" VALUE "OriginalFilename", "EmberRender.exe" VALUE "ProductName", "Ember Render" - VALUE "ProductVersion", "23, 23, 8, 1" + VALUE "ProductVersion", "23, 23, 8, 100" END END BLOCK "VarFileInfo" diff --git a/Builds/MSVC/Solution/Fractorium.rc b/Builds/MSVC/Solution/Fractorium.rc index 860c2c221f980f34429f8d8e5bbadf1478f06781..f574574afd7313222c60f23819ffe5c834807753 100644 GIT binary patch delta 42 pcmbQFyhwS&B@Si-27}2LIc!1nW?s&%Okl=A?u(3I#zbC5761yH3t<2N delta 29 lcmZ3aJV|-OC63A0IBYhHac*IntiU6-`3d(f#>I&Y diff --git a/Builds/MSVC/Solution/Fractorium.sln b/Builds/MSVC/Solution/Fractorium.sln index 0675c50..cf925db 100644 --- a/Builds/MSVC/Solution/Fractorium.sln +++ b/Builds/MSVC/Solution/Fractorium.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28010.2036 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34202.233 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ember", "Ember.vcxproj", "{2BDB7A54-BB1A-476B-A6E5-F81E90AD4E67}" EndProject @@ -17,7 +17,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EmberGenome", "EmberGenome. EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EmberCL", "EmberCL.vcxproj", "{F6A9102C-69A9-48FB-BC4B-49E49AF43236}" EndProject -Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "FractoriumInstaller", "..\Installer\FractoriumInstaller.wixproj", "{C8096C47-E358-438C-A520-146D46B0637D}" +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "FractoriumInstaller", "..\Installer\FractoriumInstaller.wixproj", "{C8096C47-E358-438C-A520-146D46B0637D}" ProjectSection(ProjectDependencies) = postProject {F6A9102C-69A9-48FB-BC4B-49E49AF43236} = {F6A9102C-69A9-48FB-BC4B-49E49AF43236} {4A191F4C-03AC-4F1B-AFFD-F5483ECEBD29} = {4A191F4C-03AC-4F1B-AFFD-F5483ECEBD29} diff --git a/Data/Version History.txt b/Data/Version History.txt index 48e4219..8c39fb4 100644 --- a/Data/Version History.txt +++ b/Data/Version History.txt @@ -1,4 +1,4 @@ -23.23.8.1 8/6/2023 +23.23.8.100 8/6/2023 --User changes -Add Clear Sequence button to the Sequence Panel. diff --git a/Source/Ember/Ember.cpp b/Source/Ember/Ember.cpp index 4df20dd..e5ac585 100644 --- a/Source/Ember/Ember.cpp +++ b/Source/Ember/Ember.cpp @@ -497,6 +497,7 @@ uint Timing::m_ProcessorCount; EXPORTPREPOSTREGVAR(Inkdrop, T) \ EXPORTPREPOSTREGVAR(HexModulus, T) \ EXPORTPREPOSTREGVAR(Vignette, T) \ + EXPORTPREPOSTREGVAR(Circle_Rand, T) \ template EMBER_API class VariationList; \ template EMBER_API class SpatialFilter; \ template EMBER_API class GaussianFilter; \ diff --git a/Source/Ember/EmberDefines.h b/Source/Ember/EmberDefines.h index 7a7242a..9a99cc1 100644 --- a/Source/Ember/EmberDefines.h +++ b/Source/Ember/EmberDefines.h @@ -37,7 +37,7 @@ static void sincos(float x, float* s, float* c) namespace EmberNs { -#define EMBER_VERSION "23.23.8.1" +#define EMBER_VERSION "23.23.8.100" //#define FLAM3_COMPAT 1//Uncomment this if you want full compatibility with flam3 regarding some of the trig-based variations in Variations01.h #define EPS6 T(1e-6) #define EPS std::numeric_limits::epsilon()//Apoplugin.h uses -20, but it's more mathematically correct to do it this way. diff --git a/Source/Ember/Variation.h b/Source/Ember/Variation.h index 8b6edb9..622b61d 100644 --- a/Source/Ember/Variation.h +++ b/Source/Ember/Variation.h @@ -96,6 +96,7 @@ enum class eVariationId : glm::uint VAR_CIRCLERAND, VAR_CIRCLESPLIT, VAR_CIRCLETRANS1, + VAR_CIRCLE_RAND, VAR_CIRCLIZE , VAR_CIRCLIZE2 , VAR_CIRCUS, @@ -514,6 +515,7 @@ enum class eVariationId : glm::uint VAR_PRE_CIRCLERAND, VAR_PRE_CIRCLESPLIT, VAR_PRE_CIRCLETRANS1, + VAR_PRE_CIRCLE_RAND, VAR_PRE_CIRCLIZE, VAR_PRE_CIRCLIZE2, VAR_PRE_CIRCUS, @@ -931,6 +933,7 @@ enum class eVariationId : glm::uint VAR_POST_CIRCLERAND, VAR_POST_CIRCLESPLIT, VAR_POST_CIRCLETRANS1, + VAR_POST_CIRCLE_RAND, VAR_POST_CIRCLIZE, VAR_POST_CIRCLIZE2, VAR_POST_CIRCUS, @@ -2213,14 +2216,12 @@ public: if (!_stricmp(param.Name().c_str(), name)) { param.Set(val); + this->Precalc(); b = true; break; } } - if (b) - this->Precalc(); - return b; } @@ -2235,10 +2236,11 @@ public: bool b = false; if (index < m_Params.size()) + { m_Params[index].Set(val); - - if (b) this->Precalc(); + b = true; + } return b; } @@ -2268,8 +2270,6 @@ public: void Clear() { for (auto& param : m_Params) *(param.Param()) = 0; - - this->Precalc(); } /// diff --git a/Source/Ember/VariationList.cpp b/Source/Ember/VariationList.cpp index 105df0a..1ddb55b 100644 --- a/Source/Ember/VariationList.cpp +++ b/Source/Ember/VariationList.cpp @@ -330,6 +330,7 @@ VariationList::VariationList() ADDPREPOSTREGVAR(CircleLinear) ADDPREPOSTREGVAR(CircleRand) ADDPREPOSTREGVAR(CircleTrans1) + ADDPREPOSTREGVAR(Circle_Rand) ADDPREPOSTREGVAR(Cubic3D) ADDPREPOSTREGVAR(CubicLattice3D) ADDPREPOSTREGVAR(Foci3D) diff --git a/Source/Ember/Variations01.h b/Source/Ember/Variations01.h index 4c439d0..e695268 100644 --- a/Source/Ember/Variations01.h +++ b/Source/Ember/Variations01.h @@ -1691,7 +1691,7 @@ public: ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); - string angle = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. + string angle = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string dist = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string vSin = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc. string vfCos = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1729,14 +1729,14 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_Angle, prefix + "perspective_angle"));//Params. + m_Params.push_back(ParamWithName(&m_Angle, prefix + "perspective_angle")); m_Params.push_back(ParamWithName(&m_Dist, prefix + "perspective_dist")); m_Params.push_back(ParamWithName(true, &m_Vsin, prefix + "perspective_vsin"));//Precalc. m_Params.push_back(ParamWithName(true, &m_VfCos, prefix + "perspective_vfcos")); } private: - T m_Angle;//Params. + T m_Angle; T m_Dist; T m_Vsin;//Precalc. T m_VfCos; @@ -1808,7 +1808,7 @@ public: ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); - string dist = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. + string dist = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string rn = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc. string cn = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1842,14 +1842,14 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_Dist, prefix + "julian_dist", 1));//Params. + m_Params.push_back(ParamWithName(&m_Dist, prefix + "julian_dist", 1)); m_Params.push_back(ParamWithName(&m_Power, prefix + "julian_power", 1, eParamType::INTEGER_NONZERO)); m_Params.push_back(ParamWithName(true, &m_Rn, prefix + "julian_rn"));//Precalc. m_Params.push_back(ParamWithName(true, &m_Cn, prefix + "julian_cn")); } private: - T m_Dist;//Params. + T m_Dist; T m_Power; T m_Rn;//Precalc. T m_Cn; @@ -1900,7 +1900,7 @@ public: ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); - string dist = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. + string dist = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string rn = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc. string cn = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1954,14 +1954,14 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_Dist, prefix + "juliascope_dist", 1));//Params. + m_Params.push_back(ParamWithName(&m_Dist, prefix + "juliascope_dist", 1)); m_Params.push_back(ParamWithName(&m_Power, prefix + "juliascope_power", 1, eParamType::REAL_NONZERO)); m_Params.push_back(ParamWithName(true, &m_Rn, prefix + "juliascope_rn"));//Precalc. m_Params.push_back(ParamWithName(true, &m_Cn, prefix + "juliascope_cn")); } private: - T m_Dist;//Params. + T m_Dist; T m_Power; T m_Rn;//Precalc. T m_Cn; @@ -2113,7 +2113,7 @@ public: ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); - string angle = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. + string angle = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string spin = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc. string zoom = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" @@ -2144,13 +2144,13 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_Angle, prefix + "radial_blur_angle"));//Params. + m_Params.push_back(ParamWithName(&m_Angle, prefix + "radial_blur_angle")); m_Params.push_back(ParamWithName(true, &m_Spin, prefix + "radial_blur_spin"));//Precalc. m_Params.push_back(ParamWithName(true, &m_Zoom, prefix + "radial_blur_zoom")); } private: - T m_Angle;//Params. + T m_Angle; T m_Spin;//Precalc. T m_Zoom; }; @@ -2222,7 +2222,7 @@ protected: m_Params.push_back(ParamWithName(&m_Slices, prefix + "pie_slices", 6, eParamType::INTEGER_NONZERO, 1)); m_Params.push_back(ParamWithName(&m_Rotation, prefix + "pie_rotation", T(0.5), eParamType::REAL_CYCLIC, 0, M_2PI)); m_Params.push_back(ParamWithName(&m_Thickness, prefix + "pie_thickness", T(0.5), eParamType::REAL, 0, 1)); - m_Params.push_back(ParamWithName(true, &m_Pi2Slices, prefix + "pie_pi2_slices")); + m_Params.push_back(ParamWithName(true, &m_Pi2Slices, prefix + "pie_pi2_slices"));//Precalc. } private: @@ -2326,7 +2326,7 @@ protected: m_Params.push_back(ParamWithName(&m_Power, prefix + "ngon_power", 3)); m_Params.push_back(ParamWithName(&m_Circle, prefix + "ngon_circle", 1)); m_Params.push_back(ParamWithName(&m_Corners, prefix + "ngon_corners", 2)); - m_Params.push_back(ParamWithName(true, &m_CSides, prefix + "ngon_csides")); + m_Params.push_back(ParamWithName(true, &m_CSides, prefix + "ngon_csides"));//Precalc. m_Params.push_back(ParamWithName(true, &m_CSidesInv, prefix + "ngon_csides_inv")); m_Params.push_back(ParamWithName(true, &m_CPower, prefix + "ngon_cpower")); } @@ -2986,7 +2986,7 @@ public: ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); - string rot = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. + string rot = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string twist = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string sinAdd = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc. string cosAdd = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3037,7 +3037,7 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_Rot, prefix + "disc2_rot"));//Params. + m_Params.push_back(ParamWithName(&m_Rot, prefix + "disc2_rot")); m_Params.push_back(ParamWithName(&m_Twist, prefix + "disc2_twist")); m_Params.push_back(ParamWithName(true, &m_SinAdd, prefix + "disc2_sin_add"));//Precalc. m_Params.push_back(ParamWithName(true, &m_CosAdd, prefix + "disc2_cos_add")); @@ -3045,7 +3045,7 @@ protected: } private: - T m_Rot;//Params. + T m_Rot; T m_Twist; T m_SinAdd;//Precalc. T m_CosAdd; @@ -3087,7 +3087,7 @@ public: ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); - string m = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. + string m = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string n1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string n2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string n3 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3131,7 +3131,7 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_M, prefix + "super_shape_m"));//Params. + m_Params.push_back(ParamWithName(&m_M, prefix + "super_shape_m")); m_Params.push_back(ParamWithName(&m_N1, prefix + "super_shape_n1", 1)); m_Params.push_back(ParamWithName(&m_N2, prefix + "super_shape_n2", 1)); m_Params.push_back(ParamWithName(&m_N3, prefix + "super_shape_n3", 1)); @@ -3142,7 +3142,7 @@ protected: } private: - T m_M;//Params. + T m_M; T m_N1; T m_N2; T m_N3; @@ -3493,14 +3493,14 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_X, prefix + "bent2_x", 1));//Params. + m_Params.push_back(ParamWithName(&m_X, prefix + "bent2_x", 1)); m_Params.push_back(ParamWithName(&m_Y, prefix + "bent2_y", 1)); m_Params.push_back(ParamWithName(true, &m_Vx, prefix + "bent2_vx"));//Precalc. m_Params.push_back(ParamWithName(true, &m_Vy, prefix + "bent2_vy")); } private: - T m_X;//Params. + T m_X; T m_Y; T m_Vx;//Precalc. T m_Vy; @@ -3649,14 +3649,14 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_Shift, prefix + "bipolar_shift"));//Params. + m_Params.push_back(ParamWithName(&m_Shift, prefix + "bipolar_shift")); m_Params.push_back(ParamWithName(true, &m_S, prefix + "bipolar_s"));//Precalc. m_Params.push_back(ParamWithName(true, &m_V, prefix + "bipolar_v")); m_Params.push_back(ParamWithName(true, &m_V4, prefix + "bipolar_v4")); } private: - T m_Shift;//Params. + T m_Shift; T m_S;//Precalc. T m_V; T m_V4; @@ -4014,7 +4014,7 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_PowerR, prefix + "cpow_r", 1));//Params. + m_Params.push_back(ParamWithName(&m_PowerR, prefix + "cpow_r", 1)); m_Params.push_back(ParamWithName(&m_PowerI, prefix + "cpow_i")); m_Params.push_back(ParamWithName(&m_Power, prefix + "cpow_power", 1, eParamType::INTEGER_NONZERO)); m_Params.push_back(ParamWithName(true, &m_C, prefix + "cpow_c"));//Precalc. @@ -4023,7 +4023,7 @@ protected: } private: - T m_PowerR;//Params. + T m_PowerR; T m_PowerI; T m_Power; T m_C;//Precalc. @@ -4096,7 +4096,7 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_XAmp, prefix + "curve_xamp"));//Params. + m_Params.push_back(ParamWithName(&m_XAmp, prefix + "curve_xamp")); m_Params.push_back(ParamWithName(&m_YAmp, prefix + "curve_yamp")); m_Params.push_back(ParamWithName(&m_XLength, prefix + "curve_xlength", 1)); m_Params.push_back(ParamWithName(&m_YLength, prefix + "curve_ylength", 1)); @@ -4107,7 +4107,7 @@ protected: } private: - T m_XAmp;//Params. + T m_XAmp; T m_YAmp; T m_XLength; T m_YLength; @@ -4472,13 +4472,13 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_Beta, prefix + "escher_beta"));//Params. + m_Params.push_back(ParamWithName(&m_Beta, prefix + "escher_beta")); m_Params.push_back(ParamWithName(true, &m_C, prefix + "escher_beta_c"));//Precalc. m_Params.push_back(ParamWithName(true, &m_D, prefix + "escher_beta_d")); } private: - T m_Beta;//Params. + T m_Beta; T m_C;//Precalc. T m_D; }; @@ -4806,14 +4806,14 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_X, prefix + "modulus_x", 1));//Params. + m_Params.push_back(ParamWithName(&m_X, prefix + "modulus_x", 1)); m_Params.push_back(ParamWithName(&m_Y, prefix + "modulus_y", 1)); m_Params.push_back(ParamWithName(true, &m_XRange, prefix + "modulus_xrange"));//Precalc. m_Params.push_back(ParamWithName(true, &m_YRange, prefix + "modulus_yrange")); } private: - T m_X;//Params. + T m_X; T m_Y; T m_XRange;//Precalc. T m_YRange; @@ -4910,7 +4910,7 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_Separation, prefix + "oscilloscope_separation", 1));//Params. + m_Params.push_back(ParamWithName(&m_Separation, prefix + "oscilloscope_separation", 1)); m_Params.push_back(ParamWithName(&m_Frequency, prefix + "oscilloscope_frequency", T(M_PI))); m_Params.push_back(ParamWithName(&m_Amplitude, prefix + "oscilloscope_amplitude", 1)); m_Params.push_back(ParamWithName(&m_Damping, prefix + "oscilloscope_damping")); @@ -4918,7 +4918,7 @@ protected: } private: - T m_Separation;//Params. + T m_Separation; T m_Frequency; T m_Amplitude; T m_Damping; @@ -5015,7 +5015,7 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_Separation, prefix + "oscilloscope2_separation", 1, eParamType::REAL, 0));//Params. + m_Params.push_back(ParamWithName(&m_Separation, prefix + "oscilloscope2_separation", 1, eParamType::REAL, 0)); m_Params.push_back(ParamWithName(&m_FrequencyX, prefix + "oscilloscope2_frequencyx", T(M_PI))); m_Params.push_back(ParamWithName(&m_FrequencyY, prefix + "oscilloscope2_frequencyy", T(M_PI))); m_Params.push_back(ParamWithName(&m_Amplitude, prefix + "oscilloscope2_amplitude", 1)); @@ -5026,7 +5026,7 @@ protected: } private: - T m_Separation;//Params. + T m_Separation; T m_FrequencyX; T m_FrequencyY; T m_Amplitude; @@ -5391,7 +5391,7 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_X, prefix + "separation_x", 1));//Params. + m_Params.push_back(ParamWithName(&m_X, prefix + "separation_x", 1)); m_Params.push_back(ParamWithName(&m_XInside, prefix + "separation_xinside")); m_Params.push_back(ParamWithName(&m_Y, prefix + "separation_y", 1)); m_Params.push_back(ParamWithName(&m_YInside, prefix + "separation_yinside")); @@ -5400,7 +5400,7 @@ protected: } private: - T m_X;//Params. + T m_X; T m_XInside; T m_Y; T m_YInside; @@ -5481,14 +5481,14 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_XSize, prefix + "split_xsize", T(0.5)));//Params. + m_Params.push_back(ParamWithName(&m_XSize, prefix + "split_xsize", T(0.5))); m_Params.push_back(ParamWithName(&m_YSize, prefix + "split_ysize", T(0.5))); m_Params.push_back(ParamWithName(true, &m_XAng, prefix + "split_xang"));//Precalc. m_Params.push_back(ParamWithName(true, &m_YAng, prefix + "split_yang")); } private: - T m_XSize;//Params. + T m_XSize; T m_YSize; T m_XAng;//Precalc. T m_YAng; @@ -5701,7 +5701,7 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_Angle, prefix + "wedge_angle", T(M_PI_2)));//Params. + m_Params.push_back(ParamWithName(&m_Angle, prefix + "wedge_angle", T(M_PI_2))); m_Params.push_back(ParamWithName(&m_Hole, prefix + "wedge_hole")); m_Params.push_back(ParamWithName(&m_Count, prefix + "wedge_count", 2, eParamType::INTEGER, 1)); m_Params.push_back(ParamWithName(&m_Swirl, prefix + "wedge_swirl")); @@ -5709,7 +5709,7 @@ protected: } private: - T m_Angle;//Params. + T m_Angle; T m_Hole; T m_Count; T m_Swirl; @@ -5749,7 +5749,7 @@ public: ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); - string angle = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. + string angle = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string count = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string dist = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -5790,7 +5790,7 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_Angle, prefix + "wedge_julia_angle"));//Params. + m_Params.push_back(ParamWithName(&m_Angle, prefix + "wedge_julia_angle")); m_Params.push_back(ParamWithName(&m_Count, prefix + "wedge_julia_count", 1)); m_Params.push_back(ParamWithName(&m_Power, prefix + "wedge_julia_power", 1)); m_Params.push_back(ParamWithName(&m_Dist, prefix + "wedge_julia_dist")); @@ -5800,7 +5800,7 @@ protected: } private: - T m_Angle;//Params. + T m_Angle; T m_Count; T m_Power; T m_Dist; @@ -5890,7 +5890,7 @@ protected: m_Params.push_back(ParamWithName(&m_Count, prefix + "wedge_sph_count", 2, eParamType::INTEGER, 1)); m_Params.push_back(ParamWithName(&m_Hole, prefix + "wedge_sph_hole")); m_Params.push_back(ParamWithName(&m_Swirl, prefix + "wedge_sph_swirl")); - m_Params.push_back(ParamWithName(true, &m_C12Pi, prefix + "wedge_sph_c1_2pi")); + m_Params.push_back(ParamWithName(true, &m_C12Pi, prefix + "wedge_sph_c1_2pi"));//Precalc. m_Params.push_back(ParamWithName(true, &m_CompFac, prefix + "wedge_sph_comp_fac")); } @@ -7342,12 +7342,12 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_Spread, prefix + "flux_spread"));//Params. + m_Params.push_back(ParamWithName(&m_Spread, prefix + "flux_spread")); m_Params.push_back(ParamWithName(true, &m_Spr, prefix + "flux_spr"));//Precalc. } private: - T m_Spread;//Params. + T m_Spread; T m_Spr;//Precalc. }; diff --git a/Source/Ember/Variations02.h b/Source/Ember/Variations02.h index eb16e63..5a006e4 100644 --- a/Source/Ember/Variations02.h +++ b/Source/Ember/Variations02.h @@ -116,7 +116,7 @@ protected: m_Params.push_back(ParamWithName(&m_N, prefix + "epispiral_n", 6)); m_Params.push_back(ParamWithName(&m_Thickness, prefix + "epispiral_thickness")); m_Params.push_back(ParamWithName(&m_Holes, prefix + "epispiral_holes", 1)); - m_Params.push_back(ParamWithName(true, &m_ThicknessWeight, prefix + "epispiral_thickness_weight")); //Precalc. + m_Params.push_back(ParamWithName(true, &m_ThicknessWeight, prefix + "epispiral_thickness_weight"));//Precalc. m_Params.push_back(ParamWithName(true, &m_HolesWeight, prefix + "epispiral_holes_weight")); } @@ -5862,7 +5862,7 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(true, &m_Weight01, prefix + "bisplit_weight01"));//Precalc only. + m_Params.push_back(ParamWithName(true, &m_Weight01, prefix + "bisplit_weight01"));//Precalcs only, no params. } private: diff --git a/Source/Ember/Variations03.h b/Source/Ember/Variations03.h index 008da3e..a503c1c 100644 --- a/Source/Ember/Variations03.h +++ b/Source/Ember/Variations03.h @@ -584,7 +584,7 @@ private: *y = r * sinPhi + m_Y1; } - T m_Radius;//Params. + T m_Radius; T m_Radius1; T m_Phi1; T m_Thickness; @@ -742,7 +742,7 @@ private: *y = r * sinPhi; } - T m_Radius;//Params. + T m_Radius; T m_Thickness; T m_Contrast; T m_Pow; @@ -907,7 +907,7 @@ private: *y = r * sinPhi; } - T m_Radius;//Params. + T m_Radius; T m_Thickness; T m_Thickness2; T m_Contrast; @@ -1014,7 +1014,7 @@ protected: } private: - T m_Radius;//Params. + T m_Radius; T m_Contrast; T m_Pow; T m_X; @@ -1123,7 +1123,7 @@ protected: } private: - T m_Radius;//Params. + T m_Radius; T m_Thickness; T m_Contrast; T m_Pow; diff --git a/Source/Ember/Variations04.h b/Source/Ember/Variations04.h index 1cc0791..dc77e7c 100644 --- a/Source/Ember/Variations04.h +++ b/Source/Ember/Variations04.h @@ -1682,7 +1682,7 @@ private: return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) * am; } - T m_K;//Params. + T m_K; T m_Step; T m_Num; T m_XSeed; @@ -1804,7 +1804,7 @@ protected: m_Params.push_back(ParamWithName(&m_XThickness, prefix + "waffle_xthickness", T(0.5))); m_Params.push_back(ParamWithName(&m_YThickness, prefix + "waffle_ythickness", T(0.5))); m_Params.push_back(ParamWithName(&m_Rotation, prefix + "waffle_rotation")); - m_Params.push_back(ParamWithName(true, &m_SinR, prefix + "waffle_sinr")); + m_Params.push_back(ParamWithName(true, &m_SinR, prefix + "waffle_sinr"));//Precalc. m_Params.push_back(ParamWithName(true, &m_CosR, prefix + "waffle_cosr")); } @@ -2284,7 +2284,7 @@ protected: m_Params.push_back(ParamWithName(&m_Y, prefix + "circlecrop_y")); m_Params.push_back(ParamWithName(&m_ScatterArea, prefix + "circlecrop_scatter_area")); m_Params.push_back(ParamWithName(&m_Zero, prefix + "circlecrop_zero", 1, eParamType::INTEGER, 0, 1)); - m_Params.push_back(ParamWithName(true, &m_Ca, prefix + "circlecrop_ca")); + m_Params.push_back(ParamWithName(true, &m_Ca, prefix + "circlecrop_ca"));//Precalc. } private: @@ -2392,7 +2392,7 @@ protected: m_Params.push_back(ParamWithName(&m_Inner, prefix + "circlecrop2_inner", T(0.5))); m_Params.push_back(ParamWithName(&m_Outer, prefix + "circlecrop2_outer", 1)); m_Params.push_back(ParamWithName(&m_Zero, prefix + "circlecrop2_zero", 1, eParamType::INTEGER, 0, 1)); - m_Params.push_back(ParamWithName(true, &m_In, prefix + "circlecrop2_in")); + m_Params.push_back(ParamWithName(true, &m_In, prefix + "circlecrop2_in"));//Precalc. m_Params.push_back(ParamWithName(true, &m_Out, prefix + "circlecrop2_out")); m_Params.push_back(ParamWithName(true, &m_OutWeight, prefix + "circlecrop2_out_weight")); } @@ -2491,7 +2491,7 @@ protected: } private: - T m_Dist;//Params. + T m_Dist; T m_Power; T m_A; T m_B; @@ -3062,7 +3062,7 @@ protected: m_Params.push_back(ParamWithName(&m_Sx, prefix + "curl_sp_sx")); m_Params.push_back(ParamWithName(&m_Sy, prefix + "curl_sp_sy")); m_Params.push_back(ParamWithName(&m_Dc, prefix + "curl_sp_dc")); - m_Params.push_back(ParamWithName(true, &m_C2x2, prefix + "curl_sp_c2_x2")); + m_Params.push_back(ParamWithName(true, &m_C2x2, prefix + "curl_sp_c2_x2"));//Precalc. m_Params.push_back(ParamWithName(true, &m_DcAdjust, prefix + "curl_sp_dc_adjust")); m_Params.push_back(ParamWithName(true, &m_PowerInv, prefix + "curl_sp_power_inv")); } @@ -3191,7 +3191,7 @@ protected: m_Params.push_back(ParamWithName(&m_Rperiod, prefix + "heat_r_period", 1)); m_Params.push_back(ParamWithName(&m_Rphase, prefix + "heat_r_phase")); m_Params.push_back(ParamWithName(&m_Ramp, prefix + "heat_r_amp")); - m_Params.push_back(ParamWithName(true, &m_At, prefix + "heat_at")); + m_Params.push_back(ParamWithName(true, &m_At, prefix + "heat_at"));//Precalc. m_Params.push_back(ParamWithName(true, &m_Bt, prefix + "heat_bt")); m_Params.push_back(ParamWithName(true, &m_Ct, prefix + "heat_ct")); m_Params.push_back(ParamWithName(true, &m_Ap, prefix + "heat_ap")); @@ -4932,7 +4932,7 @@ protected: m_Params.push_back(ParamWithName(&m_CenterY, prefix + "gdoffs_center_y")); m_Params.push_back(ParamWithName(&m_Gamma, prefix + "gdoffs_gamma", 1, eParamType::INTEGER, 1, 6)); m_Params.push_back(ParamWithName(&m_Square, prefix + "gdoffs_square", 0, eParamType::INTEGER, 0, 1)); - m_Params.push_back(ParamWithName(true, &m_Dx, prefix + "gdoffs_dx")); + m_Params.push_back(ParamWithName(true, &m_Dx, prefix + "gdoffs_dx"));//Precalc. m_Params.push_back(ParamWithName(true, &m_Ax, prefix + "gdoffs_ax")); m_Params.push_back(ParamWithName(true, &m_Cx, prefix + "gdoffs_cx")); m_Params.push_back(ParamWithName(true, &m_Dy, prefix + "gdoffs_dyd")); @@ -4948,7 +4948,7 @@ private: static inline T GdoffsFosc(T p, T a) { return GdoffsFscl(-1 * std::cos(p * a * M_2PI)); } static inline T GdoffsFlip(T a, T b, T c) { return (c * (b - a) + a); } - T m_DeltaX;//Params. + T m_DeltaX; T m_DeltaY; T m_AreaX; T m_AreaY; @@ -5245,7 +5245,7 @@ protected: m_Params.push_back(ParamWithName(&m_D1, prefix + "trade_d1", 1, eParamType::REAL, 0, TMAX)); m_Params.push_back(ParamWithName(&m_R2, prefix + "trade_r2", 1, eParamType::REAL, EPS, TMAX)); m_Params.push_back(ParamWithName(&m_D2, prefix + "trade_d2", 1, eParamType::REAL, 0, TMAX)); - m_Params.push_back(ParamWithName(true, &m_C1, prefix + "trade_c1")); + m_Params.push_back(ParamWithName(true, &m_C1, prefix + "trade_c1"));//Precalc. m_Params.push_back(ParamWithName(true, &m_C2, prefix + "trade_c2")); } @@ -5326,7 +5326,7 @@ protected: m_Params.push_back(ParamWithName(&m_Re, prefix + "Juliac_re", 2)); m_Params.push_back(ParamWithName(&m_Im, prefix + "Juliac_im", 1)); m_Params.push_back(ParamWithName(&m_Dist, prefix + "Juliac_dist", 1)); - m_Params.push_back(ParamWithName(true, &m_HalfDist, prefix + "Juliac_half_dist")); + m_Params.push_back(ParamWithName(true, &m_HalfDist, prefix + "Juliac_half_dist"));//Precalc. m_Params.push_back(ParamWithName(true, &m_ReInv, prefix + "Juliac_re_inv")); m_Params.push_back(ParamWithName(true, &m_OneOverReInv, prefix + "Juliac_one_over_re_inv")); m_Params.push_back(ParamWithName(true, &m_Im100, prefix + "Juliac_im100")); diff --git a/Source/Ember/Variations05.h b/Source/Ember/Variations05.h index e0d73a1..b4edeb5 100644 --- a/Source/Ember/Variations05.h +++ b/Source/Ember/Variations05.h @@ -819,7 +819,7 @@ protected: m_Params.clear(); m_Params.push_back(ParamWithName(&m_Xpand, prefix + "cubic3D_xpand", T(0.25))); m_Params.push_back(ParamWithName(&m_Style, prefix + "cubic3D_style")); - m_Params.push_back(ParamWithName(true, &m_Fill, prefix + "cubic3D_fill")); //Precalc. + m_Params.push_back(ParamWithName(true, &m_Fill, prefix + "cubic3D_fill"));//Precalc. m_Params.push_back(ParamWithName(true, &m_Smooth, prefix + "cubic3D_smooth")); m_Params.push_back(ParamWithName(true, &m_SmoothStyle, prefix + "cubic3D_smooth_style")); m_Params.push_back(ParamWithName(true, &m_SmoothFill, prefix + "cubic3D_smooth_fill")); @@ -2043,7 +2043,7 @@ protected: m_Params.push_back(ParamWithName(&m_Y, prefix + "popcorn2_3D_y", T(0.1))); m_Params.push_back(ParamWithName(&m_Z, prefix + "popcorn2_3D_z", T(0.1))); m_Params.push_back(ParamWithName(&m_C, prefix + "popcorn2_3D_c", 3)); - m_Params.push_back(ParamWithName(true, &m_SinTanC, prefix + "popcorn2_3D_sintanc")); + m_Params.push_back(ParamWithName(true, &m_SinTanC, prefix + "popcorn2_3D_sintanc"));//Precalc. m_Params.push_back(ParamWithName(true, &m_HalfWeight, prefix + "popcorn2_3D_half_weight")); m_Params.push_back(ParamWithName(true, &m_Vv, prefix + "popcorn2_3D_vv")); } @@ -2225,7 +2225,7 @@ protected: m_Params.push_back(ParamWithName(&m_XWidth, prefix + "shredlin_xwidth", T(0.5), eParamType::REAL, -1, 1)); m_Params.push_back(ParamWithName(&m_YDistance, prefix + "shredlin_ydistance", 1, eParamType::REAL_NONZERO)); m_Params.push_back(ParamWithName(&m_YWidth, prefix + "shredlin_ywidth", T(0.5), eParamType::REAL, -1, 1)); - m_Params.push_back(ParamWithName(true, &m_Xw, prefix + "shredlin_xw")); + m_Params.push_back(ParamWithName(true, &m_Xw, prefix + "shredlin_xw"));//Precalc. m_Params.push_back(ParamWithName(true, &m_Yw, prefix + "shredlin_yw")); m_Params.push_back(ParamWithName(true, &m_1mX, prefix + "shredlin_1mx")); m_Params.push_back(ParamWithName(true, &m_1mY, prefix + "shredlin_1my")); @@ -2585,7 +2585,7 @@ protected: m_Params.push_back(ParamWithName(&m_Invert, prefix + "falloff_invert", 0, eParamType::INTEGER, 0, 1)); m_Params.push_back(ParamWithName(&m_Type, prefix + "falloff_type", 0, eParamType::INTEGER, 0, 2)); m_Params.push_back(ParamWithName(&m_BoxPow, prefix + "falloff_boxpow", 2, eParamType::INTEGER, 2, 32));//Original defaulted this to 0 which directly contradicts the specified range of 2-32. - m_Params.push_back(ParamWithName(true, &m_InternalScatter, prefix + "falloff_internal_scatter")); + m_Params.push_back(ParamWithName(true, &m_InternalScatter, prefix + "falloff_internal_scatter"));//Precalc. } private: @@ -3625,7 +3625,7 @@ public: //Creating Z factors relative to the planes. These will be added, whereas x and y will be assigned. //Original does += z *, so using z on the right side of = is intentional. if (m_MajPlane == 2) - //Boost is the separation distance between the two planes. + //Boost is the separation distance between the two planes. helper.Out.z = helper.In.z * T(0.5) * m_ZLift + (posNeg * m_Boost); else helper.Out.z = helper.In.z * T(0.5) * m_ZLift; diff --git a/Source/Ember/Variations06.h b/Source/Ember/Variations06.h index 5f7d75e..9ca885e 100644 --- a/Source/Ember/Variations06.h +++ b/Source/Ember/Variations06.h @@ -1752,7 +1752,7 @@ protected: m_Params.push_back(ParamWithName(&m_Blur, prefix + "crob_blur", 1, eParamType::INTEGER)); m_Params.push_back(ParamWithName(&m_RatioBlur, prefix + "crob_ratioBlur", T(0.5), eParamType::REAL, 0, 1)); m_Params.push_back(ParamWithName(&m_DirectBlur, prefix + "crob_directBlur", 2)); - m_Params.push_back(ParamWithName(true, &m_XInterval, prefix + "crob_xinterval")); + m_Params.push_back(ParamWithName(true, &m_XInterval, prefix + "crob_xinterval"));//Precalc. m_Params.push_back(ParamWithName(true, &m_YInterval, prefix + "crob_yinterval")); m_Params.push_back(ParamWithName(true, &m_XInt2, prefix + "crob_xint2")); m_Params.push_back(ParamWithName(true, &m_YInt2, prefix + "crob_yint2")); @@ -3889,7 +3889,7 @@ protected: m_Params.push_back(ParamWithName(&m_Distort, prefix + "crackle_distort")); m_Params.push_back(ParamWithName(&m_Scale, prefix + "crackle_scale", 1)); m_Params.push_back(ParamWithName(&m_Z, prefix + "crackle_z")); - m_Params.push_back(ParamWithName(true, &m_HalfCellSize, prefix + "crackle_half_cellsize")); + m_Params.push_back(ParamWithName(true, &m_HalfCellSize, prefix + "crackle_half_cellsize"));//Precalc. m_Params.push_back(ParamWithName(true, &(m_C[0][0].x), prefix + "crackle_cache", sizeof(m_C))); } @@ -4028,7 +4028,7 @@ protected: string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Cellsize, prefix + "crackle2_cellsize", 1, eParamType::REAL, T(0.0001))); - m_Params.push_back(ParamWithName(true, &m_OneOverCellsize, prefix + "crackle2_one_over_cellsize")); + m_Params.push_back(ParamWithName(true, &m_OneOverCellsize, prefix + "crackle2_one_over_cellsize"));//Precalc. } private: @@ -4876,7 +4876,7 @@ protected: m_Params.push_back(ParamWithName(&m_SuperN1, prefix + "w_super_n1", 1)); m_Params.push_back(ParamWithName(&m_SuperN2, prefix + "w_super_n2", 1)); m_Params.push_back(ParamWithName(&m_SuperN3, prefix + "w_super_n3", 1)); - m_Params.push_back(ParamWithName(true, &m_InvLituusA, prefix + "w_inv_lituus_a"));//Precalc + m_Params.push_back(ParamWithName(true, &m_InvLituusA, prefix + "w_inv_lituus_a"));//Precalc. m_Params.push_back(ParamWithName(true, &m_TanStarSlope, prefix + "w_tan_star_slope")); m_Params.push_back(ParamWithName(true, &m_HypergonD, prefix + "w_hypergon_d")); m_Params.push_back(ParamWithName(true, &m_SuperM4th, prefix + "w_super_m_4th")); @@ -5076,7 +5076,7 @@ protected: m_Params.push_back(ParamWithName(&m_SuperN1, prefix + "x_super_n1", 1)); m_Params.push_back(ParamWithName(&m_SuperN2, prefix + "x_super_n2", 1)); m_Params.push_back(ParamWithName(&m_SuperN3, prefix + "x_super_n3", 1)); - m_Params.push_back(ParamWithName(true, &m_InvLituusA, prefix + "x_inv_lituus_a"));//Precalc + m_Params.push_back(ParamWithName(true, &m_InvLituusA, prefix + "x_inv_lituus_a"));//Precalc. m_Params.push_back(ParamWithName(true, &m_TanStarSlope, prefix + "x_tan_star_slope")); m_Params.push_back(ParamWithName(true, &m_HypergonD, prefix + "x_hypergon_d")); m_Params.push_back(ParamWithName(true, &m_SuperM4th, prefix + "x_super_m_4th")); @@ -5276,7 +5276,7 @@ protected: m_Params.push_back(ParamWithName(&m_SuperN1, prefix + "y_super_n1", 1)); m_Params.push_back(ParamWithName(&m_SuperN2, prefix + "y_super_n2", 1)); m_Params.push_back(ParamWithName(&m_SuperN3, prefix + "y_super_n3", 1)); - m_Params.push_back(ParamWithName(true, &m_InvLituusA, prefix + "y_inv_lituus_a"));//Precalc + m_Params.push_back(ParamWithName(true, &m_InvLituusA, prefix + "y_inv_lituus_a"));//Precalc. m_Params.push_back(ParamWithName(true, &m_TanStarSlope, prefix + "y_tan_star_slope")); m_Params.push_back(ParamWithName(true, &m_HypergonD, prefix + "y_hypergon_d")); m_Params.push_back(ParamWithName(true, &m_SuperM4th, prefix + "y_super_m_4th")); @@ -5477,7 +5477,7 @@ protected: m_Params.push_back(ParamWithName(&m_SuperN1, prefix + "z_super_n1", 1)); m_Params.push_back(ParamWithName(&m_SuperN2, prefix + "z_super_n2", 1)); m_Params.push_back(ParamWithName(&m_SuperN3, prefix + "z_super_n3", 1)); - m_Params.push_back(ParamWithName(true, &m_InvLituusA, prefix + "z_inv_lituus_a"));//Precalc + m_Params.push_back(ParamWithName(true, &m_InvLituusA, prefix + "z_inv_lituus_a"));//Precalc. m_Params.push_back(ParamWithName(true, &m_TanStarSlope, prefix + "z_tan_star_slope")); m_Params.push_back(ParamWithName(true, &m_HypergonD, prefix + "z_hypergon_d")); m_Params.push_back(ParamWithName(true, &m_SuperM4th, prefix + "z_super_m_4th")); diff --git a/Source/Ember/Variations07.h b/Source/Ember/Variations07.h index f8eb9e6..46efb27 100644 --- a/Source/Ember/Variations07.h +++ b/Source/Ember/Variations07.h @@ -821,7 +821,7 @@ protected: m_Params.push_back(ParamWithName(&m_F, prefix + "pRose3D_f", 3)); m_Params.push_back(ParamWithName(&m_Wigsc, prefix + "pRose3D_wigsc")); m_Params.push_back(ParamWithName(&m_Offset, prefix + "pRose3D_offset")); - m_Params.push_back(ParamWithName(true, &m_Cycle, prefix + "pRose3D_cycle")); + m_Params.push_back(ParamWithName(true, &m_Cycle, prefix + "pRose3D_cycle"));//Precalc. m_Params.push_back(ParamWithName(true, &m_OptDir, prefix + "pRose3D_opt_dir")); m_Params.push_back(ParamWithName(true, &m_PetalsSign, prefix + "pRose3D_petals_sign")); m_Params.push_back(ParamWithName(true, &m_NumPetals, prefix + "pRose3D_num_petals")); @@ -954,7 +954,7 @@ protected: m_Params.clear(); m_Params.push_back(ParamWithName(&m_Base, prefix + "log_db_base", 1)); m_Params.push_back(ParamWithName(&m_FixPeriod, prefix + "log_db_fix_period", 1)); - m_Params.push_back(ParamWithName(true, &m_Denom, prefix + "log_db_denom")); + m_Params.push_back(ParamWithName(true, &m_Denom, prefix + "log_db_denom"));//Precalc. m_Params.push_back(ParamWithName(true, &m_FixPe, prefix + "log_db_fix_pe")); } private: @@ -4486,7 +4486,7 @@ protected: m_Params.push_back(ParamWithName(&m_Freq2, prefix + "vibration_freq2", 1)); m_Params.push_back(ParamWithName(&m_Amp2, prefix + "vibration_amp2", T(0.25))); m_Params.push_back(ParamWithName(&m_Phase2, prefix + "vibration_phase2", 0, eParamType::REAL_CYCLIC, 0, 1)); - m_Params.push_back(ParamWithName(true, &m_CosDir, prefix + "vibration_cos_dir")); + m_Params.push_back(ParamWithName(true, &m_CosDir, prefix + "vibration_cos_dir"));//Precalc. m_Params.push_back(ParamWithName(true, &m_SinDir, prefix + "vibration_sin_dir")); m_Params.push_back(ParamWithName(true, &m_CosTot, prefix + "vibration_cos_tot")); m_Params.push_back(ParamWithName(true, &m_SinTot, prefix + "vibration_sin_tot")); @@ -4701,7 +4701,7 @@ protected: m_Params.push_back(ParamWithName(&m_F2mfreq, prefix + "vibration2_fmfreq2")); m_Params.push_back(ParamWithName(&m_A2m , prefix + "vibration2_am2")); m_Params.push_back(ParamWithName(&m_A2mfreq, prefix + "vibration2_amfreq2")); - m_Params.push_back(ParamWithName(true, &m_CosDir, prefix + "vibration2_cos_dir")); + m_Params.push_back(ParamWithName(true, &m_CosDir, prefix + "vibration2_cos_dir"));//Precalc. m_Params.push_back(ParamWithName(true, &m_SinDir, prefix + "vibration2_sin_dir")); m_Params.push_back(ParamWithName(true, &m_ScaledFreq, prefix + "vibration2_scaled_freq")); m_Params.push_back(ParamWithName(true, &m_PhaseShift, prefix + "vibration2_phase_shift")); @@ -5202,8 +5202,8 @@ public: T z_scaled = z * std::sqrt(rand.Frand01()) * T(1.1547005383792515290182975610039);//2 / sqrt(3) T n = VarFuncs::HashShadertoy(xfinal, yfinal, m_Seed); T R = m_SizeOver2 * z_scaled * std::pow(n, m_Power); - helper.Out.x = std::cos(final_angle) * R + xfinal * m_Weight; - helper.Out.y = std::sin(final_angle) * R + yfinal * m_Weight; + helper.Out.x = (std::cos(final_angle) * R + xfinal) * m_Weight; + helper.Out.y = (std::sin(final_angle) * R + yfinal) * m_Weight; } helper.Out.z = DefaultZ(helper); @@ -5270,7 +5270,7 @@ protected: m_Params.push_back(ParamWithName(&m_Power, prefix + "hex_rand_power", 1)); m_Params.push_back(ParamWithName(&m_Density, prefix + "hex_rand_density", 1, eParamType::REAL, 0, 1)); m_Params.push_back(ParamWithName(&m_Seed, prefix + "hex_rand_seed", 1)); - m_Params.push_back(ParamWithName(true, &m_SizeOver2, prefix + "hex_rand_size_over_2")); + m_Params.push_back(ParamWithName(true, &m_SizeOver2, prefix + "hex_rand_size_over_2"));//Precalc. } private: @@ -5884,7 +5884,7 @@ protected: m_Params.push_back(ParamWithName(&m_SinYAmp, prefix + "unicorngaloshen_sin_y_amplitude", 2)); m_Params.push_back(ParamWithName(&m_SinYFreq, prefix + "unicorngaloshen_sin_y_freq", T(0.2))); m_Params.push_back(ParamWithName(&m_Mode, prefix + "unicorngaloshen_mode", 0, eParamType::INTEGER, 0, 4)); - m_Params.push_back(ParamWithName(true, &m_SinXFreqPi, prefix + "unicorngaloshen_sin_x_freq_pi")); + m_Params.push_back(ParamWithName(true, &m_SinXFreqPi, prefix + "unicorngaloshen_sin_x_freq_pi"));//Precalc. m_Params.push_back(ParamWithName(true, &m_SinYFreqPi, prefix + "unicorngaloshen_sin_y_freq_pi")); } @@ -7461,7 +7461,7 @@ protected: m_Params.push_back(ParamWithName(&m_Scaley, prefix + "waves23_scaley", T(0.05))); m_Params.push_back(ParamWithName(&m_Freqx, prefix + "waves23_freqx", T(7.0))); m_Params.push_back(ParamWithName(&m_Freqy, prefix + "waves23_freqy", T(13.0))); - m_Params.push_back(ParamWithName(true, &m_Freqx12Pi, prefix + "waves23_freqx_12pi")); + m_Params.push_back(ParamWithName(true, &m_Freqx12Pi, prefix + "waves23_freqx_12pi"));//Precalc. m_Params.push_back(ParamWithName(true, &m_Freqy12Pi, prefix + "waves23_freqy_12pi")); } diff --git a/Source/Ember/Variations08.h b/Source/Ember/Variations08.h index 8514072..4933f01 100644 --- a/Source/Ember/Variations08.h +++ b/Source/Ember/Variations08.h @@ -311,7 +311,124 @@ private: T m_WeightPrecalc; }; +/// +/// Circle_Rand. +/// A new version of CircleRand from Chaotica by tatasz. +/// +template +class Circle_RandVariation : public ParametricVariation +{ +public: + Circle_RandVariation(T weight = 1.0) : ParametricVariation("Circle_Rand", eVariationId::VAR_CIRCLE_RAND, weight) + { + Init(); + } + + PARVARCOPY(Circle_RandVariation) + + virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override + { + T a = rand.Frand01() * M_2PI; + T r = std::sqrt(rand.Frand01()); + T x = 2 * (Floor(rand.Frand01() * m_SideX * 2 + T(0.5)) - m_SideX); + T y = 2 * (Floor(rand.Frand01() * m_SideY * 2 + T(0.5)) - m_SideY); + T ret; + + if (VarFuncs::HashShadertoy(y, x, m_Seed) < m_Dens) + ret = m_Size * r * std::exp(std::log(VarFuncs::HashShadertoy(x, y, m_Seed)) * m_Power); + else + ret = 0; + + if (ret > 0) + { + helper.Out.x = m_Weight * (std::cos(a) * ret + x); + helper.Out.y = m_Weight * (std::sin(a) * ret + y); + } + + helper.Out.z = DefaultZ(helper); + } + + virtual string OpenCLString() const override + { + ostringstream ss, ss2; + intmax_t i = 0; + ss2 << "_" << XformIndexInEmber() << "]"; + string index = ss2.str(); + string weight = WeightDefineString(); + string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string size = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string density = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string seed = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string sidex = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string sidey = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + ss << "\t{\n" + << "\t\treal_t seed = " << seed << ";\n" + << "\t\treal_t sidex = " << sidex << ";\n" + << "\t\treal_t sidey = " << sidey << ";\n" + << "\t\treal_t a = MwcNext01(mwc) * M_2PI;\n" + << "\t\treal_t r = sqrt(MwcNext01(mwc));\n" + << "\t\treal_t x = 2 * (floor(MwcNext01(mwc) * sidex * 2 + (real_t)(0.5)) - sidex);\n" + << "\t\treal_t y = 2 * (floor(MwcNext01(mwc) * sidey * 2 + (real_t)(0.5)) - sidey);\n" + << "\n" + << "\t\treal_t ret;\n" + << "\n" + << "\t\tif (HashShadertoy(y, x, seed) < " << density << ")\n" + << "\t\t ret = " << size << " * r * exp(log(HashShadertoy(x, y, seed)) * " << power << ");\n" + << "\t\telse" + << "\t\t ret = (real_t)(0.0);" + << "\n" + << "\t\tif (ret > (real_t)(0.0))\n" + << "\t\t{" + << "\t\t vOut.x = " << weight << " * fma((real_t)(cos(a)), ret, x);\n" + << "\t\t vOut.y = " << weight << " * fma((real_t)(sin(a)), ret, y);\n" + << "\t\t}" + << "\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Fract", "HashShadertoy" }; + } + + virtual void Precalc() override + { + m_SideX = m_X * T(0.5); + m_SideY = m_Y * T(0.5); + } + +protected: + void Init() + { + string prefix = Prefix(); + m_Params.clear(); + m_Params.push_back(ParamWithName(&m_X, prefix + "Circle_Rand_X", 10)); + m_Params.push_back(ParamWithName(&m_Y, prefix + "Circle_Rand_Y", 10)); + m_Params.push_back(ParamWithName(&m_Size, prefix + "Circle_Rand_size", 1, eParamType::REAL, 0)); + m_Params.push_back(ParamWithName(&m_Power, prefix + "Circle_Rand_power", 1)); + m_Params.push_back(ParamWithName(&m_Dens, prefix + "Circle_Rand_density", 1, eParamType::REAL, 0, 1)); + m_Params.push_back(ParamWithName(&m_Seed, prefix + "Circle_Rand_seed", 1, eParamType::REAL)); + m_Params.push_back(ParamWithName(true, &m_SideX, prefix + "Circle_Rand_side_x"));//Precalc. + m_Params.push_back(ParamWithName(true, &m_SideY, prefix + "Circle_Rand_side_y")); + } + +private: + T m_X; + T m_Y; + T m_Size; + T m_Power; + T m_Dens; + T m_Seed; + T m_SideX;//Precalc. + T m_SideY; +}; + MAKEPREPOSTPARVAR(Gnarly, gnarly, GNARLY) MAKEPREPOSTPARVAR(Inkdrop, inkdrop, INKDROP) MAKEPREPOSTPARVAR(HexModulus, hex_modulus, HEX_MODULUS) +MAKEPREPOSTPARVAR(Circle_Rand, circle_rand, CIRCLE_RAND) } \ No newline at end of file diff --git a/Source/Ember/VariationsDC.h b/Source/Ember/VariationsDC.h index 248459e..f7216c6 100644 --- a/Source/Ember/VariationsDC.h +++ b/Source/Ember/VariationsDC.h @@ -52,7 +52,7 @@ public: ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); - string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. + string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string centerX = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string centerY = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string bdcs = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc. @@ -104,14 +104,14 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_CenterX, prefix + "dc_bubble_centerx"));//Params. + m_Params.push_back(ParamWithName(&m_CenterX, prefix + "dc_bubble_centerx")); m_Params.push_back(ParamWithName(&m_CenterY, prefix + "dc_bubble_centery")); m_Params.push_back(ParamWithName(&m_Scale, prefix + "dc_bubble_scale", 1)); m_Params.push_back(ParamWithName(true, &m_Bdcs, prefix + "dc_bubble_bdcs"));//Precalc. } private: - T m_CenterX;//Params. + T m_CenterX; T m_CenterY; T m_Scale; T m_Bdcs;//Precalc. @@ -152,7 +152,7 @@ public: ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); - string origin = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. + string origin = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string h = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc. ss << "\t{\n" << "\t\tint x0 = (MwcNext(mwc) & 1) ? -1 : 1;\n" @@ -180,12 +180,12 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_Origin, prefix + "dc_carpet_origin"));//Params. + m_Params.push_back(ParamWithName(&m_Origin, prefix + "dc_carpet_origin")); m_Params.push_back(ParamWithName(true, &m_H, prefix + "dc_carpet_h"));//Precalc. } private: - T m_Origin;//Params. + T m_Origin; T m_H;//Precalc. }; @@ -263,7 +263,7 @@ public: ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); - string cubeC1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. + string cubeC1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string cubeC2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string cubeC3 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string cubeC4 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -345,7 +345,7 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_DcCubeC1, prefix + "dc_cube_c1"));//Params. + m_Params.push_back(ParamWithName(&m_DcCubeC1, prefix + "dc_cube_c1")); m_Params.push_back(ParamWithName(&m_DcCubeC2, prefix + "dc_cube_c2")); m_Params.push_back(ParamWithName(&m_DcCubeC3, prefix + "dc_cube_c3")); m_Params.push_back(ParamWithName(&m_DcCubeC4, prefix + "dc_cube_c4")); @@ -363,7 +363,7 @@ protected: } private: - T m_DcCubeC1;//Params. + T m_DcCubeC1; T m_DcCubeC2; T m_DcCubeC3; T m_DcCubeC4; @@ -429,7 +429,7 @@ public: ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); - string offset = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. + string offset = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string angle = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -484,7 +484,7 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_Offset, prefix + "dc_cylinder_offset"));//Params. + m_Params.push_back(ParamWithName(&m_Offset, prefix + "dc_cylinder_offset")); m_Params.push_back(ParamWithName(&m_Angle, prefix + "dc_cylinder_angle"));//Original used a prefix of dc_cyl_, which is incompatible with Ember's design. m_Params.push_back(ParamWithName(&m_Scale, prefix + "dc_cylinder_scale", T(0.5))); m_Params.push_back(ParamWithName(&m_X, prefix + "dc_cylinder_x", T(0.125)));//Original used a prefix of cyl_, which is incompatible with Ember's design. @@ -497,7 +497,7 @@ protected: } private: - T m_Offset;//Params. + T m_Offset; T m_Angle; T m_Scale; T m_X; @@ -730,7 +730,7 @@ public: ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); - string offset = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. + string offset = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string angle = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string ldcs = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc. @@ -778,7 +778,7 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_Offset, prefix + "dc_linear_offset"));//Params. + m_Params.push_back(ParamWithName(&m_Offset, prefix + "dc_linear_offset")); m_Params.push_back(ParamWithName(&m_Angle, prefix + "dc_linear_angle")); m_Params.push_back(ParamWithName(&m_Scale, prefix + "dc_linear_scale", 1)); m_Params.push_back(ParamWithName(true, &m_Ldcs, prefix + "dc_linear_ldcs"));//Precalc. @@ -788,7 +788,7 @@ protected: } private: - T m_Offset;//Params. + T m_Offset; T m_Angle; T m_Scale; T m_Ldcs;//Precalc. @@ -901,7 +901,7 @@ public: ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); - string scatterArea = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. + string scatterArea = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string zeroEdges = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string a = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc. ss << "\t{\n" @@ -994,13 +994,13 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_ScatterArea, prefix + "dc_triangle_scatter_area", 0, eParamType::REAL, -1, 1));//Params. + m_Params.push_back(ParamWithName(&m_ScatterArea, prefix + "dc_triangle_scatter_area", 0, eParamType::REAL, -1, 1)); m_Params.push_back(ParamWithName(&m_ZeroEdges, prefix + "dc_triangle_zero_edges", 0, eParamType::INTEGER, 0, 1)); m_Params.push_back(ParamWithName(true, &m_A, prefix + "dc_triangle_a"));//Precalc. } private: - T m_ScatterArea;//Params. + T m_ScatterArea; T m_ZeroEdges; T m_A;//Precalc. }; @@ -1044,7 +1044,7 @@ public: ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); - string x0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. + string x0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string x1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string factor = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string overwrite = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc. @@ -1081,7 +1081,7 @@ protected: { string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_X0, prefix + "dc_ztransl_x0", 0, eParamType::REAL, 0, 1));//Params. + m_Params.push_back(ParamWithName(&m_X0, prefix + "dc_ztransl_x0", 0, eParamType::REAL, 0, 1)); m_Params.push_back(ParamWithName(&m_X1, prefix + "dc_ztransl_x1", 1, eParamType::REAL, 0, 1)); m_Params.push_back(ParamWithName(&m_Factor, prefix + "dc_ztransl_factor", 1)); m_Params.push_back(ParamWithName(&m_Overwrite, prefix + "dc_ztransl_overwrite", 1, eParamType::INTEGER, 0, 1)); @@ -1092,7 +1092,7 @@ protected: } private: - T m_X0;//Params. + T m_X0; T m_X1; T m_Factor; T m_Overwrite; @@ -1426,7 +1426,7 @@ protected: string prefix = Prefix(); m_Params.clear(); m_Params.reserve(15); - m_Params.push_back(ParamWithName(&m_Shape, prefix + "dc_perlin_shape", 0, eParamType::INTEGER, 0, 2));//Params. + m_Params.push_back(ParamWithName(&m_Shape, prefix + "dc_perlin_shape", 0, eParamType::INTEGER, 0, 2)); m_Params.push_back(ParamWithName(&m_Map, prefix + "dc_perlin_map", 0, eParamType::INTEGER, 0, 5)); m_Params.push_back(ParamWithName(&m_SelectCentre, prefix + "dc_perlin_select_centre", 0, eParamType::REAL, -1, 1)); m_Params.push_back(ParamWithName(&m_SelectRange, prefix + "dc_perlin_select_range", 1, eParamType::REAL, T(0.1), 2)); @@ -1439,11 +1439,11 @@ protected: m_Params.push_back(ParamWithName(&m_Freqs, prefix + "dc_perlin_freqs", 2)); m_Params.push_back(ParamWithName(&m_Z, prefix + "dc_perlin_z")); m_Params.push_back(ParamWithName(&m_SelectBailout, prefix + "dc_perlin_select_bailout", 10, eParamType::INTEGER, 2, 1000)); - m_Params.push_back(ParamWithName(true, &m_NotchBottom, prefix + "dc_perlin_notch_bottom")); + m_Params.push_back(ParamWithName(true, &m_NotchBottom, prefix + "dc_perlin_notch_bottom"));//Precalc. m_Params.push_back(ParamWithName(true, &m_NotchTop, prefix + "dc_perlin_notch_top")); } private: - T m_Shape;//Params. + T m_Shape; T m_Map; T m_SelectCentre; T m_SelectRange; @@ -1636,7 +1636,7 @@ protected: m_Params.push_back(ParamWithName(&m_Width, prefix + "pixel_flow_width", 200)); m_Params.push_back(ParamWithName(&m_Seed, prefix + "pixel_flow_seed", 42, eParamType::INTEGER)); m_Params.push_back(ParamWithName(&m_EnableDC, prefix + "pixel_flow_enable_dc", 0, eParamType::INTEGER, 0, 1)); - m_Params.push_back(ParamWithName(true, &m_Rad, prefix + "pixel_flow_rad")); + m_Params.push_back(ParamWithName(true, &m_Rad, prefix + "pixel_flow_rad"));//Precalc. } private: diff --git a/Source/Ember/XmlToEmber.cpp b/Source/Ember/XmlToEmber.cpp index a5877d6..c28bf3b 100644 --- a/Source/Ember/XmlToEmber.cpp +++ b/Source/Ember/XmlToEmber.cpp @@ -884,7 +884,7 @@ bool XmlToEmber::ParseEmberElementFromChaos(xmlNode* emberNode, Ember& cur xmlAttrPtr att; currentEmber.m_Palette.Clear();//Wipe out the current palette. att = emberNode->properties;//The top level element is a ember element, read the attributes of it and store them. - auto variationsfunc = [&](const string & prefix, const char* nodename, xmlNode * node, Xform& xf, std::vector& alliterweights) + auto variationsfunc = [&](const string& prefix, const char* nodename, xmlNode * node, Xform& xf, std::vector& alliterweights) { if (const auto transformsChildNode = GetChildNode(node, nodename)) { @@ -1352,7 +1352,7 @@ bool XmlToEmber::ParseEmberElementFromChaos(xmlNode* emberNode, Ember& cur { if (camChildNode->type == XML_ELEMENT_NODE) { - if (ParseAndAssignContent(camChildNode, "name", "rotate", currentEmber.m_Rotate)) { currentEmber.m_Rotate = NormalizeDeg180(currentEmber.m_Rotate); } + if (ParseAndAssignContent(camChildNode, "name", "rotate", currentEmber.m_Rotate)) { currentEmber.m_Rotate = NormalizeDeg360(currentEmber.m_Rotate); } else if (ParseAndAssignContent(camChildNode, "name", "sensor_width", sensorWidth)) { } else if (ParseAndAssignContent(camChildNode, "name", "pos", pos)) { @@ -1441,7 +1441,7 @@ bool XmlToEmber::ParseEmberElementFromChaos(xmlNode* emberNode, Ember& cur valv = CCX(valvalsnode->children->content); } - auto parsehsvfunc = [&](const std::string & knots, const std::string & vals, vector& vec) + auto parsehsvfunc = [&](const std::string& knots, const std::string& vals, vector& vec) { istringstream kstr(knots); istringstream vstr(vals); @@ -1563,7 +1563,7 @@ bool XmlToEmber::ParseEmberElement(xmlNode* emberNode, Ember& currentEmber //First parse out simple float reads. if (ParseAndAssign(curAtt->name, attStr, "time", currentEmber.m_Time, ret)) {} else if (ParseAndAssign(curAtt->name, attStr, "scale", currentEmber.m_PixelsPerUnit, ret)) { currentEmber.m_OrigPixPerUnit = currentEmber.m_PixelsPerUnit; } - else if (ParseAndAssign(curAtt->name, attStr, "rotate", currentEmber.m_Rotate, ret)) { currentEmber.m_Rotate = NormalizeDeg180(currentEmber.m_Rotate); } + else if (ParseAndAssign(curAtt->name, attStr, "rotate", currentEmber.m_Rotate, ret)) { currentEmber.m_Rotate = NormalizeDeg360(currentEmber.m_Rotate); } else if (ParseAndAssign(curAtt->name, attStr, "zoom", currentEmber.m_Zoom, ret)) { ClampGteRef(currentEmber.m_Zoom, 0); } else if (ParseAndAssign(curAtt->name, attStr, "cam_zoom", currentEmber.m_Zoom, ret)) { ClampGteRef(currentEmber.m_Zoom, 0); }//JWildfire uses cam_zoom. else if (ParseAndAssign(curAtt->name, attStr, "filter", currentEmber.m_SpatialFilterRadius, ret)) {} diff --git a/Source/EmberAnimate/EmberAnimate.cpp b/Source/EmberAnimate/EmberAnimate.cpp index 322ca5f..39a190f 100644 --- a/Source/EmberAnimate/EmberAnimate.cpp +++ b/Source/EmberAnimate/EmberAnimate.cpp @@ -496,8 +496,7 @@ bool EmberAnimate(int argc, _TCHAR* argv[], EmberOptions& opt) EmberStats stats; EmberImageComments comments; Ember centerEmber; - vector finalImages[2]; - std::thread writeThread; + ThreadedWriter threadedWriter(16); os.imbue(std::locale("")); //The conditions of this loop use atomics to synchronize when running on multiple GPUs. @@ -600,8 +599,10 @@ bool EmberAnimate(int argc, _TCHAR* argv[], EmberOptions& opt) } renderer->Reset(); + auto threadIndex = threadedWriter.Increment(); + auto threadImage = threadedWriter.GetImage(opt.ThreadedWrite() ? threadIndex : 0); - if ((renderer->Run(finalImages[finalImageIndex], localTime) != eRenderStatus::RENDER_OK) || renderer->Aborted() || finalImages[finalImageIndex].empty()) + if ((renderer->Run(*threadImage, localTime) != eRenderStatus::RENDER_OK) || renderer->Aborted() || threadImage->empty()) { cout << "Error: image rendering failed, aborting.\n"; renderer->DumpErrorReport();//Something went wrong, print errors. @@ -644,19 +645,19 @@ bool EmberAnimate(int argc, _TCHAR* argv[], EmberOptions& opt) //Run image writing in a thread. Although doing it this way duplicates the final output memory, it saves a lot of time //when running with OpenCL. Call join() to ensure the previous thread call has completed. - Join(writeThread); + //Join(writeThread); const auto threadVecIndex = finalImageIndex;//Cache before launching thread. if (opt.ThreadedWrite())//Copies of all but the first parameter are passed to saveFunc(), to avoid conflicting with those values changing when starting the render for the next image. { - writeThread = std::thread(saveFunc, std::ref(finalImages[threadVecIndex]), baseFilename, comments, renderer->FinalRasW(), renderer->FinalRasH(), renderer->NumChannels()); - finalImageIndex ^= 1;//Toggle the index. + auto writeThread = std::thread(saveFunc, std::ref(*threadImage), baseFilename, comments, renderer->FinalRasW(), renderer->FinalRasH(), renderer->NumChannels()); + threadedWriter.SetThread(threadIndex, writeThread); } else - saveFunc(finalImages[threadVecIndex], baseFilename, comments, renderer->FinalRasW(), renderer->FinalRasH(), renderer->NumChannels());//Will always use the first index, thereby not requiring more memory. + saveFunc(*threadImage, baseFilename, comments, renderer->FinalRasW(), renderer->FinalRasH(), renderer->NumChannels());//Will always use the first index, thereby not requiring more memory. } - Join(writeThread);//One final check to make sure all writing is done before exiting this thread. + threadedWriter.JoinAll();//One final check to make sure all writing is done before exiting this thread. }; threadVec.reserve(renderers.size()); diff --git a/Source/EmberCommon/EmberCommon.h b/Source/EmberCommon/EmberCommon.h index 1d4c7e0..2fbc892 100644 --- a/Source/EmberCommon/EmberCommon.h +++ b/Source/EmberCommon/EmberCommon.h @@ -928,6 +928,51 @@ static bool FileExists(const string& filename, bool notempty = true) return false; } + +class ThreadedWriter +{ +public: + ThreadedWriter(int _size) + { + m_Size = _size; + m_WriteThreads.resize(m_Size); + m_FinalImages.resize(m_Size); + } + + size_t Current() + { + return m_CurrentIndex % m_Size; + } + + size_t Increment() + { + auto ret = ++m_CurrentIndex % m_Size; + Join(m_WriteThreads[ret]); + return ret; + } + + vector* GetImage(size_t i) + { + return &m_FinalImages[i]; + } + + void SetThread(size_t i, std::thread& th) + { + Join(m_WriteThreads[i]); + m_WriteThreads[i] = std::move(th); + } + + void JoinAll() + { + Join(m_WriteThreads); + } + +private: + size_t m_Size = 0; + size_t m_CurrentIndex = 0; + std::vector m_WriteThreads; + std::vector> m_FinalImages; +}; } /// diff --git a/Source/EmberCommon/JpegUtils.h b/Source/EmberCommon/JpegUtils.h index 16c4a82..2001e9d 100644 --- a/Source/EmberCommon/JpegUtils.h +++ b/Source/EmberCommon/JpegUtils.h @@ -160,34 +160,9 @@ static bool WritePng(const char* filename, unsigned char* image, size_t width, s { png_structp png_ptr; png_infop info_ptr; - png_text text[PNG_COMMENT_MAX]; size_t i = 0; constexpr glm::uint16 testbe = 1; vector rows(height); - text[0].compression = PNG_TEXT_COMPRESSION_NONE; - text[0].key = const_cast("ember_version"); - text[0].text = const_cast(EmberVersion()); - text[1].compression = PNG_TEXT_COMPRESSION_NONE; - text[1].key = const_cast("ember_nickname"); - text[1].text = const_cast(nick.c_str()); - text[2].compression = PNG_TEXT_COMPRESSION_NONE; - text[2].key = const_cast("ember_url"); - text[2].text = const_cast(url.c_str()); - text[3].compression = PNG_TEXT_COMPRESSION_NONE; - text[3].key = const_cast("ember_id"); - text[3].text = const_cast(id.c_str()); - text[4].compression = PNG_TEXT_COMPRESSION_NONE; - text[4].key = const_cast("ember_error_rate"); - text[4].text = const_cast(comments.m_Badvals.c_str()); - text[5].compression = PNG_TEXT_COMPRESSION_NONE; - text[5].key = const_cast("ember_samples"); - text[5].text = const_cast(comments.m_NumIters.c_str()); - text[6].compression = PNG_TEXT_COMPRESSION_NONE; - text[6].key = const_cast("ember_time"); - text[6].text = const_cast(comments.m_Runtime.c_str()); - text[7].compression = PNG_TEXT_COMPRESSION_zTXt; - text[7].key = const_cast("ember_genome"); - text[7].text = const_cast(comments.m_Genome.c_str()); for (i = 0; i < height; i++) rows[i] = image + i * width * 4 * bytesPerChannel; @@ -209,9 +184,37 @@ static bool WritePng(const char* filename, unsigned char* image, size_t width, s PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + //png_set_filter(png_ptr, 0, PNG_NO_FILTERS); if (enableComments == 1) + { + png_text text[PNG_COMMENT_MAX]; + text[0].compression = PNG_TEXT_COMPRESSION_NONE; + text[0].key = const_cast("ember_version"); + text[0].text = const_cast(EmberVersion()); + text[1].compression = PNG_TEXT_COMPRESSION_NONE; + text[1].key = const_cast("ember_nickname"); + text[1].text = const_cast(nick.c_str()); + text[2].compression = PNG_TEXT_COMPRESSION_NONE; + text[2].key = const_cast("ember_url"); + text[2].text = const_cast(url.c_str()); + text[3].compression = PNG_TEXT_COMPRESSION_NONE; + text[3].key = const_cast("ember_id"); + text[3].text = const_cast(id.c_str()); + text[4].compression = PNG_TEXT_COMPRESSION_NONE; + text[4].key = const_cast("ember_error_rate"); + text[4].text = const_cast(comments.m_Badvals.c_str()); + text[5].compression = PNG_TEXT_COMPRESSION_NONE; + text[5].key = const_cast("ember_samples"); + text[5].text = const_cast(comments.m_NumIters.c_str()); + text[6].compression = PNG_TEXT_COMPRESSION_NONE; + text[6].key = const_cast("ember_time"); + text[6].text = const_cast(comments.m_Runtime.c_str()); + text[7].compression = PNG_TEXT_COMPRESSION_zTXt; + text[7].key = const_cast("ember_genome"); + text[7].text = const_cast(comments.m_Genome.c_str()); png_set_text(png_ptr, info_ptr, text, PNG_COMMENT_MAX); + } png_write_info(png_ptr, info_ptr); diff --git a/Source/Fractorium/AboutDialog.ui b/Source/Fractorium/AboutDialog.ui index 03dfac0..a4c0c51 100644 --- a/Source/Fractorium/AboutDialog.ui +++ b/Source/Fractorium/AboutDialog.ui @@ -61,7 +61,7 @@ QFrame::NoFrame - <html><head/><body><p align="center"><span style=" font-size:10pt;">Fractorium 23.23.8.1</span></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=" font-size:10pt; text-decoration: underline; color:#0000ff;">fractorium.com</span></a></p></body></html> + <html><head/><body><p align="center"><span style=" font-size:10pt;">Fractorium 23.23.8.100</span></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=" font-size:10pt; text-decoration: underline; color:#0000ff;">fractorium.com</span></a></p></body></html> Qt::RichText diff --git a/Source/Fractorium/CurvesGraphicsView.cpp b/Source/Fractorium/CurvesGraphicsView.cpp index beb161e..e4672c6 100644 --- a/Source/Fractorium/CurvesGraphicsView.cpp +++ b/Source/Fractorium/CurvesGraphicsView.cpp @@ -219,7 +219,7 @@ void CurvesGraphicsView::mousePressEvent(QMouseEvent* e) { QGraphicsView::mousePressEvent(e); - if (e != nullptr) + if (e == nullptr) return; const auto thresh = devicePixelRatioF() * 4; diff --git a/Source/Fractorium/FinalRenderEmberController.cpp b/Source/Fractorium/FinalRenderEmberController.cpp index f4ef2a5..e14f711 100644 --- a/Source/Fractorium/FinalRenderEmberController.cpp +++ b/Source/Fractorium/FinalRenderEmberController.cpp @@ -17,6 +17,12 @@ FinalRenderEmberControllerBase::FinalRenderEmberControllerBase(FractoriumFinalRe m_Settings = FractoriumSettings::DefInstance(); } +template +FinalRenderEmberController::~FinalRenderEmberController() +{ + m_ThreadedWriter.JoinAll(); +} + /// /// Cancel the render by calling Abort(). /// This will block until the cancelling is actually finished. @@ -91,7 +97,6 @@ void FinalRenderEmberControllerBase::Output(const QString& s) QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderTextOutput, "append", Qt::QueuedConnection, Q_ARG(const QString&, s)); } - /// /// Render a single ember. /// @@ -103,36 +108,43 @@ template bool FinalRenderEmberController::RenderSingleEmber(Ember& ember, bool fullRender, size_t& stripForProgress) { if (!m_Renderer.get()) - { return false; - } - auto ret = true; + auto threadIndex = fullRender ? m_ThreadedWriter.Increment() : m_ThreadedWriter.Current(); + auto threadImage = m_ThreadedWriter.GetImage(threadIndex); ember.m_TemporalSamples = 1;//No temporal sampling. m_Renderer->SetEmber(ember, fullRender ? eProcessAction::FULL_RENDER : eProcessAction::KEEP_ITERATING, /* updatePointer */ true); - m_Renderer->PrepFinalAccumVector(m_FinalImage);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run(). + m_Renderer->PrepFinalAccumVector(*threadImage);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run(). m_Stats.Clear(); m_RenderTimer.Tic();//Toc() is called in RenderComplete(). - StripsRender(m_Renderer.get(), ember, m_FinalImage, 0, m_GuiState.m_Strips, m_GuiState.m_YAxisUp, + StripsRender(m_Renderer.get(), ember, *threadImage, 0, m_GuiState.m_Strips, m_GuiState.m_YAxisUp, [&](size_t strip) { stripForProgress = strip; },//Pre strip. [&](size_t strip) { m_Stats += m_Renderer->Stats(); },//Post strip. [&](size_t strip)//Error. { Output("Rendering failed.\n"); m_Fractorium->ErrorReportToQTextEdit(m_Renderer->ErrorReport(), m_FinalRenderDialog->ui.FinalRenderTextOutput, false);//Internally calls invoke. - ret = false; + m_Run = false; }, [&](Ember& finalEmber) { m_FinishedImageCount.fetch_add(1); - - if (SaveCurrentRender(finalEmber) == "") - m_Run = ret = false; - + auto stats = m_Renderer->Stats(); + auto comments = m_Renderer->ImageComments(stats, 0, true); + auto rasw = m_Renderer->FinalRasW(); + auto rash = m_Renderer->FinalRasH(); + auto png16 = m_FinalRenderDialog->Png16Bit(); + auto transparency = m_FinalRenderDialog->Transparency(); RenderComplete(finalEmber); HandleFinishedProgress(); + auto writeThread = std::thread([ = ](Ember threadEmber)//Pass ember by value. + { + if (SaveCurrentRender(threadEmber, comments, *threadImage, rasw, rash, png16, transparency) == "") + m_Run = false; + }, finalEmber); + m_ThreadedWriter.SetThread(threadIndex, writeThread); });//Final strip. - return ret; + return m_Run; } /// @@ -146,22 +158,17 @@ template bool FinalRenderEmberController::RenderSingleEmberFromSeries(std::atomic* atomfTime, size_t index) { if (m_Renderers.size() <= index) - { return false; - } - size_t ftime; - size_t finalImageIndex = 0; - std::thread writeThread; - vector finalImages[2]; - EmberStats stats; - EmberImageComments comments; - Timing renderTimer; const auto renderer = m_Renderers[index].get(); if (renderer == nullptr) return false; + size_t ftime; + Timing renderTimer; + ThreadedWriter localThreadedWriter(16);//Use a local one for each renderer in a sequence instead of the class member. + //Render each image, cancelling if m_Run ever gets set to false. //The conditions of this loop use atomics to synchronize when running on multiple GPUs. //The order is reversed from the usual loop: rather than compare and increment the counter, @@ -176,9 +183,12 @@ bool FinalRenderEmberController::RenderSingleEmberFromSeries(std::atomicm_Name))); renderer->Reset();//Have to manually set this since the ember is not set each time through. renderTimer.Tic();//Toc() is called in RenderComplete(). + auto threadIndex = localThreadedWriter.Increment(); + auto threadImage = localThreadedWriter.GetImage(threadIndex); + //renderer->PrepFinalAccumVector(threadImage); //Can't use strips render here. Run() must be called directly for animation. - if (renderer->Run(finalImages[finalImageIndex], T(ftime)) != eRenderStatus::RENDER_OK) + if (renderer->Run(*threadImage, T(ftime)) != eRenderStatus::RENDER_OK) { Output("Rendering failed.\n"); m_Fractorium->ErrorReportToQTextEdit(renderer->ErrorReport(), m_FinalRenderDialog->ui.FinalRenderTextOutput, false);//Internally calls invoke. @@ -188,31 +198,33 @@ bool FinalRenderEmberController::RenderSingleEmberFromSeries(std::atomicStats(); - comments = renderer->ImageComments(stats, 0, true); - writeThread = std::thread([&](size_t tempTime, size_t threadFinalImageIndex) - { - if (SaveCurrentRender(*m_EmberFile.Get(tempTime), - comments,//These all don't change during the renders, so it's ok to access them in the thread. - finalImages[threadFinalImageIndex], - renderer->FinalRasW(), - renderer->FinalRasH(), - m_FinalRenderDialog->Png16Bit(), - m_FinalRenderDialog->Transparency()) == "") - m_Run = false; - }, ftime, finalImageIndex); + auto stats = renderer->Stats(); + auto comments = renderer->ImageComments(stats, 0, true); + auto w = renderer->FinalRasW(); + auto h = renderer->FinalRasH(); + auto ember = m_EmberFile.Get(ftime); m_FinishedImageCount.fetch_add(1); - RenderComplete(*m_EmberFile.Get(ftime), stats, renderTimer); + RenderComplete(*ember, stats, renderTimer); if (!index)//Only first device has a progress callback, so it also makes sense to only manually set the progress on the first device as well. HandleFinishedProgress(); - } - finalImageIndex ^= 1;//Toggle the index. + auto writeThread = std::thread([ = ]() + { + if (SaveCurrentRender(*ember, + comments,//These all don't change during the renders, so it's ok to access them in the thread. + *threadImage, + w, + h, + m_FinalRenderDialog->Png16Bit(), + m_FinalRenderDialog->Transparency()) == "") + m_Run = false; + }); + localThreadedWriter.SetThread(threadIndex, writeThread); + } } - Join(writeThread);//One final check to make sure all writing is done before exiting this thread. + localThreadedWriter.JoinAll();//One final check to make sure all writing is done before exiting this thread. return m_Run; } @@ -223,7 +235,8 @@ bool FinalRenderEmberController::RenderSingleEmberFromSeries(std::atomicPointer to the final render dialog template FinalRenderEmberController::FinalRenderEmberController(FractoriumFinalRenderDialog* finalRender) - : FinalRenderEmberControllerBase(finalRender) + : FinalRenderEmberControllerBase(finalRender), + m_ThreadedWriter(16) { m_FinalPreviewRenderer = make_unique>(this); //The main rendering function which will be called in a Qt thread. @@ -321,7 +334,7 @@ FinalRenderEmberController::FinalRenderEmberController(FractoriumFinalRenderD break; Output("Image " + ToString(m_FinishedImageCount.load() + 1) + ":\n" + ComposePath(QString::fromStdString(it.m_Name))); - RenderSingleEmber(it, /* fullRender */ true, currentStripForProgress); + RenderSingleEmber(it, true, currentStripForProgress); } } else @@ -335,18 +348,21 @@ FinalRenderEmberController::FinalRenderEmberController(FractoriumFinalRenderD m_ImageCount = 1; m_Ember->m_TemporalSamples = 1; m_Fractorium->m_Controller->ParamsToEmber(*m_Ember, true);//Update color and filter params from the main window controls, which only affect the filter and/or final accumulation stage. - RenderSingleEmber(*m_Ember, /* fullRender= */ !isBump, currentStripForProgress); + RenderSingleEmber(*m_Ember, !isBump, currentStripForProgress); } else { Output("No renderer present, aborting."); } + m_ThreadedWriter.JoinAll(); const QString totalTimeString = m_Run ? "All renders completed in: " + QString::fromStdString(m_TotalTimer.Format(m_TotalTimer.Toc())) + "." : "Render aborted."; Output(totalTimeString); QFile::remove(backup); QMetaObject::invokeMethod(m_FinalRenderDialog, "Pause", Qt::QueuedConnection, Q_ARG(bool, false)); + QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderSaveAgainAsButton, "setEnabled", Qt::QueuedConnection, Q_ARG(bool, !doAll && m_Renderer.get()));//Can do save again with variable number of strips. + QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderBumpQualityStartButton, "setEnabled", Qt::QueuedConnection, Q_ARG(bool, !doAll && m_Renderer.get() && m_GuiState.m_Strips == 1)); m_Run = false; }; } @@ -815,6 +831,8 @@ QString FinalRenderEmberController::SaveCurrentAgain() minde != m_Ember->m_MinRadDE || maxde != m_Ember->m_MaxRadDE || curvede != m_Ember->m_CurveDE; + auto threadIndex = m_ThreadedWriter.Current(); + auto threadImage = m_ThreadedWriter.GetImage(threadIndex); //This is sort of a hack outside of the normal rendering process above. if (dofilterandaccum || @@ -831,14 +849,18 @@ QString FinalRenderEmberController::SaveCurrentAgain() m_Ember->m_TemporalSamples = 1; m_Renderer->m_ProgressParameter = reinterpret_cast(¤tStripForProgress);//Need to reset this because it was set to a local variable within the render thread. m_Renderer->SetEmber(*m_Ember, dofilterandaccum ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY); - m_Renderer->Run(m_FinalImage, 0, m_GuiState.m_Strips, m_GuiState.m_YAxisUp); + m_Renderer->Run(*threadImage, 0, m_GuiState.m_Strips, m_GuiState.m_YAxisUp); m_FinishedImageCount.fetch_add(1); HandleFinishedProgress(); m_Run = false; } + + auto stats = m_Renderer->Stats(); + auto comments = m_Renderer->ImageComments(stats, 0, true); + return SaveCurrentRender(*m_Ember, comments, *threadImage, m_Renderer->FinalRasW(), m_Renderer->FinalRasH(), m_FinalRenderDialog->Png16Bit(), m_FinalRenderDialog->Transparency()); } - return SaveCurrentRender(*m_Ember); + return ""; } /// @@ -941,8 +963,6 @@ void FinalRenderEmberController::HandleFinishedProgress() QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderTotalProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, static_cast((float(finishedCountCached) / static_cast(m_ImageCount)) * 100))); QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderImageCountLabel, "setText", Qt::QueuedConnection, Q_ARG(const QString&, ToString(finishedCountCached) + " / " + ToString(m_ImageCount))); - QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderSaveAgainAsButton, "setEnabled", Qt::QueuedConnection, Q_ARG(bool, !doAll && m_Renderer.get()));//Can do save again with variable number of strips. - QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderBumpQualityStartButton, "setEnabled", Qt::QueuedConnection, Q_ARG(bool, !doAll && m_Renderer.get() && m_GuiState.m_Strips == 1)); } /// diff --git a/Source/Fractorium/FinalRenderEmberController.h b/Source/Fractorium/FinalRenderEmberController.h index 6d69289..3edba1d 100644 --- a/Source/Fractorium/FinalRenderEmberController.h +++ b/Source/Fractorium/FinalRenderEmberController.h @@ -106,7 +106,7 @@ class FinalRenderEmberController : public FinalRenderEmberControllerBase public: FinalRenderEmberController(FractoriumFinalRenderDialog* finalRender); - virtual ~FinalRenderEmberController() { } + virtual ~FinalRenderEmberController(); //Virtual functions overridden from FractoriumEmberControllerBase. void SetEmberFile(const EmberFile& emberFile, bool move) override; @@ -159,6 +159,7 @@ protected: EmberToXml m_XmlWriter; unique_ptr> m_FinalPreviewRenderer; vector>> m_Renderers; + ThreadedWriter m_ThreadedWriter; }; /// diff --git a/Source/Fractorium/Fractorium.cpp b/Source/Fractorium/Fractorium.cpp index cbe1fc2..be8ec6a 100644 --- a/Source/Fractorium/Fractorium.cpp +++ b/Source/Fractorium/Fractorium.cpp @@ -69,7 +69,7 @@ Fractorium::Fractorium(QWidget* p) m_VarDialog = new FractoriumVariationsDialog(this); m_AboutDialog = new FractoriumAboutDialog(this); //Put the about dialog in the screen center. - m_AboutDialogCentered = false; + m_AboutDialogCentered = false; connect(m_ColorDialog, SIGNAL(colorSelected(const QColor&)), this, SLOT(OnColorSelected(const QColor&)), Qt::QueuedConnection); m_XformComboColors[i++] = QColor(0XFF, 0X00, 0X00); m_XformComboColors[i++] = QColor(0XCC, 0XCC, 0X00); @@ -755,11 +755,11 @@ void Fractorium::showEvent(QShowEvent* e) emit qGuiApp->focusWindowChanged(windowHandle()); QMainWindow::showEvent(e); - if(!m_AboutDialogCentered) - { - m_AboutDialogCentered = true; - QTimer::singleShot(100, this, SLOT(WindowShown())); - } + if (!m_AboutDialogCentered) + { + m_AboutDialogCentered = true; + QTimer::singleShot(100, this, SLOT(WindowShown())); + } } /// @@ -769,10 +769,10 @@ void Fractorium::showEvent(QShowEvent* e) /// void Fractorium::WindowShown() { - //Put the about dialog in the screen center. - auto screen = QGuiApplication::screenAt(pos()); - auto geom = screen->availableGeometry(); - m_AboutDialog->move(geom.center() - m_AboutDialog->rect().center()); + //Put the about dialog in the screen center. + auto screen = QGuiApplication::screenAt(pos()); + auto geom = screen->availableGeometry(); + m_AboutDialog->move(geom.center() - m_AboutDialog->rect().center()); } /// diff --git a/Source/Fractorium/Fractorium.h b/Source/Fractorium/Fractorium.h index acd9fe7..eb698d3 100644 --- a/Source/Fractorium/Fractorium.h +++ b/Source/Fractorium/Fractorium.h @@ -358,6 +358,7 @@ public slots: void OnRandomXaosButtonClicked(bool checked); void OnAddLayerButtonClicked(bool checked); void OnTransposeXaosButtonClicked(bool checked); + void OnToggleXaosButtonClicked(bool checked); void OnXaosRowDoubleClicked(int logicalIndex); void OnXaosColDoubleClicked(int logicalIndex); void OnXaosHScrollValueChanged(int value); @@ -398,7 +399,7 @@ public slots: void SetTreeItemData(EmberTreeWidgetItemBase* item, vv4F& v, uint w, uint h); private slots: - void WindowShown(); + void WindowShown(); public: //template//See below. @@ -626,7 +627,7 @@ private: std::unordered_map> m_HeightPresets; bool m_PreviousAffineState[4]; - bool m_AboutDialogCentered; + bool m_AboutDialogCentered; int m_FontSize; int m_VarSortMode; int m_PaletteSortMode; diff --git a/Source/Fractorium/Fractorium.ui b/Source/Fractorium/Fractorium.ui index 5f8fda2..3d3c966 100644 --- a/Source/Fractorium/Fractorium.ui +++ b/Source/Fractorium/Fractorium.ui @@ -2000,6 +2000,16 @@ + + + + Toggle whether to use xaos + + + Toggle Xaos + + + @@ -6025,7 +6035,7 @@ false - 3 + 2 10 @@ -6046,20 +6056,15 @@ Variation + + <html><head/><body><p>Red: Uses non-standard assignment which means direct assignment for regular variations, sum for pre/post. Order matters for these variations, which can be adjusted by dragging them within the tree on the Summary Tab.</p><p>Green: Uses direct color.</p><p>Blue: Uses an internal variation state.</p></body></html> + Weight - - - Type - - - <html><head/><body><p>Red: Uses non-standard assignment which means direct assignment for regular variations, sum for pre/post. Order matters for these variations, which can be adjusted by dragging them within the tree on the Summary Tab.</p><p>Green: Uses direct color.</p><p>Blue: Uses an internal variation state.</p></body></html> - - Spherical diff --git a/Source/Fractorium/FractoriumEmberController.cpp b/Source/Fractorium/FractoriumEmberController.cpp index 38d29b7..a3bcd1c 100644 --- a/Source/Fractorium/FractoriumEmberController.cpp +++ b/Source/Fractorium/FractoriumEmberController.cpp @@ -20,7 +20,6 @@ FractoriumEmberControllerBase::FractoriumEmberControllerBase(Fractorium* fractor m_RenderRestartTimer = make_unique(m_Fractorium); m_AnimateTimer = make_unique(m_Fractorium); m_AnimateTimer->stop(); - m_Fractorium->connect(m_RenderRestartTimer.get(), &QTimer::timeout, [&]() { m_Fractorium->StartRenderTimer(false); });//It's ok to pass false for the first shot because creating the controller will start the preview renders. // XXX: why not SLOT(SequenceAnimateNextFrame())? m_Fractorium->connect(m_AnimateTimer.get(), &QTimer::timeout, [&]() { SequenceAnimateNextFrame(); }); @@ -115,7 +114,7 @@ FractoriumEmberController::~FractoriumEmberController() { } /// 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. /// -template void FractoriumEmberController::SetEmber(const Ember& ember, bool verbatim, bool updatePointer) { SetEmberPrivate(ember, verbatim, updatePointer); } +template void FractoriumEmberController::SetEmber(const Ember& ember, bool verbatim, bool updatePointer, int xformIndex) { SetEmberPrivate(ember, verbatim, updatePointer, xformIndex); } template void FractoriumEmberController::CopyEmber(Ember& ember, std::function& ember)> perEmberOperation) { ember = m_Ember; perEmberOperation(ember); } template void FractoriumEmberController::SetEmberFile(const EmberFile& emberFile, bool move) { move ? m_EmberFile = std::move(emberFile) : m_EmberFile = emberFile; } template void FractoriumEmberController::CopyEmberFile(EmberFile& emberFile, bool sequence, std::function& ember)> perEmberOperation) @@ -132,10 +131,12 @@ template void FractoriumEmberController::CopyEmberFile(EmberFile } } +template void FractoriumEmberController::CopyXaosToggleEmber(Ember& ember) { ember = m_XaosToggleEmber; } +template void FractoriumEmberController::SetXaosToggleEmber(const Ember& ember) { m_XaosToggleEmber = ember; } template void FractoriumEmberController::SetTempPalette(const Palette& palette) { m_TempPalette = palette; } template void FractoriumEmberController::CopyTempPalette(Palette& palette) { palette = m_TempPalette; } #ifdef DO_DOUBLE -template void FractoriumEmberController::SetEmber(const Ember& ember, bool verbatim, bool updatePointer) { SetEmberPrivate(ember, verbatim, updatePointer); } +template void FractoriumEmberController::SetEmber(const Ember& ember, bool verbatim, bool updatePointer, int xformIndex) { SetEmberPrivate(ember, verbatim, updatePointer, xformIndex); } template void FractoriumEmberController::CopyEmber(Ember& ember, std::function& ember)> perEmberOperation) { ember = m_Ember; perEmberOperation(ember); } template void FractoriumEmberController::SetEmberFile(const EmberFile& emberFile, bool move) { move ? m_EmberFile = std::move(emberFile) : m_EmberFile = emberFile; } template void FractoriumEmberController::CopyEmberFile(EmberFile& emberFile, bool sequence, std::function& ember)> perEmberOperation) @@ -152,6 +153,8 @@ template void FractoriumEmberController::CopyEmberFile(EmberFile } } +template void FractoriumEmberController::CopyXaosToggleEmber(Ember& ember) { ember = m_XaosToggleEmber; } +template void FractoriumEmberController::SetXaosToggleEmber(const Ember& ember) { m_XaosToggleEmber = ember; } template void FractoriumEmberController::SetTempPalette(const Palette& palette) { m_TempPalette = palette; } template void FractoriumEmberController::CopyTempPalette(Palette& palette) { palette = m_TempPalette; } #endif @@ -166,6 +169,8 @@ void FractoriumEmberController::ConstrainDimensions(Ember& ember) /// /// Set the ember at the specified index from the currently opened file as the current Ember. +/// Also attempt to keep the same xform inxed selected, which is useful when switching between many +/// similar embers when setting up animation keyframes. /// Clears the undo state. /// Resets the rendering process. /// @@ -176,9 +181,10 @@ void FractoriumEmberController::SetEmber(size_t index, bool verbatim) { if (index < m_EmberFile.Size()) { + auto currentXformIndex = m_Fractorium->ui.CurrentXformCombo->currentIndex(); m_Fractorium->SelectLibraryItem(index); ClearUndo(); - SetEmber(*m_EmberFile.Get(index), verbatim, true); + SetEmber(*m_EmberFile.Get(index), verbatim, true, currentXformIndex); } } @@ -329,9 +335,10 @@ void FractoriumEmberController::UpdateXform(std::function*, siz /// The ember to set as the current /// If true, do not overwrite temporal samples, quality or supersample value, else overwrite. /// If true, update the current ember pointer to the address of the one passed in. +/// The xform index to select as the current one template template -void FractoriumEmberController::SetEmberPrivate(const Ember& ember, bool verbatim, bool updatePointer) +void FractoriumEmberController::SetEmberPrivate(const Ember& ember, bool verbatim, bool updatePointer, int xformIndex) { if (ember.m_Name != m_Ember.m_Name) m_LastSaveCurrent = ""; @@ -339,6 +346,7 @@ void FractoriumEmberController::SetEmberPrivate(const Ember& ember, bool v const auto w = m_Ember.m_FinalRasW;//Cache values for use below. const auto h = m_Ember.m_FinalRasH; m_Ember = ember; + m_XaosToggleEmber.Clear(); if (updatePointer && (typeid(T) == typeid(U))) m_EmberFilePointer = (Ember*)&ember; @@ -360,7 +368,7 @@ void FractoriumEmberController::SetEmberPrivate(const Ember& ember, bool v const auto filename = path.toStdString() + "/last.flame"; 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. + FillXforms(xformIndex);//Must do this first because the palette setup in FillParamTablesAndPalette() uses the xforms combo. FillParamTablesAndPalette(); FillCurvesControl(); FillSummary(); diff --git a/Source/Fractorium/FractoriumEmberController.h b/Source/Fractorium/FractoriumEmberController.h index e0792d6..8268ece 100644 --- a/Source/Fractorium/FractoriumEmberController.h +++ b/Source/Fractorium/FractoriumEmberController.h @@ -57,17 +57,21 @@ public: virtual ~FractoriumEmberControllerBase(); //Embers. - virtual void SetEmber(const Ember& ember, bool verbatim, bool updatePointer) { } + virtual void SetEmber(const Ember& ember, bool verbatim, bool updatePointer, int xformIndex) { } virtual void CopyEmber(Ember& ember, std::function& ember)> perEmberOperation/* = [&](Ember& ember) { }*/) { }//Uncomment default lambdas once LLVM fixes a crash in their compiler with default lambda parameters.//TODO virtual void SetEmberFile(const EmberFile& emberFile, bool move) { } virtual void CopyEmberFile(EmberFile& emberFile, bool sequence, std::function& ember)> perEmberOperation/* = [&](Ember& ember) { }*/) { } + virtual void CopyXaosToggleEmber(Ember& ember) { } + virtual void SetXaosToggleEmber(const Ember& ember) { } virtual void SetTempPalette(const Palette& palette) { } virtual void CopyTempPalette(Palette& palette) { } #ifdef DO_DOUBLE - virtual void SetEmber(const Ember& ember, bool verbatim, bool updatePointer) { } + virtual void SetEmber(const Ember& ember, bool verbatim, bool updatePointer, int xformIndex) { } virtual void CopyEmber(Ember& ember, std::function& ember)> perEmberOperation/* = [&](Ember& ember) { }*/) { } virtual void SetEmberFile(const EmberFile& emberFile, bool move) { } virtual void CopyEmberFile(EmberFile& emberFile, bool sequence, std::function& ember)> perEmberOperation/* = [&](Ember& ember) { }*/) { } + virtual void CopyXaosToggleEmber(Ember& ember) { } + virtual void SetXaosToggleEmber(const Ember& ember) { } virtual void SetTempPalette(const Palette& palette) { } virtual void CopyTempPalette(Palette& palette) { } #endif @@ -252,6 +256,7 @@ public: virtual void RandomXaos() { } virtual void AddLayer(int xforms) { } virtual void TransposeXaos() { } + virtual void ToggleXaos() { } //Palette. virtual size_t InitPaletteList(const QString& s) { return 0; } @@ -352,17 +357,21 @@ public: virtual ~FractoriumEmberController(); //Embers. - void SetEmber(const Ember& ember, bool verbatim, bool updatePointer) override; + void SetEmber(const Ember& ember, bool verbatim, bool updatePointer, int xformIndex) override; void CopyEmber(Ember& ember, std::function& ember)> perEmberOperation/* = [&](Ember& ember) { }*/) override; void SetEmberFile(const EmberFile& emberFile, bool move) override; void CopyEmberFile(EmberFile& emberFile, bool sequence, std::function& ember)> perEmberOperation/* = [&](Ember& ember) { }*/) override; + void CopyXaosToggleEmber(Ember& ember) override; + void SetXaosToggleEmber(const Ember& ember) override; void SetTempPalette(const Palette& palette) override; void CopyTempPalette(Palette& palette) override; #ifdef DO_DOUBLE - void SetEmber(const Ember& ember, bool verbatim, bool updatePointer) override; + void SetEmber(const Ember& ember, bool verbatim, bool updatePointer, int xformIndex) override; void CopyEmber(Ember& ember, std::function& ember)> perEmberOperation/* = [&](Ember& ember) { }*/) override; void SetEmberFile(const EmberFile& emberFile, bool move) override; void CopyEmberFile(EmberFile& emberFile, bool sequence, std::function& ember)> perEmberOperation/* = [&](Ember& ember) { }*/) override; + void CopyXaosToggleEmber(Ember& ember) override; + void SetXaosToggleEmber(const Ember& ember) override; void SetTempPalette(const Palette& palette) override; void CopyTempPalette(Palette& palette) override; #endif @@ -542,6 +551,7 @@ public: void FilteredVariations() override; void FillVariationTreeWithCurrentXform() override; void FillVariationTreeWithXform(Xform* xform); + QIcon MakeVariationIcon(const Variation* var); //Xforms Xaos. void FillXaos() override; @@ -551,6 +561,7 @@ public: void RandomXaos() override; void AddLayer(int xforms) override; void TransposeXaos() override; + void ToggleXaos() override; //Xforms Selection. virtual QString MakeXformCaption(size_t i) override; @@ -584,7 +595,7 @@ public: private: //Embers. void ApplyXmlSavingTemplate(Ember& ember); - template void SetEmberPrivate(const Ember& ember, bool verbatim, bool updatePointer); + template void SetEmberPrivate(const Ember& ember, bool verbatim, bool updatePointer, int xformIndex); //Params. template void ParamsToEmberPrivate(Ember& ember, bool imageParamsOnly); @@ -609,6 +620,7 @@ private: vector m_TempOpacities; vector m_NormalizedWeights; Ember m_Ember; + Ember m_XaosToggleEmber; Ember* m_EmberFilePointer = nullptr; EmberFile m_EmberFile; EmberFile m_SequenceFile; diff --git a/Source/Fractorium/FractoriumInfo.cpp b/Source/Fractorium/FractoriumInfo.cpp index 355f569..d6041b5 100644 --- a/Source/Fractorium/FractoriumInfo.cpp +++ b/Source/Fractorium/FractoriumInfo.cpp @@ -163,6 +163,8 @@ void FractoriumEmberController::FillSummary() vitem->setText(0, QString::fromStdString(var->Name())); vitem->setText(1, QLocale::system().toString(var->m_Weight, pc, vp).rightJustified(vlen, ' ')); vitem->setFlags(draggable); + auto qi = MakeVariationIcon(var); + vitem->setIcon(0, qi); if (const auto parVar = dynamic_cast*>(var)) { diff --git a/Source/Fractorium/FractoriumLibrary.cpp b/Source/Fractorium/FractoriumLibrary.cpp index 766b6ed..a39b19b 100644 --- a/Source/Fractorium/FractoriumLibrary.cpp +++ b/Source/Fractorium/FractoriumLibrary.cpp @@ -672,13 +672,13 @@ void FractoriumEmberController::SequenceGenerateButtonClicked() return; } - if (framesPerRot > 1 && !rots)//Because framesPerRot control has a min value of 1, check greater than 1. Also don't need to check the inverse like in EmberGenome. - { - QMessageBox::critical(m_Fractorium, "Animation sequence parameters error", - "Frames per rot cannot be greater than one while Rotations is zero. Setting it to 1."); - ui.SequenceFramesPerRotSpinBox->setValue(1); - return; - } + //if (framesPerRot > 1 && !rots)//Because framesPerRot control has a min value of 1, check greater than 1. Also don't need to check the inverse like in EmberGenome. + //{ + //QMessageBox::critical(m_Fractorium, "Animation sequence parameters error", + // "Frames per rot cannot be greater than one while Rotations is zero. Setting it to 1."); + //ui.SequenceFramesPerRotSpinBox->setValue(1); + //return; + //} } SheepTools tools(palettePath, EmberCommon::CreateRenderer(eRendererType::CPU_RENDERER, devices, false, 0, emberReport)); @@ -695,8 +695,10 @@ void FractoriumEmberController::SequenceGenerateButtonClicked() if (randFramesRot) frames = ui.SequenceRandomFramesPerRotMaxSpinBox->value(); - else + else if (rots) frames = ui.SequenceFramesPerRotSpinBox->value(); + else + frames = 1; if (randRot) frames *= ui.SequenceRandomRotationsMaxSpinBox->value(); diff --git a/Source/Fractorium/FractoriumMenus.cpp b/Source/Fractorium/FractoriumMenus.cpp index 7c6d3f6..94c03c0 100644 --- a/Source/Fractorium/FractoriumMenus.cpp +++ b/Source/Fractorium/FractoriumMenus.cpp @@ -162,14 +162,15 @@ void Fractorium::OnActionNewRandomFlameInCurrentFile(bool checked) { m_Controlle template void FractoriumEmberController::CopyFlameInCurrentFile() { - auto ember = m_Ember; StopAllPreviewRenderers(); + auto ember = m_Ember; + auto insertEmberIndex = m_Fractorium->ui.LibraryTree->currentIndex().row() + 1; ember.m_Name = EmberFile::DefaultEmberName(m_EmberFile.Size() + 1).toStdString(); - ember.m_Index = m_EmberFile.Size(); - m_EmberFile.m_Embers.push_back(ember);//Will invalidate the pointers contained in the EmberTreeWidgetItems, UpdateLibraryTree() will resync. + ember.m_Index = insertEmberIndex;//Will be overwritten below in UpdateLibraryTree(). + m_EmberFile.m_Embers.insert(Advance(m_EmberFile.m_Embers.begin(), insertEmberIndex), ember);//Will invalidate the pointers contained in the EmberTreeWidgetItems, UpdateLibraryTree() will resync. m_EmberFile.MakeNamesUnique(); - UpdateLibraryTree(); - SetEmber(m_EmberFile.Size() - 1, false); + FillLibraryTree(insertEmberIndex); + SetEmber(insertEmberIndex, false); } void Fractorium::OnActionCopyFlameInCurrentFile(bool checked) { m_Controller->CopyFlameInCurrentFile(); } @@ -590,7 +591,7 @@ void FractoriumEmberController::Undo() int index = m_Ember.GetTotalXformIndex(current, forceFinal); m_LastEditWasUndoRedo = true; m_UndoIndex = std::max(0u, m_UndoIndex - 1u); - SetEmber(m_UndoList[m_UndoIndex], true, false);//Don't update pointer because it's coming from the undo list. + SetEmber(m_UndoList[m_UndoIndex], true, false, index);//Don't update pointer because it's coming from the undo list. m_EditState = eEditUndoState::UNDO_REDO; if (index >= 0 && index < m_Fractorium->ui.CurrentXformCombo->count()) @@ -616,7 +617,7 @@ void FractoriumEmberController::Redo() int index = m_Ember.GetTotalXformIndex(current, forceFinal); m_LastEditWasUndoRedo = true; m_UndoIndex = std::min(m_UndoIndex + 1, m_UndoList.size() - 1); - SetEmber(m_UndoList[m_UndoIndex], true, false);//Don't update pointer because it's coming from the undo list. + SetEmber(m_UndoList[m_UndoIndex], true, false, index);//Don't update pointer because it's coming from the undo list. m_EditState = eEditUndoState::UNDO_REDO; if (index >= 0 && index < m_Fractorium->ui.CurrentXformCombo->count()) diff --git a/Source/Fractorium/FractoriumParams.cpp b/Source/Fractorium/FractoriumParams.cpp index 36dc00b..9057086 100644 --- a/Source/Fractorium/FractoriumParams.cpp +++ b/Source/Fractorium/FractoriumParams.cpp @@ -438,7 +438,7 @@ void FractoriumEmberController::ResizeAndScale(int width, int height, eScaleT { UpdateAll([&](Ember& ember, bool isMain) { - m_Ember.SetSizeAndAdjustScale(width, height, false, scaleType); + 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); @@ -521,11 +521,6 @@ template void FractoriumEmberController::RotateChanged(double d) } void Fractorium::OnRotateChanged(double d) { - if (d < -180) - d = 180 - ((-d + m_RotateSpin->value()) - (180 + m_RotateSpin->value())); - else if (d > 180) - d = -180 + ((d - m_RotateSpin->value()) - (180 - m_RotateSpin->value())); - m_Controller->RotateChanged(d); // d is ever between -180 and +180 } diff --git a/Source/Fractorium/FractoriumRender.cpp b/Source/Fractorium/FractoriumRender.cpp index c7b0048..6ea3505 100644 --- a/Source/Fractorium/FractoriumRender.cpp +++ b/Source/Fractorium/FractoriumRender.cpp @@ -758,9 +758,11 @@ bool Fractorium::CreateControllerFromOptions() #ifdef DO_DOUBLE EmberFile efd; Palette tempPalette; + Ember xaosToggle; #else EmberFile efd; Palette tempPalette; + Ember xaosToggle; #endif const QModelIndex index = ui.LibraryTree->currentIndex(); ui.LibraryTree->clear();//This must be here before FillLibraryTree() is called below, else a spurious EmberTreeItemChanged event will be called on a deleted object. @@ -774,6 +776,7 @@ bool Fractorium::CreateControllerFromOptions() current = m_Controller->SaveCurrentToOpenedFile(false); //Replace below with this once LLVM fixes a crash in their compiler with default lambda parameters.//TODO //m_Controller->CopyEmberFile(efd); + m_Controller->CopyXaosToggleEmber(xaosToggle); #ifdef DO_DOUBLE m_Controller->CopyEmberFile(efd, false, [&](Ember& ember) { }); #else @@ -804,6 +807,7 @@ bool Fractorium::CreateControllerFromOptions() //will apply the palette adjustments. m_Controller->FillLibraryTree(index.row()); m_Controller->SetEmber(current, true); + m_Controller->SetXaosToggleEmber(xaosToggle); m_Controller->LockedScale(scale); //Setting these and updating the GUI overwrites the work of clearing them done in SetEmber() above. //It's a corner case, but doesn't seem to matter. diff --git a/Source/Fractorium/FractoriumXaos.cpp b/Source/Fractorium/FractoriumXaos.cpp index 6b4a50a..ae4a3de 100644 --- a/Source/Fractorium/FractoriumXaos.cpp +++ b/Source/Fractorium/FractoriumXaos.cpp @@ -11,6 +11,9 @@ void Fractorium::InitXaosUI() int spinHeight = 20; ui.XaosTableView->verticalHeader()->setSectionsClickable(true); ui.XaosTableView->horizontalHeader()->setSectionsClickable(true); + auto ttstr = "

Double click to toggle all table spinner values in one row/col.

If any cell in the row is non zero, set all cells to zero, else 1.

If shift is held down, reverse the logic.

If ctrl is held down, set each cell to a random 0 or 1.

"; + ui.XaosTableView->horizontalHeader()->setToolTip(ttstr); + ui.XaosTableView->verticalHeader()->setToolTip(ttstr); m_XaosSpinBox = new DoubleSpinBox(nullptr, spinHeight, 0.1, false); m_XaosSpinBox->DoubleClick(true); m_XaosSpinBox->DoubleClickZero(1); @@ -24,6 +27,7 @@ void Fractorium::InitXaosUI() connect(ui.ClearXaosButton, SIGNAL(clicked(bool)), this, SLOT(OnClearXaosButtonClicked(bool)), Qt::QueuedConnection); connect(ui.RandomXaosButton, SIGNAL(clicked(bool)), this, SLOT(OnRandomXaosButtonClicked(bool)), Qt::QueuedConnection); connect(ui.TransposeXaosButton, SIGNAL(clicked(bool)), this, SLOT(OnTransposeXaosButtonClicked(bool)), Qt::QueuedConnection); + connect(ui.ToggleXaosButton, SIGNAL(clicked(bool)), this, SLOT(OnToggleXaosButtonClicked(bool)), Qt::QueuedConnection); connect(ui.AddLayerButton, SIGNAL(clicked(bool)), this, SLOT(OnAddLayerButtonClicked(bool)), Qt::QueuedConnection); connect(ui.XaosTableView->verticalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(OnXaosRowDoubleClicked(int)), Qt::QueuedConnection); connect(ui.XaosTableView->horizontalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(OnXaosColDoubleClicked(int)), Qt::QueuedConnection); @@ -59,22 +63,22 @@ void FractoriumEmberController::FillXaos() template void FractoriumEmberController::FillAppliedXaos() { - m_Ember.CalcNormalizedWeights(m_NormalizedWeights); + std::vector weights; + auto ct = int(XformCount()); - for (int i = 0, count = int(XformCount()); i < count; i++)//Column. + for (int i = 0, count = ct; i < count; i++) + weights.push_back(m_Ember.GetXform(i)->m_Weight); + + for (int i = 0, count = ct; i < count; i++)//Column. { if (const auto xform = m_Ember.GetXform(i)) { T norm = 0; double start = 0, offset = 0; - auto tempweights = m_NormalizedWeights; + auto tempweights = weights; for (int j = 0; j < count; j++)//Row. - { tempweights[j] *= xform->Xaos(j); - QModelIndex index = m_Fractorium->m_AppliedXaosTableModel->index(j, i, QModelIndex());//j and i are intentionally swapped here. - m_Fractorium->m_AppliedXaosTableModel->setData(index, TruncPrecision(xform->Xaos(j) * xform->m_Weight, 4));//Applied xaos is just a read only table for display purposes. - } QPixmap pixmap(m_Fractorium->ui.XaosAppliedTableView->columnWidth(i) - 8, m_Fractorium->ui.XaosTableView->rowHeight(0) * count); QPainter painter(&pixmap); @@ -84,6 +88,13 @@ void FractoriumEmberController::FillAppliedXaos() for (auto& w : tempweights) w = norm == static_cast(0) ? static_cast(0) : w / norm; + for (int j = 0; j < count; j++)//Row. + { + auto normXaosAppliedWeight = tempweights[j]; + QModelIndex index = m_Fractorium->m_AppliedXaosTableModel->index(j, i, QModelIndex());//j and i are intentionally swapped here. + m_Fractorium->m_AppliedXaosTableModel->setData(index, TruncPrecision(normXaosAppliedWeight, 4));//Applied xaos is just a read only table for display purposes. + } + if (norm) { for (size_t i = 0; i < tempweights.size() && offset <= pixmap.height(); i++) @@ -309,6 +320,48 @@ void FractoriumEmberController::TransposeXaos() void Fractorium::OnTransposeXaosButtonClicked(bool checked) { m_Controller->TransposeXaos(); } +/// +/// Toggle whether to use xaos or not by saving/restoring a backup flame. +/// Resets the rendering process. +/// +template +void FractoriumEmberController::ToggleXaos() +{ + Update([&] + { + if (m_Ember.XaosPresent()) + { + m_XaosToggleEmber = m_Ember; + m_Ember.ClearXaos(); + } + else if (m_XaosToggleEmber.XaosPresent()) + { + size_t i = 0; + + while (auto xform = m_Ember.GetXform(i)) + { + auto backupXform = m_XaosToggleEmber.GetXform(i); + + if (backupXform) + { + for (size_t j = 0; j < m_Ember.XformCount(); j++) + xform->SetXaos(j, TruncPrecision(backupXform->Xaos(j), XAOS_PREC)); + } + else + break; + + i++; + } + + m_XaosToggleEmber.Clear(); + } + }); + FillXaos(); + FillAppliedXaos(); +} + +void Fractorium::OnToggleXaosButtonClicked(bool checked) { m_Controller->ToggleXaos(); } + /// /// Toggle all xaos values in one row on left mouse button double click and resize all cells to fit their data. /// Skip toggling and only refit on right mouse button double click. diff --git a/Source/Fractorium/FractoriumXforms.cpp b/Source/Fractorium/FractoriumXforms.cpp index d3b1a41..4dd15c8 100644 --- a/Source/Fractorium/FractoriumXforms.cpp +++ b/Source/Fractorium/FractoriumXforms.cpp @@ -670,10 +670,8 @@ void FractoriumEmberController::FillXforms(int index) m_Fractorium->m_XformsSelectionLayout->blockSignals(false); combo->blockSignals(false); - - if (index < combo->count()) - combo->setCurrentIndex(index); - + index = index >= 0 && index < combo->count() ? index : 0; + combo->setCurrentIndex(index); m_Fractorium->ui.SoloXformCheckBox->blockSignals(true); if (m_Ember.m_Solo == combo->currentIndex()) diff --git a/Source/Fractorium/FractoriumXformsVariations.cpp b/Source/Fractorium/FractoriumXformsVariations.cpp index e437d7d..d6a4973 100644 --- a/Source/Fractorium/FractoriumXformsVariations.cpp +++ b/Source/Fractorium/FractoriumXformsVariations.cpp @@ -110,13 +110,9 @@ void FractoriumEmberController::SetupVariationsTree() const QSize hint0(170, 16); const QSize hint1(80, 16); const QSize hint2(20, 16); - static vector dc{ "m_ColorX" }; - static vector assign{ "outPoint->m_X =", "outPoint->m_Y =", "outPoint->m_Z =", - "outPoint->m_X=", "outPoint->m_Y=", "outPoint->m_Z=" }; auto tree = m_Fractorium->ui.VariationsTree; tree->clear(); tree->blockSignals(true); - int iconSize_ = 20; for (size_t i = 0; i < m_VariationList->Size(); i++) { @@ -129,33 +125,8 @@ void FractoriumEmberController::SetupVariationsTree() item->setSizeHint(0, hint0); item->setSizeHint(1, hint1); item->setSizeHint(2, hint2); - QPixmap pixmap(iconSize_ * 3, iconSize_); - auto mask = pixmap.createMaskFromColor(QColor("transparent"), Qt::MaskOutColor); - pixmap.setMask(mask); - QPainter paint(&pixmap); - paint.fillRect(QRect(0, 0, iconSize_ * 3, iconSize_), QColor(0, 0, 0, 0)); - - if (var->VarType() == eVariationType::VARTYPE_REG) - { - if (SearchVar(var, assign, false)) - paint.fillRect(QRect(0, 0, iconSize_, iconSize_), QColor(255, 0, 0)); - } - else if (var->VarType() == eVariationType::VARTYPE_PRE || var->VarType() == eVariationType::VARTYPE_POST) - { - if (var->AssignType() == eVariationAssignType::ASSIGNTYPE_SUM) - paint.fillRect(QRect(0, 0, iconSize_, iconSize_), QColor(255, 0, 0)); - } - - bool isDc = SearchVar(var, dc, false); - - if (isDc) - paint.fillRect(QRect(iconSize_, 0, iconSize_, iconSize_), QColor(0, 255, 0)); - - if (!var->StateOpenCLString().empty()) - paint.fillRect(QRect(iconSize_ * 2, 0, iconSize_, iconSize_), QColor(0, 0, 255)); - - QIcon qi(pixmap); - item->setIcon(2, qi); + auto qi = MakeVariationIcon(var); + item->setIcon(0, qi); spinBox->setRange(fMin, fMax); spinBox->DoubleClick(true); spinBox->DoubleClickZero(1); @@ -173,6 +144,7 @@ void FractoriumEmberController::SetupVariationsTree() { if (!params[j].IsPrecalc()) { + auto def = params[j].Def(); auto paramWidget = new VariationTreeWidgetItem(var->VariationId(), item); auto varSpinBox = new VariationTreeDoubleSpinBox(tree, paramWidget, parVar->VariationId(), params[j].Name()); paramWidget->setText(0, params[j].Name().c_str()); @@ -181,8 +153,9 @@ void FractoriumEmberController::SetupVariationsTree() varSpinBox->setRange(params[j].Min(), params[j].Max()); varSpinBox->setValue(params[j].ParamVal()); varSpinBox->DoubleClick(true); - varSpinBox->DoubleClickZero(1); - varSpinBox->DoubleClickNonZero(0); + varSpinBox->DoubleClickZero(def != 0 ? 0 : 1); + varSpinBox->DoubleClickLowVal(def); + varSpinBox->DoubleClickNonZero(def); if (params[j].Type() == eParamType::INTEGER || params[j].Type() == eParamType::INTEGER_NONZERO) { @@ -387,6 +360,50 @@ void FractoriumEmberController::FillVariationTreeWithXform(Xform* xform) m_Fractorium->OnTreeHeaderSectionClicked(m_Fractorium->m_VarSortMode); } +/// +/// Create an icon for the passed in variation which indicates the following: +/// Red: position matters because it uses non-standard assigning vs. summing. +/// Green: uses direct color. +/// Blue: maintains internal state, mostly of engineering interest. +/// +/// The variation to create the icon for +/// The newly created icon +template +QIcon FractoriumEmberController::MakeVariationIcon(const Variation* var) +{ + const int iconSize = 20; + static vector dc{ "m_ColorX" }; + static vector assign{ "outPoint->m_X =", "outPoint->m_Y =", "outPoint->m_Z =", + "outPoint->m_X=", "outPoint->m_Y=", "outPoint->m_Z=" }; + QPixmap pixmap(iconSize * 3, iconSize); + auto mask = pixmap.createMaskFromColor(QColor("transparent"), Qt::MaskOutColor); + pixmap.setMask(mask); + QPainter paint(&pixmap); + paint.fillRect(QRect(0, 0, iconSize * 3, iconSize), QColor(0, 0, 0, 0)); + + if (var->VarType() == eVariationType::VARTYPE_REG) + { + if (SearchVar(var, assign, false)) + paint.fillRect(QRect(0, 0, iconSize, iconSize), QColor(255, 0, 0)); + } + else if (var->VarType() == eVariationType::VARTYPE_PRE || var->VarType() == eVariationType::VARTYPE_POST) + { + if (var->AssignType() == eVariationAssignType::ASSIGNTYPE_SUM) + paint.fillRect(QRect(0, 0, iconSize, iconSize), QColor(255, 0, 0)); + } + + bool isDc = SearchVar(var, dc, false); + + if (isDc) + paint.fillRect(QRect(iconSize, 0, iconSize, iconSize), QColor(0, 255, 0)); + + if (!var->StateOpenCLString().empty()) + paint.fillRect(QRect(iconSize * 2, 0, iconSize, iconSize), QColor(0, 0, 255)); + + QIcon qi(pixmap); + return qi; +} + /// /// Change the sorting to be either by variation ID, or by weight. /// If sorting by variation ID, repeated clicks will alternate ascending or descending. diff --git a/Source/Fractorium/GLEmberController.cpp b/Source/Fractorium/GLEmberController.cpp index 21caee7..dd3e81b 100644 --- a/Source/Fractorium/GLEmberController.cpp +++ b/Source/Fractorium/GLEmberController.cpp @@ -99,8 +99,8 @@ template T GLEmberController::CalcRotation() { const auto scrolledWorldCenter = ScrolledCenter(true); - const T rotStart = NormalizeDeg180((std::atan2(m_MouseDownWorldPos.y - scrolledWorldCenter.y, m_MouseDownWorldPos.x - scrolledWorldCenter.x) * RAD_2_DEG_T)); - const T rot = NormalizeDeg180((std::atan2(m_MouseWorldPos.y - scrolledWorldCenter.y, m_MouseWorldPos.x - scrolledWorldCenter.x) * RAD_2_DEG_T)); + const T rotStart = NormalizeDeg360((std::atan2(m_MouseDownWorldPos.y - scrolledWorldCenter.y, m_MouseDownWorldPos.x - scrolledWorldCenter.x) * RAD_2_DEG_T)); + const T rot = NormalizeDeg360((std::atan2(m_MouseWorldPos.y - scrolledWorldCenter.y, m_MouseWorldPos.x - scrolledWorldCenter.x) * RAD_2_DEG_T)); return rotStart - rot; } diff --git a/Source/Fractorium/GLWidget.cpp b/Source/Fractorium/GLWidget.cpp index 4850ab2..d09497b 100755 --- a/Source/Fractorium/GLWidget.cpp +++ b/Source/Fractorium/GLWidget.cpp @@ -1078,7 +1078,7 @@ void GLEmberController::MouseMove(QMouseEvent* e) { const T rot = CalcRotation(); const T scale = CalcScale(); - ember->m_Rotate = NormalizeDeg180(m_RotationDown + rot); + ember->m_Rotate = NormalizeDeg360(m_RotationDown + rot); m_Fractorium->SetRotation(ember->m_Rotate, true); m_Fractorium->SetScale(std::max(static_cast(10), m_ScaleDown + scale));//Will restart the rendering process. } diff --git a/Source/Fractorium/OptionsDialog.ui b/Source/Fractorium/OptionsDialog.ui index f93f26b..cdb3af4 100644 --- a/Source/Fractorium/OptionsDialog.ui +++ b/Source/Fractorium/OptionsDialog.ui @@ -841,6 +841,9 @@ + + <html><head/><body><p>When resaving a file, use an auto generated unique name based on the first name supplied.</p><p>This allows you to keep snapshots of your changes instead of overwriting them with each save.</p></body></html> + Auto Unique Filenames