diff --git a/Source/Ember/Ember.cpp b/Source/Ember/Ember.cpp index a902efc..6bef185 100644 --- a/Source/Ember/Ember.cpp +++ b/Source/Ember/Ember.cpp @@ -1,28 +1,25 @@ #include "EmberPch.h" #include "EmberDefines.h" #include "Isaac.h" +#include "Utils.h" namespace EmberNs { template<> unique_ptr> QTIsaac::GlobalRand = unique_ptr>(new QTIsaac()); template<> unique_ptr QTIsaac::s_CS = unique_ptr(new recursive_mutex()); template EMBER_API class QTIsaac; +bool Compat::m_Compat = false; } #include "Curves.h" #include "Ember.h" -#include "Utils.h" #include "Iterator.h" #include "Palette.h" #include "PaletteList.h" #include "Point.h" #include "VarFuncs.h" #include "Variation.h" -#ifdef FLAM3_COMPAT - #include "Variations01_flam3_compat.h"//Do this instead if you want full compatibility with flam3. -#else - #include "Variations01.h" -#endif +#include "Variations01.h" #include "Variations02.h" #include "Variations03.h" #include "Variations04.h" diff --git a/Source/Ember/EmberDefines.h b/Source/Ember/EmberDefines.h index 32032a5..7ef0420 100644 --- a/Source/Ember/EmberDefines.h +++ b/Source/Ember/EmberDefines.h @@ -44,7 +44,6 @@ namespace EmberNs #define ISAAC_SIZE 4 #define MEMALIGN 32 #define DE_THRESH 100 -#define MAX_VARS_PER_XFORM 8 #define DEG_2_RAD (M_PI / 180) #define RAD_2_DEG (180 / M_PI) #define DEG_2_RAD_T (T(M_PI) / T(180)) diff --git a/Source/Ember/Utils.h b/Source/Ember/Utils.h index 527b97a..5420b0a 100644 --- a/Source/Ember/Utils.h +++ b/Source/Ember/Utils.h @@ -285,6 +285,16 @@ protected: x(const x& other) = delete; \ const x& operator=(const x& other) = delete +/// +/// The calculations in some variations were changed from what they were in flam3/Apophysis to match Chaotica. +/// Some users prefer the old functionality, so provide an option to retain it. +/// +class EMBER_API Compat +{ +public: + static bool m_Compat; +}; + /// /// Open a file in binary mode and read its entire contents into a vector of bytes. Optionally null terminate. /// diff --git a/Source/Ember/Variations01.h b/Source/Ember/Variations01.h index 6e31e6a..eed8c5f 100644 --- a/Source/Ember/Variations01.h +++ b/Source/Ember/Variations01.h @@ -6239,26 +6239,50 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T x = helper.In.x * M_PI2; - T y = helper.In.y * M_PI2; - helper.Out.x = m_Weight * std::sin(x) * std::cosh(y); - helper.Out.y = m_Weight * std::cos(x) * std::sinh(y); + if (Compat::m_Compat) + { + helper.Out.x = m_Weight * std::sin(helper.In.x) * std::cosh(helper.In.y); + helper.Out.y = m_Weight * std::cos(helper.In.x) * std::sinh(helper.In.y); + } + else + { + T x = helper.In.x * M_PI2; + T y = helper.In.y * M_PI2; + helper.Out.x = m_Weight * std::sin(x) * std::cosh(y); + helper.Out.y = m_Weight * std::cos(x) * std::sinh(y); + } + helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { - ostringstream ss; - string weight = WeightDefineString(); - intmax_t varIndex = IndexInXform(); - ss << "\t{\n" - << "\t\treal_t x = vIn.x * MPI2;\n" - << "\t\treal_t y = vIn.y * MPI2;\n" - << "\t\tvOut.x = " << weight << " * sin(x) * cosh(y);\n" - << "\t\tvOut.y = " << weight << " * cos(x) * sinh(y);\n" - << "\t\tvOut.z = " << DefaultZCl() - << "\t}\n"; - return ss.str(); + if (Compat::m_Compat) + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\tvOut.x = " << weight << " * sin(vIn.x) * cosh(vIn.y);\n" + << "\t\tvOut.y = " << weight << " * cos(vIn.x) * sinh(vIn.y);\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } + else + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\treal_t x = vIn.x * MPI2;\n" + << "\t\treal_t y = vIn.y * MPI2;\n" + << "\t\tvOut.x = " << weight << " * sin(x) * cosh(y);\n" + << "\t\tvOut.y = " << weight << " * cos(x) * sinh(y);\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } } }; @@ -6275,26 +6299,51 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T x = helper.In.x * M_PI2; - T y = helper.In.y * M_PI2; - helper.Out.x = m_Weight * std::cos(x) * std::cosh(y); - helper.Out.y = m_Weight * -std::sin(x) * std::sinh(y); + if (Compat::m_Compat) + { + //clamp fabs x and y to 7.104760e+002 for cosh, and |x| 7.104760e+002 for sinh + helper.Out.x = m_Weight * std::cos(helper.In.x) * std::cosh(helper.In.y); + helper.Out.y = -(m_Weight * std::sin(helper.In.x) * std::sinh(helper.In.y)); + } + else + { + T x = helper.In.x * M_PI2; + T y = helper.In.y * M_PI2; + helper.Out.x = m_Weight * std::cos(x) * std::cosh(y); + helper.Out.y = m_Weight * -std::sin(x) * std::sinh(y); + } + helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { - ostringstream ss; - string weight = WeightDefineString(); - intmax_t varIndex = IndexInXform(); - ss << "\t{\n" - << "\t\treal_t x = vIn.x * MPI2;\n" - << "\t\treal_t y = vIn.y * MPI2;\n" - << "\t\tvOut.x = " << weight << " * cos(x) * cosh(y);\n" - << "\t\tvOut.y = " << weight << " * -sin(x) * sinh(y);\n" - << "\t\tvOut.z = " << DefaultZCl() - << "\t}\n"; - return ss.str(); + if (Compat::m_Compat) + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\tvOut.x = " << weight << " * cos(vIn.x) * cosh(vIn.y);\n" + << "\t\tvOut.y = -(" << weight << " * sin(vIn.x) * sinh(vIn.y));\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } + else + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\treal_t x = vIn.x * MPI2;\n" + << "\t\treal_t y = vIn.y * MPI2;\n" + << "\t\tvOut.x = " << weight << " * cos(x) * cosh(y);\n" + << "\t\tvOut.y = " << weight << " * -sin(x) * sinh(y);\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } } }; @@ -6311,29 +6360,64 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T x = helper.In.x * M_PI2; - T y = helper.In.y * M_PI2; - T den = m_Weight / Zeps(std::cos(x) + std::cosh(y)); - helper.Out.x = std::sin(x) * den; - helper.Out.y = std::sinh(y) * den; + if (Compat::m_Compat) + { + T tansin, tancos, tansinh, tancosh, tanden; + sincos(2 * helper.In.x, &tansin, &tancos); + tansinh = std::sinh(2 * helper.In.y); + tancosh = std::cosh(2 * helper.In.y); + tanden = 1 / Zeps(tancos + tancosh); + helper.Out.x = m_Weight * tanden * tansin; + helper.Out.y = m_Weight * tanden * tansinh; + } + else + { + T x = helper.In.x * M_PI2; + T y = helper.In.y * M_PI2; + T den = m_Weight / Zeps(std::cos(x) + std::cosh(y)); + helper.Out.x = std::sin(x) * den; + helper.Out.y = std::sinh(y) * den; + } + helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { - ostringstream ss; - string weight = WeightDefineString(); - intmax_t varIndex = IndexInXform(); - ss << "\t{\n" - << "\t\treal_t x = vIn.x * MPI2;\n" - << "\t\treal_t y = vIn.y * MPI2;\n" - << "\t\treal_t den = " << weight << " / Zeps(cos(x) + cosh(y));\n" - << "\n" - << "\t\tvOut.x = sin(x) * den;\n" - << "\t\tvOut.y = sinh(y) * den;\n" - << "\t\tvOut.z = " << DefaultZCl() - << "\t}\n"; - return ss.str(); + if (Compat::m_Compat) + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\treal_t tansin = sin((real_t)(2.0) * vIn.x);\n" + << "\t\treal_t tancos = cos((real_t)(2.0) * vIn.x);\n" + << "\t\treal_t tansinh = sinh((real_t)(2.0) * vIn.y);\n" + << "\t\treal_t tancosh = cosh((real_t)(2.0) * vIn.y);\n" + << "\t\treal_t tanden = (real_t)(1.0) / Zeps(tancos + tancosh);\n" + << "\n" + << "\t\tvOut.x = " << weight << " * tanden * tansin;\n" + << "\t\tvOut.y = " << weight << " * tanden * tansinh;\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } + else + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\treal_t x = vIn.x * MPI2;\n" + << "\t\treal_t y = vIn.y * MPI2;\n" + << "\t\treal_t den = " << weight << " / Zeps(cos(x) + cosh(y));\n" + << "\n" + << "\t\tvOut.x = sin(x) * den;\n" + << "\t\tvOut.y = sinh(y) * den;\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } } virtual vector OpenCLGlobalFuncNames() const override @@ -6355,37 +6439,72 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T x = helper.In.x * T(M_PI); - T y = helper.In.y * T(M_PI); - T secsin, seccos, secsinh, seccosh, secden; - sincos(x, &secsin, &seccos); - secsinh = std::sinh(y); - seccosh = std::cosh(y); - secden = (m_Weight * 2) / Zeps(std::cos(2 * x) + std::cosh(2 * y)); - helper.Out.x = secden * seccos * seccosh; - helper.Out.y = secden * secsin * secsinh; + if (Compat::m_Compat) + { + T secsin, seccos, secsinh, seccosh, secden; + sincos(helper.In.x, &secsin, &seccos); + secsinh = std::sinh(helper.In.y); + seccosh = std::cosh(helper.In.y); + secden = 2 / Zeps(std::cos(2 * helper.In.x) + std::cosh(2 * helper.In.y)); + helper.Out.x = m_Weight * secden * seccos * seccosh; + helper.Out.y = m_Weight * secden * secsin * secsinh; + } + else + { + T x = helper.In.x * T(M_PI); + T y = helper.In.y * T(M_PI); + T secsin, seccos, secsinh, seccosh, secden; + sincos(x, &secsin, &seccos); + secsinh = std::sinh(y); + seccosh = std::cosh(y); + secden = m_Weight * (2 / Zeps(std::cos(2 * x) + std::cosh(2 * y))); + helper.Out.x = secden * seccos * seccosh; + helper.Out.y = secden * secsin * secsinh; + } + helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { - ostringstream ss; - string weight = WeightDefineString(); - intmax_t varIndex = IndexInXform(); - ss << "\t{\n" - << "\t\treal_t x = vIn.x * MPI;\n" - << "\t\treal_t y = vIn.y * MPI;\n" - << "\t\treal_t secsin = sin(x);\n" - << "\t\treal_t seccos = cos(x);\n" - << "\t\treal_t secsinh = sinh(y);\n" - << "\t\treal_t seccosh = cosh(y);\n" - << "\t\treal_t secden = (" << weight << " * (real_t)(2.0)) / Zeps(cos((real_t)(2.0) * x) + cosh((real_t)(2.0) * y));\n" - << "\n" - << "\t\tvOut.x = secden * seccos * seccosh;\n" - << "\t\tvOut.y = secden * secsin * secsinh;\n" - << "\t\tvOut.z = " << DefaultZCl() - << "\t}\n"; - return ss.str(); + if (Compat::m_Compat) + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\treal_t secsin = sin(vIn.x);\n" + << "\t\treal_t seccos = cos(vIn.x);\n" + << "\t\treal_t secsinh = sinh(vIn.y);\n" + << "\t\treal_t seccosh = cosh(vIn.y);\n" + << "\t\treal_t secden = (real_t)(2.0) / Zeps(cos((real_t)(2.0) * vIn.x) + cosh((real_t)(2.0) * vIn.y));\n" + << "\n" + << "\t\tvOut.x = " << weight << " * secden * seccos * seccosh;\n" + << "\t\tvOut.y = " << weight << " * secden * secsin * secsinh;\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } + else + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\treal_t x = vIn.x * MPI;\n" + << "\t\treal_t y = vIn.y * MPI;\n" + << "\t\treal_t secsin = sin(x);\n" + << "\t\treal_t seccos = cos(x);\n" + << "\t\treal_t secsinh = sinh(y);\n" + << "\t\treal_t seccosh = cosh(y);\n" + << "\t\treal_t secden = " << weight << " * ((real_t)(2.0) / Zeps(cos((real_t)(2.0) * x) + cosh((real_t)(2.0) * y)));\n" + << "\n" + << "\t\tvOut.x = secden * seccos * seccosh;\n" + << "\t\tvOut.y = secden * secsin * secsinh;\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } } virtual vector OpenCLGlobalFuncNames() const override @@ -6407,39 +6526,74 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T x = helper.In.x * M_PI2; - T y = helper.In.y * M_PI2; - T cscsin, csccos, cscsinh, csccosh, cscden, d; - sincos(x, &cscsin, &csccos); - cscsinh = std::sinh(y); - csccosh = std::cosh(y); - d = 1 + 2 * cscsinh * cscsinh - std::cos(2 * x); - cscden = 2 * m_Weight / d; - helper.Out.x = cscden * cscsin * csccosh; - helper.Out.y = cscden * csccos * cscsinh; + if (Compat::m_Compat) + { + T cscsin, csccos, cscsinh, csccosh, cscden; + sincos(helper.In.x, &cscsin, &csccos); + cscsinh = std::sinh(helper.In.y); + csccosh = std::cosh(helper.In.y); + cscden = 2 / Zeps(std::cosh(2 * helper.In.y) - std::cos(2 * helper.In.x)); + helper.Out.x = m_Weight * cscden * cscsin * csccosh; + helper.Out.y = -(m_Weight * cscden * csccos * cscsinh); + } + else + { + T x = helper.In.x * M_PI2; + T y = helper.In.y * M_PI2; + T cscsin, csccos, cscsinh, csccosh, cscden, d; + sincos(x, &cscsin, &csccos); + cscsinh = std::sinh(y); + csccosh = std::cosh(y); + d = 1 + 2 * cscsinh * cscsinh - std::cos(2 * x); + cscden = 2 * m_Weight / d; + helper.Out.x = cscden * cscsin * csccosh; + helper.Out.y = cscden * csccos * cscsinh; + } + helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { - ostringstream ss; - string weight = WeightDefineString(); - intmax_t varIndex = IndexInXform(); - ss << "\t{\n" - << "\t\treal_t x = vIn.x * MPI2;\n" - << "\t\treal_t y = vIn.y * MPI2;\n" - << "\t\treal_t cscsin = sin(x);\n" - << "\t\treal_t csccos = cos(x);\n" - << "\t\treal_t cscsinh = sinh(y);\n" - << "\t\treal_t csccosh = cosh(y);\n" - << "\t\treal_t d = Zeps(1 + 2 * cscsinh * cscsinh - cos(2 * x));\n" - << "\t\treal_t cscden = 2 * " << weight << " / d;\n" - << "\n" - << "\t\tvOut.x = cscden * cscsin * csccosh;\n" - << "\t\tvOut.y = cscden * csccos * cscsinh;\n" - << "\t\tvOut.z = " << DefaultZCl() - << "\t}\n"; - return ss.str(); + if (Compat::m_Compat) + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\treal_t cscsin = sin(vIn.x);\n" + << "\t\treal_t csccos = cos(vIn.x);\n" + << "\t\treal_t cscsinh = sinh(vIn.y);\n" + << "\t\treal_t csccosh = cosh(vIn.y);\n" + << "\t\treal_t cscden = (real_t)(2.0) / Zeps(cosh((real_t)(2.0) * vIn.y) - cos((real_t)(2.0) * vIn.x));\n" + << "\n" + << "\t\tvOut.x = " << weight << " * cscden * cscsin * csccosh;\n" + << "\t\tvOut.y = -(" << weight << " * cscden * csccos * cscsinh);\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } + else + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\treal_t x = vIn.x * MPI2;\n" + << "\t\treal_t y = vIn.y * MPI2;\n" + << "\t\treal_t cscsin = sin(x);\n" + << "\t\treal_t csccos = cos(x);\n" + << "\t\treal_t cscsinh = sinh(y);\n" + << "\t\treal_t csccosh = cosh(y);\n" + << "\t\treal_t d = Zeps(1 + 2 * cscsinh * cscsinh - cos(2 * x));\n" + << "\t\treal_t cscden = 2 * " << weight << " / d;\n" + << "\n" + << "\t\tvOut.x = cscden * cscsin * csccosh;\n" + << "\t\tvOut.y = cscden * csccos * cscsinh;\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } } virtual vector OpenCLGlobalFuncNames() const override @@ -6461,37 +6615,72 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T x = helper.In.x * M_PI2; - T y = helper.In.y * M_PI2; - T cotsin, cotcos, cotsinh, cotcosh, cotden; - sincos(x, &cotsin, &cotcos); - cotsinh = std::sinh(y); - cotcosh = std::cosh(y); - cotden = m_Weight / Zeps(cotcosh - cotcos); - helper.Out.x = cotden * cotsin; - helper.Out.y = cotden * cotsinh; + if (Compat::m_Compat) + { + T cotsin, cotcos, cotsinh, cotcosh, cotden; + sincos(2 * helper.In.x, &cotsin, &cotcos); + cotsinh = std::sinh(2 * helper.In.y); + cotcosh = std::cosh(2 * helper.In.y); + cotden = 1 / Zeps(cotcosh - cotcos); + helper.Out.x = m_Weight * cotden * cotsin; + helper.Out.y = m_Weight * cotden * -1 * cotsinh; + } + else + { + T x = helper.In.x * M_PI2; + T y = helper.In.y * M_PI2; + T cotsin, cotcos, cotsinh, cotcosh, cotden; + sincos(x, &cotsin, &cotcos); + cotsinh = std::sinh(y); + cotcosh = std::cosh(y); + cotden = m_Weight / Zeps(cotcosh - cotcos); + helper.Out.x = cotden * cotsin; + helper.Out.y = cotden * cotsinh; + } + helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { - ostringstream ss; - string weight = WeightDefineString(); - intmax_t varIndex = IndexInXform(); - ss << "\t{\n" - << "\t\treal_t x = vIn.x * MPI2;\n" - << "\t\treal_t y = vIn.y * MPI2;\n" - << "\t\treal_t cotsin = sin(x);\n" - << "\t\treal_t cotcos = cos(x);\n" - << "\t\treal_t cotsinh = sinh(y);\n" - << "\t\treal_t cotcosh = cosh(y);\n" - << "\t\treal_t cotden = " << weight << " / Zeps(cotcosh - cotcos);\n" - << "\n" - << "\t\tvOut.x = cotden * cotsin;\n" - << "\t\tvOut.y = cotden * cotsinh;\n" - << "\t\tvOut.z = " << DefaultZCl() - << "\t}\n"; - return ss.str(); + if (Compat::m_Compat) + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\treal_t cotsin = sin((real_t)(2.0) * vIn.x);\n" + << "\t\treal_t cotcos = cos((real_t)(2.0) * vIn.x);\n" + << "\t\treal_t cotsinh = sinh((real_t)(2.0) * vIn.y);\n" + << "\t\treal_t cotcosh = cosh((real_t)(2.0) * vIn.y);\n" + << "\t\treal_t cotden = (real_t)(1.0) / Zeps(cotcosh - cotcos);\n" + << "\n" + << "\t\tvOut.x = " << weight << " * cotden * cotsin;\n" + << "\t\tvOut.y = " << weight << " * cotden * -1 * cotsinh;\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } + else + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\treal_t x = vIn.x * MPI2;\n" + << "\t\treal_t y = vIn.y * MPI2;\n" + << "\t\treal_t cotsin = sin(x);\n" + << "\t\treal_t cotcos = cos(x);\n" + << "\t\treal_t cotsinh = sinh(y);\n" + << "\t\treal_t cotcosh = cosh(y);\n" + << "\t\treal_t cotden = " << weight << " / Zeps(cotcosh - cotcos);\n" + << "\n" + << "\t\tvOut.x = cotden * cotsin;\n" + << "\t\tvOut.y = cotden * cotsinh;\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } } virtual vector OpenCLGlobalFuncNames() const override @@ -6513,35 +6702,68 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T sinhsin, sinhcos, sinhsinh, sinhcosh; - T x = helper.In.x * M_PI4; - T y = helper.In.y * M_PI4; - sincos(y, &sinhsin, &sinhcos); - sinhsinh = std::sinh(x); - sinhcosh = std::cosh(x); - helper.Out.x = m_Weight * sinhsinh * sinhcos; - helper.Out.y = m_Weight * sinhcosh * sinhsin; + if (Compat::m_Compat) + { + T sinhsin, sinhcos, sinhsinh, sinhcosh; + sincos(helper.In.y, &sinhsin, &sinhcos); + sinhsinh = std::sinh(helper.In.x); + sinhcosh = std::cosh(helper.In.x); + helper.Out.x = m_Weight * sinhsinh * sinhcos; + helper.Out.y = m_Weight * sinhcosh * sinhsin; + } + else + { + T sinhsin, sinhcos, sinhsinh, sinhcosh; + T x = helper.In.x * M_PI4; + T y = helper.In.y * M_PI4; + sincos(y, &sinhsin, &sinhcos); + sinhsinh = std::sinh(x); + sinhcosh = std::cosh(x); + helper.Out.x = m_Weight * sinhsinh * sinhcos; + helper.Out.y = m_Weight * sinhcosh * sinhsin; + } + helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { - ostringstream ss; - string weight = WeightDefineString(); - intmax_t varIndex = IndexInXform(); - ss << "\t{\n" - << "\t\treal_t x = vIn.x * MPI4;\n" - << "\t\treal_t y = vIn.y * MPI4;\n" - << "\t\treal_t sinhsin = sin(y);\n" - << "\t\treal_t sinhcos = cos(y);\n" - << "\t\treal_t sinhsinh = sinh(x);\n" - << "\t\treal_t sinhcosh = cosh(x);\n" - << "\n" - << "\t\tvOut.x = " << weight << " * sinhsinh * sinhcos;\n" - << "\t\tvOut.y = " << weight << " * sinhcosh * sinhsin;\n" - << "\t\tvOut.z = " << DefaultZCl() - << "\t}\n"; - return ss.str(); + if (Compat::m_Compat) + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\treal_t sinhsin = sin(vIn.y);\n" + << "\t\treal_t sinhcos = cos(vIn.y);\n" + << "\t\treal_t sinhsinh = sinh(vIn.x);\n" + << "\t\treal_t sinhcosh = cosh(vIn.x);\n" + << "\n" + << "\t\tvOut.x = " << weight << " * sinhsinh * sinhcos;\n" + << "\t\tvOut.y = " << weight << " * sinhcosh * sinhsin;\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } + else + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\treal_t x = vIn.x * MPI4;\n" + << "\t\treal_t y = vIn.y * MPI4;\n" + << "\t\treal_t sinhsin = sin(y);\n" + << "\t\treal_t sinhcos = cos(y);\n" + << "\t\treal_t sinhsinh = sinh(x);\n" + << "\t\treal_t sinhcosh = cosh(x);\n" + << "\n" + << "\t\tvOut.x = " << weight << " * sinhsinh * sinhcos;\n" + << "\t\tvOut.y = " << weight << " * sinhcosh * sinhsin;\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } } }; @@ -6558,35 +6780,68 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T coshsin, coshcos, coshsinh, coshcosh; - T x = helper.In.x * M_PI2; - T y = helper.In.y * M_PI2; - sincos(y, &coshsin, &coshcos); - coshsinh = std::sinh(x); - coshcosh = std::cosh(x); - helper.Out.x = m_Weight * coshcosh * coshcos; - helper.Out.y = m_Weight * coshsinh * coshsin; + if (Compat::m_Compat) + { + T coshsin, coshcos, coshsinh, coshcosh; + sincos(helper.In.y, &coshsin, &coshcos); + coshsinh = std::sinh(helper.In.x); + coshcosh = std::cosh(helper.In.x); + helper.Out.x = m_Weight * coshcosh * coshcos; + helper.Out.y = m_Weight * coshsinh * coshsin; + } + else + { + T coshsin, coshcos, coshsinh, coshcosh; + T x = helper.In.x * M_PI2; + T y = helper.In.y * M_PI2; + sincos(y, &coshsin, &coshcos); + coshsinh = std::sinh(x); + coshcosh = std::cosh(x); + helper.Out.x = m_Weight * coshcosh * coshcos; + helper.Out.y = m_Weight * coshsinh * coshsin; + } + helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { - ostringstream ss; - string weight = WeightDefineString(); - intmax_t varIndex = IndexInXform(); - ss << "\t{\n" - << "\t\treal_t x = vIn.x * MPI2;\n" - << "\t\treal_t y = vIn.y * MPI2;\n" - << "\t\treal_t coshsin = sin(y);\n" - << "\t\treal_t coshcos = cos(y);\n" - << "\t\treal_t coshsinh = sinh(x);\n" - << "\t\treal_t coshcosh = cosh(x);\n" - << "\n" - << "\t\tvOut.x = " << weight << " * coshcosh * coshcos;\n" - << "\t\tvOut.y = " << weight << " * coshsinh * coshsin;\n" - << "\t\tvOut.z = " << DefaultZCl() - << "\t}\n"; - return ss.str(); + if (Compat::m_Compat) + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\treal_t coshsin = sin(vIn.y);\n" + << "\t\treal_t coshcos = cos(vIn.y);\n" + << "\t\treal_t coshsinh = sinh(vIn.x);\n" + << "\t\treal_t coshcosh = cosh(vIn.x);\n" + << "\n" + << "\t\tvOut.x = " << weight << " * coshcosh * coshcos;\n" + << "\t\tvOut.y = " << weight << " * coshsinh * coshsin;\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } + else + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\treal_t x = vIn.x * MPI2;\n" + << "\t\treal_t y = vIn.y * MPI2;\n" + << "\t\treal_t coshsin = sin(y);\n" + << "\t\treal_t coshcos = cos(y);\n" + << "\t\treal_t coshsinh = sinh(x);\n" + << "\t\treal_t coshcosh = cosh(x);\n" + << "\n" + << "\t\tvOut.x = " << weight << " * coshcosh * coshcos;\n" + << "\t\tvOut.y = " << weight << " * coshsinh * coshsin;\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } } }; @@ -6603,37 +6858,72 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T tanhsin, tanhcos, tanhsinh, tanhcosh, tanhden; - T x = helper.In.x * M_PI2; - T y = helper.In.y * M_PI2; - sincos(y, &tanhsin, &tanhcos); - tanhsinh = std::sinh(x); - tanhcosh = std::cosh(x); - tanhden = m_Weight / Zeps(tanhcos + tanhcosh); - helper.Out.x = tanhden * tanhsinh; - helper.Out.y = tanhden * tanhsin; + if (Compat::m_Compat) + { + T tanhsin, tanhcos, tanhsinh, tanhcosh, tanhden; + sincos(2 * helper.In.y, &tanhsin, &tanhcos); + tanhsinh = std::sinh(2 * helper.In.x); + tanhcosh = std::cosh(2 * helper.In.x); + tanhden = 1 / Zeps(tanhcos + tanhcosh); + helper.Out.x = m_Weight * tanhden * tanhsinh; + helper.Out.y = m_Weight * tanhden * tanhsin; + } + else + { + T tanhsin, tanhcos, tanhsinh, tanhcosh, tanhden; + T x = helper.In.x * M_PI2; + T y = helper.In.y * M_PI2; + sincos(y, &tanhsin, &tanhcos); + tanhsinh = std::sinh(x); + tanhcosh = std::cosh(x); + tanhden = m_Weight / Zeps(tanhcos + tanhcosh); + helper.Out.x = tanhden * tanhsinh; + helper.Out.y = tanhden * tanhsin; + } + helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { - ostringstream ss; - string weight = WeightDefineString(); - intmax_t varIndex = IndexInXform(); - ss << "\t{\n" - << "\t\treal_t x = vIn.x * MPI2;\n" - << "\t\treal_t y = vIn.y * MPI2;\n" - << "\t\treal_t tanhsin = sin(y);\n" - << "\t\treal_t tanhcos = cos(y);\n" - << "\t\treal_t tanhsinh = sinh(x);\n" - << "\t\treal_t tanhcosh = cosh(x);\n" - << "\t\treal_t tanhden = " << weight << " / Zeps(tanhcos + tanhcosh);\n" - << "\n" - << "\t\tvOut.x = tanhden * tanhsinh;\n" - << "\t\tvOut.y = tanhden * tanhsin;\n" - << "\t\tvOut.z = " << DefaultZCl() - << "\t}\n"; - return ss.str(); + if (Compat::m_Compat) + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\treal_t tanhsin = sin((real_t)(2.0) * vIn.y);\n" + << "\t\treal_t tanhcos = cos((real_t)(2.0) * vIn.y);\n" + << "\t\treal_t tanhsinh = sinh((real_t)(2.0) * vIn.x);\n" + << "\t\treal_t tanhcosh = cosh((real_t)(2.0) * vIn.x);\n" + << "\t\treal_t tanhden = (real_t)(1.0) / Zeps(tanhcos + tanhcosh);\n" + << "\n" + << "\t\tvOut.x = " << weight << " * tanhden * tanhsinh;\n" + << "\t\tvOut.y = " << weight << " * tanhden * tanhsin;\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } + else + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\treal_t x = vIn.x * MPI2;\n" + << "\t\treal_t y = vIn.y * MPI2;\n" + << "\t\treal_t tanhsin = sin(y);\n" + << "\t\treal_t tanhcos = cos(y);\n" + << "\t\treal_t tanhsinh = sinh(x);\n" + << "\t\treal_t tanhcosh = cosh(x);\n" + << "\t\treal_t tanhden = " << weight << " / Zeps(tanhcos + tanhcosh);\n" + << "\n" + << "\t\tvOut.x = tanhden * tanhsinh;\n" + << "\t\tvOut.y = tanhden * tanhsin;\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } } virtual vector OpenCLGlobalFuncNames() const override @@ -6714,37 +7004,72 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T sechsin, sechcos, sechsinh, sechcosh, sechden; - T x = helper.In.x * M_PI4; - T y = helper.In.y * M_PI4; - sincos(y, &sechsin, &sechcos); - sechsinh = std::sinh(x); - sechcosh = std::cosh(x); - sechden = (m_Weight * 2) / Zeps(std::cos(y * 2) + std::cosh(x * 2)); - helper.Out.x = sechden * sechcos * sechcosh; - helper.Out.y = sechden * sechsin * sechsinh; + if (Compat::m_Compat) + { + T sechsin, sechcos, sechsinh, sechcosh, sechden; + sincos(helper.In.y, &sechsin, &sechcos); + sechsinh = std::sinh(helper.In.x); + sechcosh = std::cosh(helper.In.x); + sechden = 2 / Zeps(std::cos(2 * helper.In.y) + std::cosh(2 * helper.In.x)); + helper.Out.x = m_Weight * sechden * sechcos * sechcosh; + helper.Out.y = -(m_Weight * sechden * sechsin * sechsinh); + } + else + { + T sechsin, sechcos, sechsinh, sechcosh, sechden; + T x = helper.In.x * M_PI4; + T y = helper.In.y * M_PI4; + sincos(y, &sechsin, &sechcos); + sechsinh = std::sinh(x); + sechcosh = std::cosh(x); + sechden = m_Weight * (2 / Zeps(std::cos(y * 2) + std::cosh(x * 2))); + helper.Out.x = sechden * sechcos * sechcosh; + helper.Out.y = sechden * sechsin * sechsinh; + } + helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { - ostringstream ss; - string weight = WeightDefineString(); - intmax_t varIndex = IndexInXform(); - ss << "\t{\n" - << "\t\treal_t x = vIn.x * MPI4;\n" - << "\t\treal_t y = vIn.y * MPI4;\n" - << "\t\treal_t sechsin = sin(y);\n" - << "\t\treal_t sechcos = cos(y);\n" - << "\t\treal_t sechsinh = sinh(x);\n" - << "\t\treal_t sechcosh = cosh(x);\n" - << "\t\treal_t sechden = (" << weight << " * (real_t)(2.0)) / Zeps(cos(y * (real_t)(2.0)) + cosh(x * (real_t)(2.0)));\n" - << "\n" - << "\t\tvOut.x = sechden * sechcos * sechcosh;\n" - << "\t\tvOut.y = sechden * sechsin * sechsinh;\n" - << "\t\tvOut.z = " << DefaultZCl() - << "\t}\n"; - return ss.str(); + if (Compat::m_Compat) + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\treal_t sechsin = sin(vIn.y);\n" + << "\t\treal_t sechcos = cos(vIn.y);\n" + << "\t\treal_t sechsinh = sinh(vIn.x);\n" + << "\t\treal_t sechcosh = cosh(vIn.x);\n" + << "\t\treal_t sechden = (real_t)(2.0) / Zeps(cos((real_t)(2.0) * vIn.y) + cosh((real_t)(2.0) * vIn.x));\n" + << "\n" + << "\t\tvOut.x = " << weight << " * sechden * sechcos * sechcosh;\n" + << "\t\tvOut.y = -(" << weight << " * sechden * sechsin * sechsinh);\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } + else + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\treal_t x = vIn.x * MPI4;\n" + << "\t\treal_t y = vIn.y * MPI4;\n" + << "\t\treal_t sechsin = sin(y);\n" + << "\t\treal_t sechcos = cos(y);\n" + << "\t\treal_t sechsinh = sinh(x);\n" + << "\t\treal_t sechcosh = cosh(x);\n" + << "\t\treal_t sechden = " << weight << " * ((real_t)(2.0) / Zeps(cos(y * (real_t)(2.0)) + cosh(x * (real_t)(2.0))));\n" + << "\n" + << "\t\tvOut.x = sechden * sechcos * sechcosh;\n" + << "\t\tvOut.y = sechden * sechsin * sechsinh;\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } } virtual vector OpenCLGlobalFuncNames() const override @@ -6766,37 +7091,72 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T cschsin, cschcos, cschsinh, cschcosh, cschden; - T x = helper.In.x * M_PI4; - T y = helper.In.y * M_PI4; - sincos(y, &cschsin, &cschcos); - cschsinh = std::sinh(x); - cschcosh = std::cosh(x); - cschden = (m_Weight * 2) / Zeps(std::cosh(2 * x) - std::cos(2 * y)); - helper.Out.x = cschden * cschsinh * cschcos; - helper.Out.y = cschden * cschcosh * cschsin; + if (Compat::m_Compat) + { + T cschsin, cschcos, cschsinh, cschcosh, cschden; + sincos(helper.In.y, &cschsin, &cschcos); + cschsinh = std::sinh(helper.In.x); + cschcosh = std::cosh(helper.In.x); + cschden = 2 / Zeps(std::cosh(2 * helper.In.x) - std::cos(2 * helper.In.y)); + helper.Out.x = m_Weight * cschden * cschsinh * cschcos; + helper.Out.y = -(m_Weight * cschden * cschcosh * cschsin); + } + else + { + T cschsin, cschcos, cschsinh, cschcosh, cschden; + T x = helper.In.x * M_PI4; + T y = helper.In.y * M_PI4; + sincos(y, &cschsin, &cschcos); + cschsinh = std::sinh(x); + cschcosh = std::cosh(x); + cschden = m_Weight * (2 / Zeps(std::cosh(2 * x) - std::cos(2 * y))); + helper.Out.x = cschden * cschsinh * cschcos; + helper.Out.y = cschden * cschcosh * cschsin; + } + helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { - ostringstream ss; - string weight = WeightDefineString(); - intmax_t varIndex = IndexInXform(); - ss << "\t{\n" - << "\t\treal_t x = vIn.x * MPI4;\n" - << "\t\treal_t y = vIn.y * MPI4;\n" - << "\t\treal_t cschsin = sin(y);\n" - << "\t\treal_t cschcos = cos(y);\n" - << "\t\treal_t cschsinh = sinh(x);\n" - << "\t\treal_t cschcosh = cosh(x);\n" - << "\t\treal_t cschden = (" << weight << " * (real_t)(2.0)) / Zeps(cosh((real_t)(2.0) * x) - cos((real_t)(2.0) * y));\n" - << "\n" - << "\t\tvOut.x = cschden * cschsinh * cschcos;\n" - << "\t\tvOut.y = cschden * cschcosh * cschsin;\n" - << "\t\tvOut.z = " << DefaultZCl() - << "\t}\n"; - return ss.str(); + if (Compat::m_Compat) + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\treal_t cschsin = sin(vIn.y);\n" + << "\t\treal_t cschcos = cos(vIn.y);\n" + << "\t\treal_t cschsinh = sinh(vIn.x);\n" + << "\t\treal_t cschcosh = cosh(vIn.x);\n" + << "\t\treal_t cschden = (real_t)(2.0) / Zeps(cosh((real_t)(2.0) * vIn.x) - cos((real_t)(2.0) * vIn.y));\n" + << "\n" + << "\t\tvOut.x = " << weight << " * cschden * cschsinh * cschcos;\n" + << "\t\tvOut.y = -(" << weight << " * cschden * cschcosh * cschsin);\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } + else + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\treal_t x = vIn.x * MPI4;\n" + << "\t\treal_t y = vIn.y * MPI4;\n" + << "\t\treal_t cschsin = sin(y);\n" + << "\t\treal_t cschcos = cos(y);\n" + << "\t\treal_t cschsinh = sinh(x);\n" + << "\t\treal_t cschcosh = cosh(x);\n" + << "\t\treal_t cschden = " << weight << " * ((real_t)(2.0) / Zeps(cosh((real_t)(2.0) * x) - cos((real_t)(2.0) * y)));\n" + << "\n" + << "\t\tvOut.x = cschden * cschsinh * cschcos;\n" + << "\t\tvOut.y = cschden * cschcosh * cschsin;\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } } virtual vector OpenCLGlobalFuncNames() const override @@ -6818,37 +7178,72 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T cothsin, cothcos, cothsinh, cothcosh, cothden; - T x = helper.In.x * M_PI2; - T y = helper.In.y * M_PI2; - sincos(y, &cothsin, &cothcos); - cothsinh = std::sinh(x); - cothcosh = std::cosh(x); - cothden = m_Weight / Zeps(cothcosh - cothcos); - helper.Out.x = cothden * cothsinh; - helper.Out.y = cothden * cothsin; + if (Compat::m_Compat) + { + T cothsin, cothcos, cothsinh, cothcosh, cothden; + sincos(2 * helper.In.y, &cothsin, &cothcos); + cothsinh = std::sinh(2 * helper.In.x); + cothcosh = std::cosh(2 * helper.In.x); + cothden = 1 / Zeps(cothcosh - cothcos); + helper.Out.x = m_Weight * cothden * cothsinh; + helper.Out.y = m_Weight * cothden * cothsin; + } + else + { + T cothsin, cothcos, cothsinh, cothcosh, cothden; + T x = helper.In.x * M_PI2; + T y = helper.In.y * M_PI2; + sincos(y, &cothsin, &cothcos); + cothsinh = std::sinh(x); + cothcosh = std::cosh(x); + cothden = m_Weight / Zeps(cothcosh - cothcos); + helper.Out.x = cothden * cothsinh; + helper.Out.y = cothden * cothsin; + } + helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { - ostringstream ss; - string weight = WeightDefineString(); - intmax_t varIndex = IndexInXform(); - ss << "\t{\n" - << "\t\treal_t x = vIn.x * MPI2;\n" - << "\t\treal_t y = vIn.y * MPI2;\n" - << "\t\treal_t cothsin = sin(y);\n" - << "\t\treal_t cothcos = cos(y);\n" - << "\t\treal_t cothsinh = sinh(x);\n" - << "\t\treal_t cothcosh = cosh(x);\n" - << "\t\treal_t cothden = " << weight << " / Zeps(cothcosh - cothcos);\n" - << "\n" - << "\t\tvOut.x = cothden * cothsinh;\n" - << "\t\tvOut.y = cothden * cothsin;\n" - << "\t\tvOut.z = " << DefaultZCl() - << "\t}\n"; - return ss.str(); + if (Compat::m_Compat) + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\treal_t cothsin = sin((real_t)(2.0) * vIn.y);\n" + << "\t\treal_t cothcos = cos((real_t)(2.0) * vIn.y);\n" + << "\t\treal_t cothsinh = sinh((real_t)(2.0) * vIn.x);\n" + << "\t\treal_t cothcosh = cosh((real_t)(2.0) * vIn.x);\n" + << "\t\treal_t cothden = (real_t)(1.0) / Zeps(cothcosh - cothcos);\n" + << "\n" + << "\t\tvOut.x = " << weight << " * cothden * cothsinh;\n" + << "\t\tvOut.y = " << weight << " * cothden * cothsin;\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } + else + { + ostringstream ss; + string weight = WeightDefineString(); + intmax_t varIndex = IndexInXform(); + ss << "\t{\n" + << "\t\treal_t x = vIn.x * MPI2;\n" + << "\t\treal_t y = vIn.y * MPI2;\n" + << "\t\treal_t cothsin = sin(y);\n" + << "\t\treal_t cothcos = cos(y);\n" + << "\t\treal_t cothsinh = sinh(x);\n" + << "\t\treal_t cothcosh = cosh(x);\n" + << "\t\treal_t cothden = " << weight << " / Zeps(cothcosh - cothcos);\n" + << "\n" + << "\t\tvOut.x = cothden * cothsinh;\n" + << "\t\tvOut.y = cothden * cothsin;\n" + << "\t\tvOut.z = " << DefaultZCl() + << "\t}\n"; + return ss.str(); + } } virtual vector OpenCLGlobalFuncNames() const override diff --git a/Source/Ember/Xform.h b/Source/Ember/Xform.h index d5ac347..e9391a3 100644 --- a/Source/Ember/Xform.h +++ b/Source/Ember/Xform.h @@ -268,16 +268,15 @@ public: m_HasPost = false; m_HasPreOrRegularVars = false; m_ParentEmber = nullptr; - m_PreVariations.reserve(MAX_VARS_PER_XFORM); - m_Variations.reserve(MAX_VARS_PER_XFORM); - m_PostVariations.reserve(MAX_VARS_PER_XFORM); + m_PreVariations.reserve(8); + m_Variations.reserve(8); + m_PostVariations.reserve(8); CacheColorVals(); count++; } /// /// Add a pointer to a variation which will be deleted on destruction so the caller should not delete. - /// This checks if the total number of variations is less than or equal to MAX_VARS_PER_XFORM. /// It also checks if the variation is already present, in which case it doesn't add. /// If add, set all precalcs. /// @@ -299,23 +298,63 @@ public: else vec = &m_Variations; - if (vec->size() < MAX_VARS_PER_XFORM) + vec->push_back(variation); + + //Flatten must always be last. + for (size_t i = 0; i < vec->size(); i++) { - vec->push_back(variation); - - //Flatten must always be last. - for (size_t i = 0; i < vec->size(); i++) + if ((i != vec->size() - 1) && ((*vec)[i]->Name().find("flatten") != string::npos)) { - if ((i != vec->size() - 1) && ((*vec)[i]->Name().find("flatten") != string::npos)) - { - std::swap((*vec)[i], (*vec)[vec->size() - 1]); - break; - } + std::swap((*vec)[i], (*vec)[vec->size() - 1]); + break; } - - SetPrecalcFlags(); - return true; } + + SetPrecalcFlags(); + return true; + } + + return false; + } + + /// + /// Insert a pointer to a variation, at the specified location, which will be deleted on destruction so the caller should not delete. + /// It also checks if the variation is already present, in which case it doesn't add. + /// If add, set all precalcs. + /// + /// Pointer to a varation to add + /// The index to insert at + /// True if the successful, else false. + bool InsertVariation(Variation* variation, size_t index) + { + if (variation && (GetVariationById(variation->VariationId()) == nullptr)) + { + string name = variation->Name(); + bool pre = name.find("pre_") == 0; + bool post = name.find("post_") == 0; + vector*>* vec; + + if (pre) + vec = &m_PreVariations; + else if (post) + vec = &m_PostVariations; + else + vec = &m_Variations; + + vec->insert(vec->begin() + index, variation); + + //Flatten must always be last. + for (size_t i = 0; i < vec->size(); i++) + { + if ((i != vec->size() - 1) && ((*vec)[i]->Name().find("flatten") != string::npos)) + { + std::swap((*vec)[i], (*vec)[vec->size() - 1]); + break; + } + } + + SetPrecalcFlags(); + return true; } return false; @@ -443,6 +482,36 @@ public: return found; } + /// + /// Remove the variation with the matching ID, but instead of deleting it, return it. + /// Update precalcs if deletion successful. + /// + /// The ID to search for + /// The variation if found, else nullptr. + Variation* RemoveVariationById(eVariationId id) + { + bool found = false; + Variation* var = nullptr; + AllVarsFunc([&](vector*>& variations, bool & keepGoing) + { + for (size_t i = 0; i < variations.size(); i++) + { + if (variations[i] && variations[i]->VariationId() == id) + { + var = variations[i]; + variations.erase(variations.begin() + i); + keepGoing = false; + break; + } + } + }); + + if (var) + SetPrecalcFlags(); + + return var; + } + /// /// Delete the motion elements. /// diff --git a/Source/EmberAnimate/EmberAnimate.cpp b/Source/EmberAnimate/EmberAnimate.cpp index 999d15b..004ebb2 100644 --- a/Source/EmberAnimate/EmberAnimate.cpp +++ b/Source/EmberAnimate/EmberAnimate.cpp @@ -46,6 +46,7 @@ bool EmberAnimate(int argc, _TCHAR* argv[], EmberOptions& opt) vector errorReport; std::recursive_mutex verboseCs; auto fullpath = GetExePath(argv[0]); + Compat::m_Compat = opt.Flam3Compat(); if (opt.EmberCL()) { diff --git a/Source/EmberCL/IterOpenCLKernelCreator.cpp b/Source/EmberCL/IterOpenCLKernelCreator.cpp index 9c92714..0693e52 100644 --- a/Source/EmberCL/IterOpenCLKernelCreator.cpp +++ b/Source/EmberCL/IterOpenCLKernelCreator.cpp @@ -994,6 +994,13 @@ template bool IterOpenCLKernelCreator::IsBuildRequired(const Ember& ember1, const Ember& ember2, bool optAffine) { size_t i, j, xformCount = ember1.TotalXformCount(); + static bool lastCompat = Compat::m_Compat; + + if (lastCompat != Compat::m_Compat) + { + lastCompat = Compat::m_Compat; + return true; + } if (xformCount != ember2.TotalXformCount()) return true; diff --git a/Source/EmberCommon/EmberOptions.h b/Source/EmberCommon/EmberOptions.h index 4df2b1b..8947ed6 100644 --- a/Source/EmberCommon/EmberOptions.h +++ b/Source/EmberCommon/EmberOptions.h @@ -68,6 +68,7 @@ enum class eOptionIDs : et OPT_CW_INTERP_LOOPS, OPT_LOCK_ACCUM, OPT_DUMP_KERNEL, + OPT_FLAM3_COMPAT, //Value args. OPT_NTHREADS,//Int value args. @@ -372,6 +373,7 @@ public: INITBOOLOPTION(CwInterpLoops, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_CW_INTERP_LOOPS, _T("--cwinterploops"), false, SO_NONE, " --cwinterploops Rotate clockwise during interpolation, ignored if --interploops is 0 [default: false].\n")); INITBOOLOPTION(LockAccum, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_LOCK_ACCUM, _T("--lock_accum"), false, SO_NONE, " --lock_accum Lock threads when accumulating to the histogram using the CPU. This will drop performance to that of single threading [default: false].\n")); INITBOOLOPTION(DumpKernel, Eob(eOptionUse::OPT_USE_RENDER, eOptionIDs::OPT_DUMP_KERNEL, _T("--dump_kernel"), false, SO_NONE, " --dump_kernel Print the iteration kernel string when using OpenCL (ignored for CPU) [default: false].\n")); + INITBOOLOPTION(Flam3Compat, Eob(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_FLAM3_COMPAT, _T("--flam3_compat"), false, SO_NONE, " --flam3_compat The behavior of the cos, cosh, cot, coth, csc, csch, sec, sech, sin, sinh, tan and tanh variations are different in flam3/Apophysis versus Chaotica. True for flam3/Apophysis behavior, false for Chaotica behavior [default: false].\n")); //Int. INITINTOPTION(Symmetry, Eoi(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_SYMMETRY, _T("--symmetry"), 0, SO_REQ_SEP, " --symmetry= Set symmetry of result [default: 0].\n")); INITINTOPTION(SheepGen, Eoi(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_SHEEP_GEN, _T("--sheep_gen"), -1, SO_REQ_SEP, " --sheep_gen= Sheep generation of this flame [default: -1].\n")); @@ -531,6 +533,7 @@ public: PARSEBOOLOPTION(eOptionIDs::OPT_CW_INTERP_LOOPS, CwInterpLoops); PARSEBOOLOPTION(eOptionIDs::OPT_LOCK_ACCUM, LockAccum); PARSEBOOLOPTION(eOptionIDs::OPT_DUMP_KERNEL, DumpKernel); + PARSEBOOLOPTION(eOptionIDs::OPT_FLAM3_COMPAT, Flam3Compat); PARSEOPTION(eOptionIDs::OPT_SYMMETRY, Symmetry);//Int args PARSEOPTION(eOptionIDs::OPT_SHEEP_GEN, SheepGen); PARSEOPTION(eOptionIDs::OPT_SHEEP_ID, SheepId); @@ -819,6 +822,7 @@ public: Eob CwInterpLoops; Eob LockAccum; Eob DumpKernel; + Eob Flam3Compat; Eoi Symmetry;//Value int. Eoi SheepGen; diff --git a/Source/EmberGenome/EmberGenome.cpp b/Source/EmberGenome/EmberGenome.cpp index 5719a13..3023261 100644 --- a/Source/EmberGenome/EmberGenome.cpp +++ b/Source/EmberGenome/EmberGenome.cpp @@ -58,6 +58,7 @@ bool EmberGenome(int argc, _TCHAR* argv[], EmberOptions& opt) return true; } + Compat::m_Compat = opt.Flam3Compat(); auto varList = VariationList::Instance(); if (opt.AllVars() || opt.SumVars() || opt.AssignVars() || opt.PpSumVars() || opt.PpAssignVars() || diff --git a/Source/EmberRender/EmberRender.cpp b/Source/EmberRender/EmberRender.cpp index 882f51d..c1fedb5 100644 --- a/Source/EmberRender/EmberRender.cpp +++ b/Source/EmberRender/EmberRender.cpp @@ -48,6 +48,7 @@ bool EmberRender(int argc, _TCHAR* argv[], EmberOptions& opt) unique_ptr> renderer(CreateRenderer(opt.EmberCL() ? eRendererType::OPENCL_RENDERER : eRendererType::CPU_RENDERER, devices, false, 0, emberReport)); vector errorReport = emberReport.ErrorReport(); auto fullpath = GetExePath(argv[0]); + Compat::m_Compat = opt.Flam3Compat(); if (!errorReport.empty()) emberReport.DumpErrorReport(); diff --git a/Source/Fractorium/Fractorium.h b/Source/Fractorium/Fractorium.h index 128b987..b08a316 100644 --- a/Source/Fractorium/Fractorium.h +++ b/Source/Fractorium/Fractorium.h @@ -129,6 +129,9 @@ public: bool DrawAllPost(); bool LocalPivot(); + //Info. + void ReorderVariations(QTreeWidgetItem* item); + public slots: //Dock. void OnDockTopLevelChanged(bool topLevel); diff --git a/Source/Fractorium/Fractorium.ui b/Source/Fractorium/Fractorium.ui index db0668e..0753fad 100644 --- a/Source/Fractorium/Fractorium.ui +++ b/Source/Fractorium/Fractorium.ui @@ -6540,7 +6540,7 @@ - + 0 @@ -6562,6 +6562,12 @@ false + + QAbstractItemView::InternalMove + + + Qt::MoveAction + QAbstractItemView::SingleSelection @@ -8727,6 +8733,11 @@ QTreeWidget
LibraryTreeWidget.h
+ + InfoTreeWidget + QTreeWidget +
LibraryTreeWidget.h
+
LibraryDockWidget diff --git a/Source/Fractorium/FractoriumEmberController.h b/Source/Fractorium/FractoriumEmberController.h index f396845..e17139a 100644 --- a/Source/Fractorium/FractoriumEmberController.h +++ b/Source/Fractorium/FractoriumEmberController.h @@ -262,6 +262,7 @@ public: //Info. virtual void FillSummary() { } + virtual void ReorderVariations(QTreeWidgetItem* item) { } //Rendering/progress. virtual bool Render() { return false; } @@ -556,6 +557,7 @@ public: //Info. virtual void FillSummary() override; + virtual void ReorderVariations(QTreeWidgetItem* item) override; //Rendering/progress. virtual bool Render() override; diff --git a/Source/Fractorium/FractoriumInfo.cpp b/Source/Fractorium/FractoriumInfo.cpp index 53722f6..014cb2c 100644 --- a/Source/Fractorium/FractoriumInfo.cpp +++ b/Source/Fractorium/FractoriumInfo.cpp @@ -21,6 +21,7 @@ void Fractorium::InitInfoUI() ui.SummaryTable->setItem(4, 0, m_InfoXformCountItem = new QTableWidgetItem("")); ui.SummaryTable->setItem(5, 0, m_InfoFinalXformItem = new QTableWidgetItem("")); ui.InfoTabWidget->setCurrentIndex(0);//Make summary tab focused by default. + ui.SummaryTree->SetMainWindow(this); } /// @@ -75,6 +76,8 @@ void FractoriumEmberController::FillSummary() QColor color; auto table = m_Fractorium->ui.SummaryTable; auto tree = m_Fractorium->ui.SummaryTree; + auto nondraggable = Qt::ItemIsEnabled | Qt::ItemIsSelectable; + auto draggable = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled; tree->blockSignals(true); tree->clear(); m_Fractorium->m_InfoNameItem->setText(m_Ember.m_Name.c_str()); @@ -109,8 +112,10 @@ void FractoriumEmberController::FillSummary() item1->setText(0, "Final xform"); item1->setText(1, xform->m_Name.c_str()); + item1->setFlags(nondraggable); auto affineItem = new QTreeWidgetItem(item1); affineItem->setText(0, "Affine"); + affineItem->setFlags(nondraggable); if (xform->m_Affine.IsZero()) as += " Empty"; @@ -129,6 +134,7 @@ void FractoriumEmberController::FillSummary() auto colorIndexItem = new QTreeWidgetItem(item1); colorIndexItem->setText(0, "Color index"); colorIndexItem->setText(1, QLocale::system().toString(xform->m_ColorX, pc, p)); + colorIndexItem->setFlags(nondraggable | Qt::ItemNeverHasChildren); color = ColorIndexToQColor(xform->m_ColorX); color.setAlphaF(xform->m_Opacity); colorIndexItem->setBackgroundColor(1, color); @@ -136,18 +142,25 @@ void FractoriumEmberController::FillSummary() auto colorSpeedItem = new QTreeWidgetItem(item1); colorSpeedItem->setText(0, "Color speed"); colorSpeedItem->setText(1, QLocale::system().toString(xform->m_ColorSpeed, pc, p)); + colorSpeedItem->setFlags(nondraggable | Qt::ItemNeverHasChildren); auto opacityItem = new QTreeWidgetItem(item1); opacityItem->setText(0, "Opacity"); opacityItem->setText(1, QLocale::system().toString(xform->m_Opacity, pc, p)); + opacityItem->setFlags(nondraggable | Qt::ItemNeverHasChildren); auto dcItem = new QTreeWidgetItem(item1); dcItem->setText(0, "Direct color"); dcItem->setText(1, QLocale::system().toString(xform->m_DirectColor, pc, p)); + dcItem->setFlags(nondraggable | Qt::ItemNeverHasChildren); + + if (dcItem->text(0) != tree->LastNonVarField()) + throw "Last info tree non-variation index did not match expected value"; while (auto var = xform->GetVariation(i++)) { - auto vitem = new QTreeWidgetItem(item1); + auto vitem = new VariationTreeWidgetItem(var->VariationId(), item1); vitem->setText(0, QString::fromStdString(var->Name())); vitem->setText(1, QLocale::system().toString(var->m_Weight, pc, vp).rightJustified(vlen, ' ')); + vitem->setFlags(draggable); if (auto parVar = dynamic_cast*>(var)) { @@ -160,6 +173,7 @@ void FractoriumEmberController::FillSummary() auto pitem = new QTreeWidgetItem(vitem); pitem->setText(0, params[j].Name().c_str()); pitem->setText(1, QLocale::system().toString(params[j].ParamVal(), pc, vp).rightJustified(vlen, ' ')); + pitem->setFlags(nondraggable); } } } @@ -177,6 +191,57 @@ void Fractorium::FillSummary() m_Controller->FillSummary(); } +/// +/// Reorder the variations of the xform for the passed in tree widget item. +/// Read the newly reordered variation items in order, removing each from the xform +/// corresponding to the passed in item, and storing them in a vector. Then re-add those variation +/// pointers back to the xform in the same order they were removed. +/// This will be called after the user performs a drag and drop operation on the variations in the +/// info tree. So the variations will be in the newly desired order. +/// +/// Pointer to the parent (xform level) tree widget item which contains the variation item being dragged +template +void FractoriumEmberController::ReorderVariations(QTreeWidgetItem* item) +{ + auto tree = m_Fractorium->ui.SummaryTree; + auto xfindex = tree->indexOfTopLevelItem(item) / 2;//Blank lines each count as one. + + if (auto xform = m_Ember.GetTotalXform(xfindex)) + { + vector*> vars; + vars.reserve(xform->TotalVariationCount()); + Update([&] + { + int i = 0; + + while (auto ch = item->child(i)) + { + if (ch->text(0) == tree->LastNonVarField()) + { + i++; + + while (auto varch = dynamic_cast(item->child(i++))) + if (auto var = xform->RemoveVariationById(varch->Id())) + vars.push_back(var); + + for (auto& var : vars) + xform->AddVariation(var); + + break; + } + + i++; + } + + }, true, eProcessAction::FULL_RENDER); + } +} + +void Fractorium::ReorderVariations(QTreeWidgetItem* item) +{ + m_Controller->ReorderVariations(item); +} + /// /// Update the histogram bounds display labels. /// This shows the user the actual bounds of what's diff --git a/Source/Fractorium/FractoriumMenus.cpp b/Source/Fractorium/FractoriumMenus.cpp index 973966c..f2c7e3f 100644 --- a/Source/Fractorium/FractoriumMenus.cpp +++ b/Source/Fractorium/FractoriumMenus.cpp @@ -1076,12 +1076,15 @@ void Fractorium::OnActionOptions(bool checked) bool ec = m_Settings->EarlyClip(); bool yup = m_Settings->YAxisUp(); bool trans = m_Settings->Transparency(); + bool compat = m_Settings->Flam3Compat(); if (m_OptionsDialog->exec()) { bool updatePreviews = ec != m_Settings->EarlyClip() || yup != m_Settings->YAxisUp() || - trans != m_Settings->Transparency(); + trans != m_Settings->Transparency() || + compat != m_Settings->Flam3Compat(); + Compat::m_Compat = m_Settings->Flam3Compat(); SyncOptionsToToolbar();//This won't trigger a recreate, the call below handles it. ShutdownAndRecreateFromOptions(updatePreviews);//This will recreate the controller and/or the renderer from the options if necessary, then start the render timer. } diff --git a/Source/Fractorium/FractoriumSettings.cpp b/Source/Fractorium/FractoriumSettings.cpp index d2f924f..292c460 100644 --- a/Source/Fractorium/FractoriumSettings.cpp +++ b/Source/Fractorium/FractoriumSettings.cpp @@ -122,6 +122,8 @@ void FractoriumSettings::EnsureDefaults() if (value(SHAREDTEXTURE).toString() == "")//Set this to true if the setting is missing because it only needs to be false for the rare system that has problems with shared textures. SharedTexture(true); + + Compat::m_Compat = Flam3Compat(); } /// @@ -200,6 +202,9 @@ void FractoriumSettings::LoadLast(bool b) { setValue(LOAD bool FractoriumSettings::RotateAndScale() { return value(ROTSCALE).toBool(); } void FractoriumSettings::RotateAndScale(bool b) { setValue(ROTSCALE, b); } +bool FractoriumSettings::Flam3Compat() { return value(FLAM3COMPAT).toBool(); } +void FractoriumSettings::Flam3Compat(bool b) { setValue(FLAM3COMPAT, b); } + /// /// Sequence generation settings. /// diff --git a/Source/Fractorium/FractoriumSettings.h b/Source/Fractorium/FractoriumSettings.h index 1004781..85f9def 100644 --- a/Source/Fractorium/FractoriumSettings.h +++ b/Source/Fractorium/FractoriumSettings.h @@ -30,6 +30,7 @@ #define OPENCLQUALITY "render/openclquality" #define LOADLAST "render/loadlastonstart" #define ROTSCALE "render/rotateandscale" +#define FLAM3COMPAT "render/flam3compat" #define STAGGER "sequence/stagger" #define STAGGERMAX "sequence/staggermax" @@ -180,6 +181,9 @@ public: bool RotateAndScale(); void RotateAndScale(bool b); + bool Flam3Compat(); + void Flam3Compat(bool b); + double Stagger(); void Stagger(double i); diff --git a/Source/Fractorium/LibraryTreeWidget.cpp b/Source/Fractorium/LibraryTreeWidget.cpp index b0f81de..9a74640 100644 --- a/Source/Fractorium/LibraryTreeWidget.cpp +++ b/Source/Fractorium/LibraryTreeWidget.cpp @@ -93,4 +93,112 @@ void LibraryTreeWidget::dropEvent(QDropEvent* de) m_Fractorium->m_Controller->MoveLibraryItems(items, row); } -} \ No newline at end of file +} + +/// +/// Set a pointer to the main window. +/// +/// Pointer to the main Fractorium object +void InfoTreeWidget::SetMainWindow(Fractorium* f) +{ + m_Fractorium = f; +} + +/// +/// Called on each mouse movement while dragging, validate whether the area +/// being dragged over can be dropped on. +/// Can only drop on like (pre/reg/post) variation section of the same xform +/// of the variation being dragged. +/// +/// Pointer to the drag move event +void InfoTreeWidget::dragMoveEvent(QDragMoveEvent* dme) +{ + QModelIndex index = indexAt(dme->pos()); + + if (!index.isValid())//Don't process drop because it's outside of the droppable area. + { + dme->ignore(); + return; + } + + QList dragItems = selectedItems(); + + if (dragItems.size()) + { + auto drag0 = dragItems[0]; + + if (auto itemat = itemFromIndex(index)) + { + auto dragpre = drag0->text(0).startsWith("pre_", Qt::CaseInsensitive); + auto droppre = itemat->text(0).startsWith("pre_", Qt::CaseInsensitive); + auto dragpost = drag0->text(0).startsWith("post_", Qt::CaseInsensitive); + auto droppost = itemat->text(0).startsWith("post_", Qt::CaseInsensitive); + + if (auto par = itemat->parent()) + { + if (drag0->parent() == par && + (par->text(0).startsWith("xform ", Qt::CaseInsensitive) || + par->text(0).startsWith("final", Qt::CaseInsensitive))) + { + if (auto vitemat = dynamic_cast(itemat)) + { + bool dopre = dragpre && droppre; + bool dopost = dragpost && droppost; + bool doreg = !dragpre && !droppre && !dragpost && !droppost; + + if (dopre || doreg || dopost) + { + QTreeWidget::dragMoveEvent(dme); + return; + } + } + } + } + } + } + + dme->ignore(); +} + +/// +/// Process the drop event to allow for moving items around inside of the tree. +/// This will only allow variations to be moved around within the variation section of the tree +/// and nowhere else. +/// +/// Pointer to the QDropEvent object +void InfoTreeWidget::dropEvent(QDropEvent* de) +{ + QModelIndex droppedIndex = indexAt(de->pos()); + auto items = selectionModel()->selectedRows(); + + if (!droppedIndex.isValid())//Don't process drop because it's outside of the droppable area. + { + de->ignore(); + return; + } + else if (!items.empty())//Actually do the drop and move the item to a new location. + { + QList dragItems = selectedItems(); + + if (dragItems.size()) + { + auto drag0 = dragItems[0]; + auto itemat = itemFromIndex(droppedIndex); + + if (auto par = itemat->parent()) + { + if (auto vdropitem = dynamic_cast(itemat)) + { + if (auto vdragitem = dynamic_cast(drag0)) + { + QTreeWidget::dropEvent(de);//This internally changes the order of the items. + m_Fractorium->ReorderVariations(par); + return; + } + } + } + } + + de->ignore(); + } +} diff --git a/Source/Fractorium/LibraryTreeWidget.h b/Source/Fractorium/LibraryTreeWidget.h index 83b7458..60b2dc4 100644 --- a/Source/Fractorium/LibraryTreeWidget.h +++ b/Source/Fractorium/LibraryTreeWidget.h @@ -26,4 +26,29 @@ protected: virtual void dropEvent(QDropEvent* de) override; Fractorium* m_Fractorium = nullptr; -}; \ No newline at end of file +}; + + +class InfoTreeWidget : public QTreeWidget +{ + Q_OBJECT +public: + /// + /// Constructor that passes p to the parent. + /// + /// The parent widget + explicit InfoTreeWidget(QWidget* p = nullptr) + : QTreeWidget(p) + { + } + + void SetMainWindow(Fractorium* f); + const QString& LastNonVarField() const { return m_LastNonVarField; } + +protected: + virtual void dropEvent(QDropEvent* de) override; + virtual void dragMoveEvent(QDragMoveEvent* dme) override; + + Fractorium* m_Fractorium = nullptr; + QString m_LastNonVarField = "Direct color";//It is critical to update this if any more fields are ever added before the variations start. +}; diff --git a/Source/Fractorium/OptionsDialog.cpp b/Source/Fractorium/OptionsDialog.cpp index 10432f9..ab6910e 100644 --- a/Source/Fractorium/OptionsDialog.cpp +++ b/Source/Fractorium/OptionsDialog.cpp @@ -78,6 +78,7 @@ bool FractoriumOptionsDialog::Png16Bit() { return ui.Png16BitCheckBox->isChecked bool FractoriumOptionsDialog::AutoUnique() { return ui.AutoUniqueCheckBox->isChecked(); } bool FractoriumOptionsDialog::LoadLast() { return ui.LoadLastOnStartCheckBox->isChecked(); } bool FractoriumOptionsDialog::RotateAndScale() { return ui.RotateAndScaleCheckBox->isChecked(); } +bool FractoriumOptionsDialog::Flam3Compat() { return ui.Flam3CompatCheckBox->isChecked(); } uint FractoriumOptionsDialog::ThreadCount() { return ui.ThreadCountSpin->value(); } uint FractoriumOptionsDialog::RandomCount() { return ui.RandomCountSpin->value(); } uint FractoriumOptionsDialog::CpuQuality() { return ui.CpuQualitySpin->value(); } @@ -196,6 +197,7 @@ void FractoriumOptionsDialog::GuiToData() m_Settings->RandomCount(RandomCount()); m_Settings->LoadLast(LoadLast()); m_Settings->RotateAndScale(RotateAndScale()); + m_Settings->Flam3Compat(Flam3Compat()); m_Settings->CpuQuality(CpuQuality()); m_Settings->OpenClQuality(OpenClQuality()); m_Settings->CpuSubBatch(ui.CpuSubBatchSpin->value()); @@ -236,6 +238,7 @@ void FractoriumOptionsDialog::DataToGui() ui.RandomCountSpin->setValue(m_Settings->RandomCount()); ui.LoadLastOnStartCheckBox->setChecked(m_Settings->LoadLast()); ui.RotateAndScaleCheckBox->setChecked(m_Settings->RotateAndScale()); + ui.Flam3CompatCheckBox->setChecked(m_Settings->Flam3Compat()); ui.CpuQualitySpin->setValue(m_Settings->CpuQuality()); ui.OpenCLQualitySpin->setValue(m_Settings->OpenClQuality()); ui.CpuSubBatchSpin->setValue(m_Settings->CpuSubBatch()); diff --git a/Source/Fractorium/OptionsDialog.h b/Source/Fractorium/OptionsDialog.h index c8d3842..74cf598 100644 --- a/Source/Fractorium/OptionsDialog.h +++ b/Source/Fractorium/OptionsDialog.h @@ -38,6 +38,7 @@ public: bool AutoUnique(); bool LoadLast(); bool RotateAndScale(); + bool Flam3Compat(); uint ThreadCount(); uint RandomCount(); uint CpuQuality(); diff --git a/Source/Fractorium/OptionsDialog.ui b/Source/Fractorium/OptionsDialog.ui index d69a2c3..ba3f9a6 100644 --- a/Source/Fractorium/OptionsDialog.ui +++ b/Source/Fractorium/OptionsDialog.ui @@ -7,7 +7,7 @@ 0 0 546 - 490 + 512 @@ -538,6 +538,16 @@ + + + + <html><head/><body><p>The behavior of the cos, cosh, cot, coth, csc, csch, sec, sech, sin, sinh, tan and tanh variations are different in flam3/Apophysis versus Chaotica.</p><p>Checked: use the Apophysis behavior.</p><p>Unchecked: use the Chaotica behavior.</p></body></html> + + + Flam3 Compatibility + + +