mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2026-06-09 14:51:58 -04:00
--User changes
-Support 4k monitors, and in general, properly scale any monitor that is not HD. -Allow for a spatial filter of radius zero, which means do not use a spatial filter. -Add new variations: concentric, cpow3, helicoid, helix, rand_cubes, sphereblur. -Use a new method for computing elliptic which is more precise. Developed by Discord user Claude. -Remove the 8 variation per xform limitation on the GPU. -Allow for loading the last flame file on startup, rather than randoms. -Use two different default quality values in the interactive renderer, one each for CPU and GPU. -Creating linked xforms was using non-standard behavior. Make it match Apo and also support creating multiple linked xforms at once. --Bug fixes -No variations in an xform used to have the same behavior as a single linear variation with weight 1. While sensible, this breaks backward compatibility. No variations now sets the output point to zeroes. -Prevent crashing the program when adjusting a value on the main window while a final render is in progress. -The xaos table was inverted. --Code changes -Convert projects to Visual Studio 2017. -Change bad vals from +- 1e10 to +-1e20. -Reintroduce the symmetry tag in xforms for legacy support in programs that do not use color_speed. -Compiler will not let us use default values in templated member functions anymore.
This commit is contained in:
@@ -181,6 +181,19 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reserve the underlying xforms vector to contain the specified capacity.
|
||||
/// This should be called at the start of scenarios where xforms are added and their pointers
|
||||
/// are used in the process. That way no resizing takes place and the pointers remain valid.
|
||||
/// No action is taken if i is less than the existing capacity.
|
||||
/// </summary>
|
||||
/// <param name="i">The capacity to reserve</param>
|
||||
void Reserve(size_t i)
|
||||
{
|
||||
if (i > m_Xforms.capacity())
|
||||
m_Xforms.reserve(i);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a copy of a new xform to the xforms vector.
|
||||
/// </summary>
|
||||
@@ -201,6 +214,7 @@ public:
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
Xform<T> xform;
|
||||
xform.AddVariation(m_VariationList->GetVariationCopy(eVariationId::VAR_LINEAR));
|
||||
AddXform(xform);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ static void sincos(float x, float* s, float* c)
|
||||
|
||||
namespace EmberNs
|
||||
{
|
||||
#define EMBER_VERSION "1.0.0.6"
|
||||
#define EMBER_VERSION "1.0.0.7"
|
||||
#define EPS6 T(1e-6)
|
||||
#define EPS std::numeric_limits<T>::epsilon()//Apoplugin.h uses -20, but it's more mathematically correct to do it this way.
|
||||
#define ISAAC_SIZE 4
|
||||
@@ -60,7 +60,7 @@ namespace EmberNs
|
||||
#define XC(c) (reinterpret_cast<const xmlChar*>(c))
|
||||
#define CX(c) (reinterpret_cast<char*>(c))
|
||||
#define CCX(c) (reinterpret_cast<const char*>(c))
|
||||
#define BadVal(x) (((x) != (x)) || ((x) > 1e10) || ((x) < -1e10))
|
||||
#define BadVal(x) (((x) != (x)) || ((x) > 1e20) || ((x) < -1e20))
|
||||
#define Vlen(x) (sizeof(x) / sizeof(*x))
|
||||
#define SQR(x) ((x) * (x))
|
||||
#define CUBE(x) ((x) * (x) * (x))
|
||||
@@ -72,17 +72,17 @@ namespace EmberNs
|
||||
#define CURVES_LENGTH_M1 65535.0f
|
||||
#define ONE_OVER_CURVES_LENGTH_M1 1.525902189669e-5f
|
||||
#define EMPTYFIELD -9999
|
||||
typedef std::chrono::high_resolution_clock Clock;
|
||||
typedef std::chrono::duration<double, std::ratio<1, 1000>> DoubleMs;
|
||||
typedef std::chrono::time_point<Clock, DoubleMs> DoubleMsTimePoint;
|
||||
static inline DoubleMsTimePoint NowMsD() { return time_point_cast<DoubleMs>(Clock::now()); }
|
||||
static inline size_t NowMs() { return duration_cast<milliseconds>(Clock::now().time_since_epoch()).count(); }
|
||||
typedef uint et;
|
||||
typedef std::lock_guard <std::recursive_mutex> rlg;
|
||||
|
||||
/// <summary>
|
||||
/// Thin wrapper around getting the current time in milliseconds.
|
||||
/// </summary>
|
||||
typedef std::chrono::high_resolution_clock Clock;
|
||||
typedef std::chrono::duration<double, std::ratio<1, 1000>> DoubleMs;
|
||||
typedef std::chrono::time_point<Clock, DoubleMs> DoubleMsTimePoint;
|
||||
static inline DoubleMsTimePoint NowMsD() { return time_point_cast<DoubleMs>(Clock::now()); }
|
||||
static inline size_t NowMs() { return duration_cast<milliseconds>(Clock::now().time_since_epoch()).count(); }
|
||||
|
||||
#ifndef byte
|
||||
typedef unsigned char byte;
|
||||
|
||||
@@ -500,7 +500,8 @@ string EmberToXml<T>::ToString(Xform<T>& xform, size_t xformCount, bool isFinal,
|
||||
|
||||
if (!doMotion || xform.m_ColorSpeed != EMPTYFIELD) os << "color_speed=\"" << xform.m_ColorSpeed << "\" ";
|
||||
|
||||
//os << "symmetry=\"" << fabs(xform.m_ColorSpeed - 1) * 2 << "\" ";//Legacy support.
|
||||
//Legacy support.
|
||||
os << "symmetry=\"" << 1 - (xform.m_ColorSpeed * 2) << "\" ";
|
||||
|
||||
if (!doMotion)
|
||||
{
|
||||
|
||||
@@ -29,7 +29,7 @@ public:
|
||||
|
||||
bool Save(const string& filename, Ember<T>& ember, size_t printEditDepth, bool doEdits, bool hexPalette, bool append = false, bool start = false, bool finish = false);
|
||||
template <typename Alloc, template <typename, typename> class C>
|
||||
bool Save(const string& filename, C<Ember<T>, Alloc>& embers, size_t printEditDepth, bool doEdits, bool hexPalette, bool append = false, bool start = false, bool finish = false);
|
||||
bool Save(const string& filename, C<Ember<T>, Alloc>& embers, size_t printEditDepth, bool doEdits, bool hexPalette, bool append, bool start, bool finish);
|
||||
string ToString(Ember<T>& ember, const string& extraAttributes, size_t printEditDepth, bool doEdits, bool hexPalette = true);
|
||||
xmlDocPtr CreateNewEditdoc(Ember<T>* parent0, Ember<T>* parent1, const string& action, const string& nick, const string& url, const string& id, const string& comment, intmax_t sheepGen = 0, intmax_t sheepId = 0);
|
||||
|
||||
|
||||
@@ -806,6 +806,12 @@ bool Renderer<T, bucketT>::Alloc(bool histOnly)
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_StandardIterator.get())
|
||||
m_StandardIterator = make_unique<StandardIterator<T>>();
|
||||
|
||||
if (!m_XaosIterator.get())
|
||||
m_XaosIterator = make_unique<XaosIterator<T>>();
|
||||
|
||||
if (lock)
|
||||
LeaveResize();
|
||||
|
||||
|
||||
@@ -107,6 +107,14 @@ public:
|
||||
{
|
||||
do
|
||||
{
|
||||
if (!m_FilterRadius)
|
||||
{
|
||||
m_Filter.resize(1);
|
||||
m_Filter[0] = 1;
|
||||
m_FinalFilterWidth = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
T fw = T(2.0) * m_Support * m_Supersample * m_FilterRadius / m_PixelAspectRatio;
|
||||
T adjust, ii, jj;
|
||||
int fwidth = int(fw) + 1;
|
||||
|
||||
@@ -186,6 +186,21 @@ public:
|
||||
return static_cast<double>(temp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Integer hash function from http://burtleburtle.net/bob/hash/integer.html
|
||||
/// </summary>
|
||||
/// <param name="a">The value to hash</param>
|
||||
/// <returns>The hashed value</returns>
|
||||
static T Hash(int a)
|
||||
{
|
||||
a = (a ^ 61) ^ (a >> 16);
|
||||
a = a + (a << 3);
|
||||
a = a ^ (a >> 4);
|
||||
a = a * 0x27d4eb2d;
|
||||
a = a ^ (a >> 15);
|
||||
return (T)a / std::numeric_limits<int>::max();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve information about a piece of shared data by looking
|
||||
/// up its name.
|
||||
|
||||
@@ -39,12 +39,16 @@ enum class eVariationAssignType : et
|
||||
ASSIGNTYPE_SUM
|
||||
};
|
||||
|
||||
#define WEIGHT_PREFIX "parVars[WEIGHT_"
|
||||
|
||||
/// <summary>
|
||||
/// Complete list of every variation class ID.
|
||||
/// </summary>
|
||||
enum class eVariationId : et
|
||||
{
|
||||
VAR_ARCH,
|
||||
//VAR_ARCSINH,
|
||||
//VAR_ARCTANH,
|
||||
VAR_AUGER ,
|
||||
VAR_BARYCENTROID,
|
||||
VAR_BCIRCLE ,
|
||||
@@ -90,6 +94,7 @@ enum class eVariationId : et
|
||||
VAR_CIRCLIZE2 ,
|
||||
VAR_CIRCUS,
|
||||
VAR_COLLIDEOSCOPE,
|
||||
VAR_CONCENTRIC ,
|
||||
VAR_CONIC ,
|
||||
VAR_COS ,
|
||||
VAR_COS_WRAP ,
|
||||
@@ -103,6 +108,7 @@ enum class eVariationId : et
|
||||
VAR_COTQ ,
|
||||
VAR_CPOW ,
|
||||
VAR_CPOW2 ,
|
||||
VAR_CPOW3 ,
|
||||
VAR_CRACKLE ,
|
||||
VAR_CRESCENTS ,
|
||||
VAR_CROB ,
|
||||
@@ -180,6 +186,8 @@ enum class eVariationId : et
|
||||
VAR_HANDKERCHIEF,
|
||||
VAR_HEART ,
|
||||
VAR_HEAT,
|
||||
VAR_HELICOID,
|
||||
VAR_HELIX,
|
||||
VAR_HEMISPHERE ,
|
||||
VAR_HEXAPLAY3D ,
|
||||
VAR_HEXCROP ,
|
||||
@@ -275,6 +283,7 @@ enum class eVariationId : et
|
||||
VAR_PSPHERE ,
|
||||
VAR_Q_ODE,
|
||||
VAR_RADIAL_BLUR ,
|
||||
VAR_RAND_CUBES ,
|
||||
VAR_RATIONAL3 ,
|
||||
VAR_RAYS ,
|
||||
VAR_RBLUR,
|
||||
@@ -309,6 +318,7 @@ enum class eVariationId : et
|
||||
VAR_SINUSOIDAL ,
|
||||
VAR_SINUSOIDAL3D,
|
||||
//VAR_SMARTCROP ,
|
||||
VAR_SPHEREBLUR ,
|
||||
VAR_SPHERICAL ,
|
||||
VAR_SPHERICAL3D ,
|
||||
VAR_SPHERICALN ,
|
||||
@@ -376,6 +386,8 @@ enum class eVariationId : et
|
||||
VAR_ZTRANSLATE,
|
||||
|
||||
VAR_PRE_ARCH,
|
||||
//VAR_PRE_ARCSINH,
|
||||
//VAR_PRE_ARCTANH,
|
||||
VAR_PRE_AUGER,
|
||||
VAR_PRE_BARYCENTROID,
|
||||
VAR_PRE_BCIRCLE,
|
||||
@@ -421,6 +433,7 @@ enum class eVariationId : et
|
||||
VAR_PRE_CIRCLIZE2,
|
||||
VAR_PRE_CIRCUS,
|
||||
VAR_PRE_COLLIDEOSCOPE,
|
||||
VAR_PRE_CONCENTRIC,
|
||||
VAR_PRE_CONIC,
|
||||
VAR_PRE_COS,
|
||||
VAR_PRE_COS_WRAP,
|
||||
@@ -434,6 +447,7 @@ enum class eVariationId : et
|
||||
VAR_PRE_COTQ,
|
||||
VAR_PRE_CPOW,
|
||||
VAR_PRE_CPOW2,
|
||||
VAR_PRE_CPOW3,
|
||||
VAR_PRE_CRACKLE,
|
||||
VAR_PRE_CRESCENTS,
|
||||
VAR_PRE_CROB,
|
||||
@@ -511,6 +525,8 @@ enum class eVariationId : et
|
||||
VAR_PRE_HANDKERCHIEF,
|
||||
VAR_PRE_HEART,
|
||||
VAR_PRE_HEAT,
|
||||
VAR_PRE_HELICOID,
|
||||
VAR_PRE_HELIX,
|
||||
VAR_PRE_HEMISPHERE,
|
||||
VAR_PRE_HEXAPLAY3D,
|
||||
VAR_PRE_HEXCROP,
|
||||
@@ -606,6 +622,7 @@ enum class eVariationId : et
|
||||
VAR_PRE_PSPHERE,
|
||||
VAR_PRE_Q_ODE,
|
||||
VAR_PRE_RADIAL_BLUR,
|
||||
VAR_PRE_RAND_CUBES,
|
||||
VAR_PRE_RATIONAL3,
|
||||
VAR_PRE_RAYS,
|
||||
VAR_PRE_RBLUR,
|
||||
@@ -640,6 +657,7 @@ enum class eVariationId : et
|
||||
VAR_PRE_SINUSOIDAL,
|
||||
VAR_PRE_SINUSOIDAL3D,
|
||||
//VAR_PRE_SMARTCROP,
|
||||
VAR_PRE_SPHEREBLUR,
|
||||
VAR_PRE_SPHERICAL,
|
||||
VAR_PRE_SPHERICAL3D,
|
||||
VAR_PRE_SPHERICALN,
|
||||
@@ -707,6 +725,8 @@ enum class eVariationId : et
|
||||
VAR_PRE_ZTRANSLATE,
|
||||
|
||||
VAR_POST_ARCH,
|
||||
//VAR_POST_ARCSINH,
|
||||
//VAR_POST_ARCTANH,
|
||||
VAR_POST_AUGER,
|
||||
VAR_POST_BARYCENTROID,
|
||||
VAR_POST_BCIRCLE,
|
||||
@@ -752,6 +772,7 @@ enum class eVariationId : et
|
||||
VAR_POST_CIRCLIZE2,
|
||||
VAR_POST_CIRCUS,
|
||||
VAR_POST_COLLIDEOSCOPE,
|
||||
VAR_POST_CONCENTRIC,
|
||||
VAR_POST_CONIC,
|
||||
VAR_POST_COS,
|
||||
VAR_POST_COS_WRAP,
|
||||
@@ -765,6 +786,7 @@ enum class eVariationId : et
|
||||
VAR_POST_COTQ,
|
||||
VAR_POST_CPOW,
|
||||
VAR_POST_CPOW2,
|
||||
VAR_POST_CPOW3,
|
||||
VAR_POST_CRACKLE,
|
||||
VAR_POST_CRESCENTS,
|
||||
VAR_POST_CROB,
|
||||
@@ -842,6 +864,8 @@ enum class eVariationId : et
|
||||
VAR_POST_HANDKERCHIEF,
|
||||
VAR_POST_HEART,
|
||||
VAR_POST_HEAT,
|
||||
VAR_POST_HELICOID,
|
||||
VAR_POST_HELIX,
|
||||
VAR_POST_HEMISPHERE,
|
||||
VAR_POST_HEXAPLAY3D,
|
||||
VAR_POST_HEXCROP,
|
||||
@@ -937,6 +961,7 @@ enum class eVariationId : et
|
||||
VAR_POST_PSPHERE,
|
||||
VAR_POST_Q_ODE,
|
||||
VAR_POST_RADIAL_BLUR,
|
||||
VAR_POST_RAND_CUBES,
|
||||
VAR_POST_RATIONAL3,
|
||||
VAR_POST_RAYS,
|
||||
VAR_POST_RBLUR,
|
||||
@@ -971,6 +996,7 @@ enum class eVariationId : et
|
||||
VAR_POST_SINUSOIDAL,
|
||||
VAR_POST_SINUSOIDAL3D,
|
||||
VAR_POST_SMARTCROP,
|
||||
VAR_POST_SPHEREBLUR,
|
||||
VAR_POST_SPHERICAL,
|
||||
VAR_POST_SPHERICAL3D,
|
||||
VAR_POST_SPHERICALN,
|
||||
@@ -1472,6 +1498,11 @@ protected:
|
||||
return m_VarType == eVariationType::VARTYPE_REG ? "0;\n" : (m_PrePostAssignType == eVariationAssignType::ASSIGNTYPE_SET ? "vIn.z;\n" : "0;\n");
|
||||
}
|
||||
|
||||
string WeightDefineString() const
|
||||
{
|
||||
return WEIGHT_PREFIX + std::to_string(XformIndexInEmber()) + "_" + std::to_string(IndexInXform()) + "]";
|
||||
}
|
||||
|
||||
Xform<T>* m_Xform;//The parent Xform that this variation is a child of.
|
||||
eVariationId m_VariationId;//The unique ID of this variation.
|
||||
string m_Name;//The unique name of this variation.
|
||||
|
||||
@@ -351,6 +351,11 @@ VariationList<T>::VariationList()
|
||||
ADDPREPOSTREGVAR(Waves2Radial)
|
||||
ADDPREPOSTREGVAR(Panorama1)
|
||||
ADDPREPOSTREGVAR(Panorama2)
|
||||
ADDPREPOSTREGVAR(Helicoid)
|
||||
ADDPREPOSTREGVAR(Helix)
|
||||
ADDPREPOSTREGVAR(Sphereblur)
|
||||
ADDPREPOSTREGVAR(Cpow3)
|
||||
ADDPREPOSTREGVAR(Concentric)
|
||||
//ADDPREPOSTREGVAR(LinearXZ)
|
||||
//ADDPREPOSTREGVAR(LinearYZ)
|
||||
//DC are special.
|
||||
@@ -363,6 +368,7 @@ VariationList<T>::VariationList()
|
||||
ADDPREPOSTREGVAR(DCPerlin)
|
||||
ADDPREPOSTREGVAR(DCTriangle)
|
||||
ADDPREPOSTREGVAR(DCZTransl)
|
||||
ADDPREPOSTREGVAR(RandCubes)
|
||||
|
||||
for (auto var : m_Variations) const_cast<Variation<T>*>(var)->Precalc();//Modify once here, then const after this.
|
||||
|
||||
|
||||
+602
-456
File diff suppressed because it is too large
Load Diff
+492
-428
File diff suppressed because it is too large
Load Diff
+399
-346
File diff suppressed because it is too large
Load Diff
+420
-367
File diff suppressed because it is too large
Load Diff
+392
-363
File diff suppressed because it is too large
Load Diff
+514
-500
File diff suppressed because it is too large
Load Diff
+709
-237
File diff suppressed because it is too large
Load Diff
+225
-125
@@ -51,18 +51,19 @@ public:
|
||||
intmax_t i = 0, varIndex = IndexInXform();
|
||||
ss2 << "_" << XformIndexInEmber() << "]";
|
||||
string index = ss2.str();
|
||||
string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params.
|
||||
string weight = WeightDefineString();
|
||||
string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params.
|
||||
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.
|
||||
string bdcs = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc.
|
||||
ss << "\t{\n"
|
||||
<< "\t\treal_t r = precalcSumSquares;\n"
|
||||
<< "\t\treal_t r4_1 = Zeps(r / 4 + 1);\n"
|
||||
<< "\t\tr4_1 = xform->m_VariationWeights[" << varIndex << "] / r4_1;\n"
|
||||
<< "\t\tr4_1 = " << weight << " / r4_1;\n"
|
||||
<< "\n"
|
||||
<< "\t\tvOut.x = r4_1 * vIn.x;\n"
|
||||
<< "\t\tvOut.y = r4_1 * vIn.y;\n"
|
||||
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * (2 / r4_1 - 1);\n"
|
||||
<< "\t\tvOut.z = " << weight << " * (2 / r4_1 - 1);\n"
|
||||
<< "\n"
|
||||
<< "\t\treal_t sumX, sumY;\n\n";
|
||||
|
||||
@@ -105,7 +106,7 @@ protected:
|
||||
m_Params.clear();
|
||||
m_Params.push_back(ParamWithName<T>(&m_CenterX, prefix + "dc_bubble_centerx"));//Params.
|
||||
m_Params.push_back(ParamWithName<T>(&m_CenterY, prefix + "dc_bubble_centery"));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Scale, prefix + "dc_bubble_scale", 1));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Scale, prefix + "dc_bubble_scale", 1));
|
||||
m_Params.push_back(ParamWithName<T>(true, &m_Bdcs, prefix + "dc_bubble_bdcs"));//Precalc.
|
||||
}
|
||||
|
||||
@@ -150,8 +151,9 @@ public:
|
||||
intmax_t i = 0, varIndex = IndexInXform();
|
||||
ss2 << "_" << XformIndexInEmber() << "]";
|
||||
string index = ss2.str();
|
||||
string weight = WeightDefineString();
|
||||
string origin = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params.
|
||||
string h = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc.
|
||||
string h = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc.
|
||||
ss << "\t{\n"
|
||||
<< "\t\tint x0 = (MwcNext(mwc) & 1) ? -1 : 1;\n"
|
||||
<< "\t\tint y0 = (MwcNext(mwc) & 1) ? -1 : 1;\n"
|
||||
@@ -160,8 +162,8 @@ public:
|
||||
<< "\t\treal_t x0_xor_y0 = (real_t)(x0 ^ y0);\n"
|
||||
<< "\t\treal_t h = -" << h << " + (1 - x0_xor_y0) * " << h << ";\n"
|
||||
<< "\n"
|
||||
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (xform->m_A * x + xform->m_B * y + xform->m_E);\n"
|
||||
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * (xform->m_C * x + xform->m_D * y + xform->m_F);\n"
|
||||
<< "\t\tvOut.x = " << weight << " * (xform->m_A * x + xform->m_B * y + xform->m_E);\n"
|
||||
<< "\t\tvOut.y = " << weight << " * (xform->m_C * x + xform->m_D * y + xform->m_F);\n"
|
||||
<< "\t\tvOut.z = " << DefaultZCl()
|
||||
<< "\t\toutPoint->m_ColorX = fmod(fabs(outPoint->m_ColorX * (real_t)(0.5) * (1 + h) + x0_xor_y0 * (1 - h) * (real_t)(0.5)), (real_t)(1.0));\n"
|
||||
<< "\t}\n";
|
||||
@@ -260,15 +262,16 @@ public:
|
||||
intmax_t i = 0, varIndex = IndexInXform();
|
||||
ss2 << "_" << XformIndexInEmber() << "]";
|
||||
string index = ss2.str();
|
||||
string cubeC1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params.
|
||||
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;
|
||||
string cubeC5 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string cubeC6 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string cubeX = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string cubeY = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string cubeZ = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string weight = WeightDefineString();
|
||||
string cubeC1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params.
|
||||
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;
|
||||
string cubeC5 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string cubeC6 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string cubeX = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string cubeY = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string cubeZ = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string clampC1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc.
|
||||
string clampC2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string clampC3 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
@@ -285,9 +288,9 @@ public:
|
||||
<< "\t\tswitch (i)\n"
|
||||
<< "\t\t{\n"
|
||||
<< "\t\t case 0:\n"
|
||||
<< "\t\t x = xform->m_VariationWeights[" << varIndex << "] * (j ? -1 : 1);\n"
|
||||
<< "\t\t y = xform->m_VariationWeights[" << varIndex << "] * p;\n"
|
||||
<< "\t\t z = xform->m_VariationWeights[" << varIndex << "] * q;\n"
|
||||
<< "\t\t x = " << weight << " * (j ? -1 : 1);\n"
|
||||
<< "\t\t y = " << weight << " * p;\n"
|
||||
<< "\t\t z = " << weight << " * q;\n"
|
||||
<< "\n"
|
||||
<< "\t\t if (j)\n"
|
||||
<< "\t\t outPoint->m_ColorX = " << clampC1 << ";\n"
|
||||
@@ -296,9 +299,9 @@ public:
|
||||
<< "\n"
|
||||
<< "\t\t break;\n"
|
||||
<< "\t\t case 1:\n"
|
||||
<< "\t\t x =xform->m_VariationWeights[" << varIndex << "] * p;\n"
|
||||
<< "\t\t y =xform->m_VariationWeights[" << varIndex << "] * (j ? -1 : 1);\n"
|
||||
<< "\t\t z =xform->m_VariationWeights[" << varIndex << "] * q;\n"
|
||||
<< "\t\t x =" << weight << " * p;\n"
|
||||
<< "\t\t y =" << weight << " * (j ? -1 : 1);\n"
|
||||
<< "\t\t z =" << weight << " * q;\n"
|
||||
<< "\n"
|
||||
<< "\t\t if (j)\n"
|
||||
<< "\t\t outPoint->m_ColorX = " << clampC3 << ";\n"
|
||||
@@ -307,9 +310,9 @@ public:
|
||||
<< "\n"
|
||||
<< "\t\t break;\n"
|
||||
<< "\t\t case 2:\n"
|
||||
<< "\t\t x = xform->m_VariationWeights[" << varIndex << "] * p;\n"
|
||||
<< "\t\t y = xform->m_VariationWeights[" << varIndex << "] * q;\n"
|
||||
<< "\t\t z = xform->m_VariationWeights[" << varIndex << "] * (j ? -1 : 1);\n"
|
||||
<< "\t\t x = " << weight << " * p;\n"
|
||||
<< "\t\t y = " << weight << " * q;\n"
|
||||
<< "\t\t z = " << weight << " * (j ? -1 : 1);\n"
|
||||
<< "\n"
|
||||
<< "\t\t if (j)\n"
|
||||
<< "\t\t outPoint->m_ColorX = " << clampC5 << ";\n"
|
||||
@@ -347,9 +350,9 @@ protected:
|
||||
m_Params.push_back(ParamWithName<T>(&m_DcCubeC4, prefix + "dc_cube_c4"));
|
||||
m_Params.push_back(ParamWithName<T>(&m_DcCubeC5, prefix + "dc_cube_c5"));
|
||||
m_Params.push_back(ParamWithName<T>(&m_DcCubeC6, prefix + "dc_cube_c6"));
|
||||
m_Params.push_back(ParamWithName<T>(&m_DcCubeX, prefix + "dc_cube_x", 1));
|
||||
m_Params.push_back(ParamWithName<T>(&m_DcCubeY, prefix + "dc_cube_y", 1));
|
||||
m_Params.push_back(ParamWithName<T>(&m_DcCubeZ, prefix + "dc_cube_z", 1));
|
||||
m_Params.push_back(ParamWithName<T>(&m_DcCubeX, prefix + "dc_cube_x", 1));
|
||||
m_Params.push_back(ParamWithName<T>(&m_DcCubeY, prefix + "dc_cube_y", 1));
|
||||
m_Params.push_back(ParamWithName<T>(&m_DcCubeZ, prefix + "dc_cube_z", 1));
|
||||
m_Params.push_back(ParamWithName<T>(true, &m_ClampC1, prefix + "dc_cube_clamp_c1"));//Precalc.
|
||||
m_Params.push_back(ParamWithName<T>(true, &m_ClampC2, prefix + "dc_cube_clamp_c2"));
|
||||
m_Params.push_back(ParamWithName<T>(true, &m_ClampC3, prefix + "dc_cube_clamp_c3"));
|
||||
@@ -424,24 +427,25 @@ public:
|
||||
intmax_t i = 0, varIndex = IndexInXform();
|
||||
ss2 << "_" << XformIndexInEmber() << "]";
|
||||
string index = ss2.str();
|
||||
string weight = WeightDefineString();
|
||||
string offset = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params.
|
||||
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;
|
||||
string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string blur = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string sina = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc.
|
||||
string cosa = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string ldcs = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string ldca = "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;
|
||||
string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string blur = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string sina = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc.
|
||||
string cosa = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string ldcs = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string ldca = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
ss << "\t{\n"
|
||||
<< "\t\treal_t temp = MwcNext(mwc) * M_2PI;\n"
|
||||
<< "\t\treal_t sr = sin(temp);\n"
|
||||
<< "\t\treal_t cr = cos(temp);\n"
|
||||
<< "\t\treal_t r = " << blur << " * (MwcNext01(mwc) + MwcNext01(mwc) + MwcNext01(mwc) + MwcNext01(mwc) - 2);\n"
|
||||
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * sin(vIn.x + r * sr)* " << x << ";\n"
|
||||
<< "\t\tvOut.x = " << weight << " * sin(vIn.x + r * sr)* " << x << ";\n"
|
||||
<< "\t\tvOut.y = r + vIn.y * " << y << ";\n"
|
||||
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * cos(vIn.x + r * cr);\n"
|
||||
<< "\t\tvOut.z = " << weight << " * cos(vIn.x + r * cr);\n"
|
||||
<< "\n"
|
||||
<< "\t\treal_t sumX, sumY;\n\n";
|
||||
|
||||
@@ -480,11 +484,11 @@ protected:
|
||||
string prefix = Prefix();
|
||||
m_Params.clear();
|
||||
m_Params.push_back(ParamWithName<T>(&m_Offset, prefix + "dc_cylinder_offset"));//Params.
|
||||
m_Params.push_back(ParamWithName<T>(&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<T>(&m_Scale, prefix + "dc_cylinder_scale", T(0.5)));
|
||||
m_Params.push_back(ParamWithName<T>(&m_X, prefix + "dc_cylinder_x", T(0.125)));//Original used a prefix of cyl_, which is incompatible with Ember's design.
|
||||
m_Params.push_back(ParamWithName<T>(&m_Y, prefix + "dc_cylinder_y", T(0.125)));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Blur, prefix + "dc_cylinder_blur", 1));
|
||||
m_Params.push_back(ParamWithName<T>(&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<T>(&m_Scale, prefix + "dc_cylinder_scale", T(0.5)));
|
||||
m_Params.push_back(ParamWithName<T>(&m_X, prefix + "dc_cylinder_x", T(0.125)));//Original used a prefix of cyl_, which is incompatible with Ember's design.
|
||||
m_Params.push_back(ParamWithName<T>(&m_Y, prefix + "dc_cylinder_y", T(0.125)));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Blur, prefix + "dc_cylinder_blur", 1));
|
||||
m_Params.push_back(ParamWithName<T>(true, &m_Sina, prefix + "dc_cylinder_sina"));//Precalc.
|
||||
m_Params.push_back(ParamWithName<T>(true, &m_Cosa, prefix + "dc_cylinder_cosa"));
|
||||
m_Params.push_back(ParamWithName<T>(true, &m_Ldcs, prefix + "dc_cylinder_ldcs"));
|
||||
@@ -596,6 +600,7 @@ public:
|
||||
{
|
||||
ostringstream ss;
|
||||
intmax_t varIndex = IndexInXform();
|
||||
string weight = WeightDefineString();
|
||||
ss << "\t{\n"
|
||||
<< "\t\treal_t x = LRint(vIn.x);\n"
|
||||
<< "\t\treal_t y = LRint(vIn.y);\n"
|
||||
@@ -607,14 +612,14 @@ public:
|
||||
<< "\t\t {\n"
|
||||
<< "\t\t if (-y >= x)\n"
|
||||
<< "\t\t {\n"
|
||||
<< "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * (vIn.x + 1);\n"
|
||||
<< "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * vIn.y;\n"
|
||||
<< "\t\t vOut.x = " << weight << " * (vIn.x + 1);\n"
|
||||
<< "\t\t vOut.y = " << weight << " * vIn.y;\n"
|
||||
<< "\t\t c += (real_t)(0.25);\n"
|
||||
<< "\t\t }\n"
|
||||
<< "\t\t else\n"
|
||||
<< "\t\t {\n"
|
||||
<< "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x;\n"
|
||||
<< "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * (vIn.y + 1);\n"
|
||||
<< "\t\t vOut.x = " << weight << " * vIn.x;\n"
|
||||
<< "\t\t vOut.y = " << weight << " * (vIn.y + 1);\n"
|
||||
<< "\t\t c += (real_t)(0.75);\n"
|
||||
<< "\t\t }\n"
|
||||
<< "\t\t }\n"
|
||||
@@ -622,14 +627,14 @@ public:
|
||||
<< "\t\t {\n"
|
||||
<< "\t\t if (y <= x)\n"
|
||||
<< "\t\t {\n"
|
||||
<< "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * (vIn.x + 1);\n"
|
||||
<< "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * vIn.y;\n"
|
||||
<< "\t\t vOut.x = " << weight << " * (vIn.x + 1);\n"
|
||||
<< "\t\t vOut.y = " << weight << " * vIn.y;\n"
|
||||
<< "\t\t c += (real_t)(0.25);\n"
|
||||
<< "\t\t }\n"
|
||||
<< "\t\t else\n"
|
||||
<< "\t\t {\n"
|
||||
<< "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x;\n"
|
||||
<< "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * (vIn.y - 1);\n"
|
||||
<< "\t\t vOut.x = " << weight << " * vIn.x;\n"
|
||||
<< "\t\t vOut.y = " << weight << " * (vIn.y - 1);\n"
|
||||
<< "\t\t c += (real_t)(0.75);\n"
|
||||
<< "\t\t }\n"
|
||||
<< "\t\t }\n"
|
||||
@@ -640,14 +645,14 @@ public:
|
||||
<< "\t\t {\n"
|
||||
<< "\t\t if (y >= x)\n"
|
||||
<< "\t\t {\n"
|
||||
<< "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * (vIn.x - 1);\n"
|
||||
<< "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * vIn.y;\n"
|
||||
<< "\t\t vOut.x = " << weight << " * (vIn.x - 1);\n"
|
||||
<< "\t\t vOut.y = " << weight << " * vIn.y;\n"
|
||||
<< "\t\t c += (real_t)(0.25);\n"
|
||||
<< "\t\t }\n"
|
||||
<< "\t\t else\n"
|
||||
<< "\t\t {\n"
|
||||
<< "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x;\n"
|
||||
<< "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * (vIn.y + 1);\n"
|
||||
<< "\t\t vOut.x = " << weight << " * vIn.x;\n"
|
||||
<< "\t\t vOut.y = " << weight << " * (vIn.y + 1);\n"
|
||||
<< "\t\t c += (real_t)(0.75);\n"
|
||||
<< "\t\t }\n"
|
||||
<< "\t\t }\n"
|
||||
@@ -655,14 +660,14 @@ public:
|
||||
<< "\t\t {\n"
|
||||
<< "\t\t if (y > -x)\n"
|
||||
<< "\t\t {\n"
|
||||
<< "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * (vIn.x - 1);\n"
|
||||
<< "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * vIn.y;\n"
|
||||
<< "\t\t vOut.x = " << weight << " * (vIn.x - 1);\n"
|
||||
<< "\t\t vOut.y = " << weight << " * vIn.y;\n"
|
||||
<< "\t\t c += (real_t)(0.25);\n"
|
||||
<< "\t\t }\n"
|
||||
<< "\t\t else\n"
|
||||
<< "\t\t {\n"
|
||||
<< "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x;\n"
|
||||
<< "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * (vIn.y - 1);\n"
|
||||
<< "\t\t vOut.x = " << weight << " * vIn.x;\n"
|
||||
<< "\t\t vOut.y = " << weight << " * (vIn.y - 1);\n"
|
||||
<< "\t\t c += (real_t)(0.75);\n"
|
||||
<< "\t\t }\n"
|
||||
<< "\t\t }\n"
|
||||
@@ -724,17 +729,18 @@ public:
|
||||
intmax_t i = 0, varIndex = IndexInXform();
|
||||
ss2 << "_" << XformIndexInEmber() << "]";
|
||||
string index = ss2.str();
|
||||
string weight = WeightDefineString();
|
||||
string offset = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params.
|
||||
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.
|
||||
string ldca = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string sina = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string cosa = "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.
|
||||
string ldca = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string sina = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string cosa = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
ss << "\t{\n"
|
||||
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x;\n"
|
||||
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * vIn.y;\n"
|
||||
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
|
||||
<< "\t\tvOut.x = " << weight << " * vIn.x;\n"
|
||||
<< "\t\tvOut.y = " << weight << " * vIn.y;\n"
|
||||
<< "\t\tvOut.z = " << weight << " * vIn.z;\n"
|
||||
<< "\n"
|
||||
<< "\t\treal_t sumX, sumY;\n\n";
|
||||
|
||||
@@ -773,8 +779,8 @@ protected:
|
||||
string prefix = Prefix();
|
||||
m_Params.clear();
|
||||
m_Params.push_back(ParamWithName<T>(&m_Offset, prefix + "dc_linear_offset"));//Params.
|
||||
m_Params.push_back(ParamWithName<T>(&m_Angle, prefix + "dc_linear_angle"));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Scale, prefix + "dc_linear_scale", 1));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Angle, prefix + "dc_linear_angle"));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Scale, prefix + "dc_linear_scale", 1));
|
||||
m_Params.push_back(ParamWithName<T>(true, &m_Ldcs, prefix + "dc_linear_ldcs"));//Precalc.
|
||||
m_Params.push_back(ParamWithName<T>(true, &m_Ldca, prefix + "dc_linear_ldca"));
|
||||
m_Params.push_back(ParamWithName<T>(true, &m_Sina, prefix + "dc_linear_sina"));
|
||||
@@ -894,9 +900,10 @@ public:
|
||||
intmax_t i = 0, varIndex = IndexInXform();
|
||||
ss2 << "_" << XformIndexInEmber() << "]";
|
||||
string index = ss2.str();
|
||||
string weight = WeightDefineString();
|
||||
string scatterArea = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params.
|
||||
string zeroEdges = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string a = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc.
|
||||
string zeroEdges = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string a = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc.
|
||||
ss << "\t{\n"
|
||||
<< "\t\tconst real_t\n"
|
||||
<< "\t\txx = xform->m_A, xy = xform->m_B,\n"
|
||||
@@ -969,9 +976,9 @@ public:
|
||||
<< "\t\t }\n"
|
||||
<< "\t\t}\n"
|
||||
<< "\n"
|
||||
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (ox + u * xx + v * yx);\n"
|
||||
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * (oy + u * xy + v * yy);\n"
|
||||
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
|
||||
<< "\t\tvOut.x = " << weight << " * (ox + u * xx + v * yx);\n"
|
||||
<< "\t\tvOut.y = " << weight << " * (oy + u * xy + v * yy);\n"
|
||||
<< "\t\tvOut.z = " << weight << " * vIn.z;\n"
|
||||
<< "\t\toutPoint->m_ColorX = fmod(fabs(u + v), (real_t)(1.0));\n"
|
||||
<< "\t}\n";
|
||||
return ss.str();
|
||||
@@ -988,8 +995,8 @@ protected:
|
||||
string prefix = Prefix();
|
||||
m_Params.clear();
|
||||
m_Params.push_back(ParamWithName<T>(&m_ScatterArea, prefix + "dc_triangle_scatter_area", 0, eParamType::REAL, -1, 1));//Params.
|
||||
m_Params.push_back(ParamWithName<T>(&m_ZeroEdges, prefix + "dc_triangle_zero_edges", 0, eParamType::INTEGER, 0, 1));
|
||||
m_Params.push_back(ParamWithName<T>(true, &m_A, prefix + "dc_triangle_a"));//Precalc.
|
||||
m_Params.push_back(ParamWithName<T>(&m_ZeroEdges, prefix + "dc_triangle_zero_edges", 0, eParamType::INTEGER, 0, 1));
|
||||
m_Params.push_back(ParamWithName<T>(true, &m_A, prefix + "dc_triangle_a"));//Precalc.
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -1036,27 +1043,28 @@ public:
|
||||
intmax_t i = 0, varIndex = IndexInXform();
|
||||
ss2 << "_" << XformIndexInEmber() << "]";
|
||||
string index = ss2.str();
|
||||
string x0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params.
|
||||
string x1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string factor = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string weight = WeightDefineString();
|
||||
string x0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params.
|
||||
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.
|
||||
string clamp = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string x0_ = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string x1_ = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string x1_m_x0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string clamp = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string x0_ = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string x1_ = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string x1_m_x0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
ss << "\t{\n"
|
||||
<< "\t\treal_t zf = " << factor << " * (outPoint->m_ColorX - " << x0_ << ") / " << x1_m_x0 << ";\n"
|
||||
<< "\n"
|
||||
<< "\t\tif (" << clamp << " != 0)\n"
|
||||
<< "\t\t zf = zf < 0 ? 0 : zf > 1 ? 1 : zf;\n"
|
||||
<< "\n"
|
||||
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x;\n"
|
||||
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * vIn.y;\n"
|
||||
<< "\t\tvOut.x = " << weight << " * vIn.x;\n"
|
||||
<< "\t\tvOut.y = " << weight << " * vIn.y;\n"
|
||||
<< "\n"
|
||||
<< "\t\tif (" << overwrite << " == 0)\n"
|
||||
<< "\t\t vOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z * zf;\n"
|
||||
<< "\t\t vOut.z = " << weight << " * vIn.z * zf;\n"
|
||||
<< "\t\telse\n"
|
||||
<< "\t\t vOut.z = xform->m_VariationWeights[" << varIndex << "] * zf;\n"
|
||||
<< "\t\t vOut.z = " << weight << " * zf;\n"
|
||||
<< "\t}\n";
|
||||
return ss.str();
|
||||
}
|
||||
@@ -1073,13 +1081,13 @@ protected:
|
||||
{
|
||||
string prefix = Prefix();
|
||||
m_Params.clear();
|
||||
m_Params.push_back(ParamWithName<T>(&m_X0, prefix + "dc_ztransl_x0", 0, eParamType::REAL, 0, 1));//Params.
|
||||
m_Params.push_back(ParamWithName<T>(&m_X1, prefix + "dc_ztransl_x1", 1, eParamType::REAL, 0, 1));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Factor, prefix + "dc_ztransl_factor", 1));
|
||||
m_Params.push_back(ParamWithName<T>(&m_X0, prefix + "dc_ztransl_x0", 0, eParamType::REAL, 0, 1));//Params.
|
||||
m_Params.push_back(ParamWithName<T>(&m_X1, prefix + "dc_ztransl_x1", 1, eParamType::REAL, 0, 1));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Factor, prefix + "dc_ztransl_factor", 1));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Overwrite, prefix + "dc_ztransl_overwrite", 1, eParamType::INTEGER, 0, 1));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Clamp, prefix + "dc_ztransl_clamp", 0, eParamType::INTEGER, 0, 1));
|
||||
m_Params.push_back(ParamWithName<T>(true, &m_X0_, prefix + "dc_ztransl_x0_"));//Precalc.
|
||||
m_Params.push_back(ParamWithName<T>(true, &m_X1_, prefix + "dc_ztransl_x1_"));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Clamp, prefix + "dc_ztransl_clamp", 0, eParamType::INTEGER, 0, 1));
|
||||
m_Params.push_back(ParamWithName<T>(true, &m_X0_, prefix + "dc_ztransl_x0_"));//Precalc.
|
||||
m_Params.push_back(ParamWithName<T>(true, &m_X1_, prefix + "dc_ztransl_x1_"));
|
||||
m_Params.push_back(ParamWithName<T>(true, &m_X1_m_x0, prefix + "dc_ztransl_x1_m_x0"));
|
||||
}
|
||||
|
||||
@@ -1262,22 +1270,23 @@ public:
|
||||
ostringstream ss, ss2;
|
||||
intmax_t i = 0, varIndex = IndexInXform();
|
||||
ss2 << "_" << XformIndexInEmber();
|
||||
string weight = WeightDefineString();
|
||||
string index = ss2.str() + "]";
|
||||
string shape = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string map = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string selectCentre = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string selectRange = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string centre = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string range = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string edge = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string octaves = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string amps = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string freqs = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string z = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string shape = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string map = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string selectCentre = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string selectRange = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string centre = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string range = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string edge = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string octaves = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string amps = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string freqs = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string z = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string selectBailout = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string notchBottom = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string notchTop = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string notchBottom = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string notchTop = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
ss << "\t{\n"
|
||||
<< "\t\treal4 v;\n"
|
||||
<< "\t\treal_t vx, vy, col, r, theta, s, c, p, e;\n"
|
||||
@@ -1393,8 +1402,8 @@ public:
|
||||
<< "\t\t}\n"
|
||||
<< "\t\twhile ((e < " << notchBottom << " || e > " << notchTop << ") && t++ < iBailout); \n"
|
||||
<< "\n"
|
||||
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * vx; \n"
|
||||
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * vy; \n"
|
||||
<< "\t\tvOut.x = " << weight << " * vx; \n"
|
||||
<< "\t\tvOut.y = " << weight << " * vy; \n"
|
||||
<< "\t\tvOut.z = " << DefaultZCl()
|
||||
<< "\t\tcol = " << centre << " + " << range << " * p; \n"
|
||||
<< "\t\toutPoint->m_ColorX = col - floor(col); \n"
|
||||
@@ -1417,21 +1426,21 @@ protected:
|
||||
string prefix = Prefix();
|
||||
m_Params.clear();
|
||||
m_Params.reserve(15);
|
||||
m_Params.push_back(ParamWithName<T>(&m_Shape, prefix + "dc_perlin_shape", 0, eParamType::INTEGER, 0, 2));//Params.
|
||||
m_Params.push_back(ParamWithName<T>(&m_Map, prefix + "dc_perlin_map", 0, eParamType::INTEGER, 0, 5));
|
||||
m_Params.push_back(ParamWithName<T>(&m_SelectCentre, prefix + "dc_perlin_select_centre", 0, eParamType::REAL, -1, 1));
|
||||
m_Params.push_back(ParamWithName<T>(&m_SelectRange, prefix + "dc_perlin_select_range", 1, eParamType::REAL, T(0.1), 2));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Centre, prefix + "dc_perlin_centre", T(0.25)));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Range, prefix + "dc_perlin_range", T(0.25)));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Edge, prefix + "dc_perlin_edge"));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Scale, prefix + "dc_perlin_scale", 1));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Octaves, prefix + "dc_perlin_octaves", 2, eParamType::INTEGER, 1, 5));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Amps, prefix + "dc_perlin_amps", 2));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Freqs, prefix + "dc_perlin_freqs", 2));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Z, prefix + "dc_perlin_z"));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Shape, prefix + "dc_perlin_shape", 0, eParamType::INTEGER, 0, 2));//Params.
|
||||
m_Params.push_back(ParamWithName<T>(&m_Map, prefix + "dc_perlin_map", 0, eParamType::INTEGER, 0, 5));
|
||||
m_Params.push_back(ParamWithName<T>(&m_SelectCentre, prefix + "dc_perlin_select_centre", 0, eParamType::REAL, -1, 1));
|
||||
m_Params.push_back(ParamWithName<T>(&m_SelectRange, prefix + "dc_perlin_select_range", 1, eParamType::REAL, T(0.1), 2));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Centre, prefix + "dc_perlin_centre", T(0.25)));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Range, prefix + "dc_perlin_range", T(0.25)));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Edge, prefix + "dc_perlin_edge"));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Scale, prefix + "dc_perlin_scale", 1));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Octaves, prefix + "dc_perlin_octaves", 2, eParamType::INTEGER, 1, 5));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Amps, prefix + "dc_perlin_amps", 2));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Freqs, prefix + "dc_perlin_freqs", 2));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Z, prefix + "dc_perlin_z"));
|
||||
m_Params.push_back(ParamWithName<T>(&m_SelectBailout, prefix + "dc_perlin_select_bailout", 10, eParamType::INTEGER, 2, 1000));
|
||||
m_Params.push_back(ParamWithName<T>(true, &m_NotchBottom, prefix + "dc_perlin_notch_bottom"));
|
||||
m_Params.push_back(ParamWithName<T>(true, &m_NotchTop, prefix + "dc_perlin_notch_top"));
|
||||
m_Params.push_back(ParamWithName<T>(true, &m_NotchTop, prefix + "dc_perlin_notch_top"));
|
||||
}
|
||||
private:
|
||||
T m_Shape;//Params.
|
||||
@@ -1452,6 +1461,96 @@ private:
|
||||
shared_ptr<VarFuncs<T>> m_VarFuncs = VarFuncs<T>::Instance();
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// randCubes.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
class RandCubesVariation : public ParametricVariation<T>
|
||||
{
|
||||
public:
|
||||
RandCubesVariation(T weight = 1.0) : ParametricVariation<T>("randCubes", eVariationId::VAR_RAND_CUBES, weight)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
PARVARCOPY(RandCubesVariation)
|
||||
|
||||
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
||||
{
|
||||
auto blockx = Floor<T>(std::log(rand.Frand01<T>()) * (rand.RandBit() ? m_Spread : -m_Spread));
|
||||
auto blocky = Floor<T>(std::log(rand.Frand01<T>()) * (rand.RandBit() ? m_Spread : -m_Spread));
|
||||
T z = VarFuncs<T>::Hash(int(blockx * m_Seed)) + VarFuncs<T>::Hash(int(blockx + blocky * m_Seed)); //random height for each block
|
||||
|
||||
if (m_VarType == eVariationType::VARTYPE_REG)
|
||||
{
|
||||
outPoint.m_X = 0;//This variation intentionally assigns instead of summing.
|
||||
outPoint.m_Y = 0;
|
||||
outPoint.m_Z = 0;
|
||||
}
|
||||
|
||||
helper.Out.x = (blockx * m_Density + rand.Frand01<T>()) * m_BlockSize;
|
||||
helper.Out.y = (blocky * m_Density + rand.Frand01<T>()) * m_BlockSize;
|
||||
helper.Out.z = m_BlockHeight * z * std::pow(rand.Frand01<T>(), T(0.125)); //fade out down
|
||||
outPoint.m_ColorX = z / 2;//block height -> palette location
|
||||
}
|
||||
|
||||
virtual string OpenCLString() const override
|
||||
{
|
||||
ostringstream ss, ss2;
|
||||
intmax_t i = 0, varIndex = IndexInXform();
|
||||
ss2 << "_" << XformIndexInEmber() << "]";
|
||||
string index = ss2.str();
|
||||
string weight = WeightDefineString();
|
||||
string blocksize = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string blockheight = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string spread = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string seed = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
string density = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
ss << "\t{\n"
|
||||
<< "\t\treal_t blockx = floor(log(MwcNext01(mwc)) * ((MwcNext(mwc) & 1) ? " << spread << " : -" << spread << "));\n"
|
||||
<< "\t\treal_t blocky = floor(log(MwcNext01(mwc)) * ((MwcNext(mwc) & 1) ? " << spread << " : -" << spread << "));\n"
|
||||
<< "\t\treal_t z = Hash(blockx * " << seed << ") + Hash(blockx + blocky * " << seed << ");\n";
|
||||
|
||||
if (m_VarType == eVariationType::VARTYPE_REG)
|
||||
{
|
||||
ss << "\t\toutPoint->m_X = 0;\n"
|
||||
<< "\t\toutPoint->m_Y = 0;\n"
|
||||
<< "\t\toutPoint->m_Z = 0;\n";
|
||||
}
|
||||
|
||||
ss << "\t\tvOut.x = (blockx * " << density << " + MwcNext01(mwc)) * " << blocksize << ";\n"
|
||||
<< "\t\tvOut.y = (blocky * " << density << " + MwcNext01(mwc)) * " << blocksize << ";\n"
|
||||
<< "\t\tvOut.z = " << blockheight << " * z * pow(MwcNext01(mwc), 0.125);\n"
|
||||
<< "\t\toutPoint->m_ColorX = z / 2;\n"
|
||||
<< "\t}\n";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
virtual vector<string> OpenCLGlobalFuncNames() const override
|
||||
{
|
||||
return vector<string> { "Hash" };
|
||||
}
|
||||
|
||||
protected:
|
||||
void Init()
|
||||
{
|
||||
string prefix = Prefix();
|
||||
m_Params.clear();
|
||||
m_Params.push_back(ParamWithName<T>(&m_BlockSize, prefix + "randCubes_blockSize", 1));
|
||||
m_Params.push_back(ParamWithName<T>(&m_BlockHeight, prefix + "randCubes_blockHeight", 1));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Spread, prefix + "randCubes_spread", 3));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Seed, prefix + "randCubes_seed", 1, eParamType::INTEGER));
|
||||
m_Params.push_back(ParamWithName<T>(&m_Density, prefix + "randCubes_density", 1));
|
||||
}
|
||||
|
||||
private:
|
||||
T m_BlockSize;
|
||||
T m_BlockHeight;
|
||||
T m_Spread;
|
||||
T m_Seed;
|
||||
T m_Density;
|
||||
};
|
||||
|
||||
MAKEPREPOSTPARVAR(DCBubble, dc_bubble, DC_BUBBLE)
|
||||
MAKEPREPOSTPARVAR(DCCarpet, dc_carpet, DC_CARPET)
|
||||
MAKEPREPOSTPARVARASSIGN(DCCube, dc_cube, DC_CUBE, eVariationAssignType::ASSIGNTYPE_SUM)
|
||||
@@ -1461,4 +1560,5 @@ MAKEPREPOSTPARVAR(DCLinear, dc_linear, DC_LINEAR)
|
||||
MAKEPREPOSTPARVAR(DCTriangle, dc_triangle, DC_TRIANGLE)
|
||||
MAKEPREPOSTPARVAR(DCZTransl, dc_ztransl, DC_ZTRANSL)
|
||||
MAKEPREPOSTPARVAR(DCPerlin, dc_perlin, DC_PERLIN)
|
||||
MAKEPREPOSTPARVAR(RandCubes, randCubes, RAND_CUBES)
|
||||
}
|
||||
|
||||
+8
-10
@@ -656,9 +656,9 @@ public:
|
||||
{
|
||||
//There are no variations, so the affine transformed points can be assigned directly to the output points.
|
||||
T inX = inPoint->m_X;
|
||||
outPoint->m_X = (m_Affine.A() * inX) + (m_Affine.B() * inPoint->m_Y) + m_Affine.C();
|
||||
outPoint->m_Y = (m_Affine.D() * inX) + (m_Affine.E() * inPoint->m_Y) + m_Affine.F();
|
||||
outPoint->m_Z = inPoint->m_Z;
|
||||
outPoint->m_X = 0;//(m_Affine.A() * inX) + (m_Affine.B() * inPoint->m_Y) + m_Affine.C();
|
||||
outPoint->m_Y = 0;//(m_Affine.D() * inX) + (m_Affine.E() * inPoint->m_Y) + m_Affine.F();
|
||||
outPoint->m_Z = 0;//inPoint->m_Z;
|
||||
}
|
||||
|
||||
//Apply post variations, these will modify outPoint.
|
||||
@@ -917,17 +917,15 @@ public:
|
||||
|
||||
if (shouldFlatten)//Flatten was not present and neither was any variation name or parameter in the list.
|
||||
{
|
||||
auto var = vl->GetVariationCopy(eVariationId::VAR_FLATTEN);
|
||||
auto varflatten = vl->GetVariationCopy(eVariationId::VAR_FLATTEN);
|
||||
|
||||
if (AddVariation(var))
|
||||
if (!AddVariation(varflatten))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete var;
|
||||
delete varflatten;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+28
-11
@@ -45,7 +45,7 @@ XmlToEmber<T>::XmlToEmber()
|
||||
if (!m_Init)
|
||||
{
|
||||
//This list is for variation params which are incorrect, but their parent variation name may or may not be correct.
|
||||
//This has some overlap with the list below since some of these have parent variation names that are incorrect.
|
||||
//This has some overlap with the list below since some of these have parent variation names that are also incorrect.
|
||||
m_BadParamNames = unordered_map<string, string>
|
||||
{
|
||||
{ "swtin_distort", "stwin_distort" }, //stwin.
|
||||
@@ -163,7 +163,16 @@ XmlToEmber<T>::XmlToEmber()
|
||||
{ "w2r_distance", "waves2_radial_distance" },
|
||||
{ "tf_exponent", "Truchet_fill_exponent" },
|
||||
{ "tf_arc_width", "Truchet_fill_arc_width" },
|
||||
{ "tf_seed", "Truchet_fill_seed" }
|
||||
{ "tf_seed", "Truchet_fill_seed" },
|
||||
{ "blockSize", "randCubes_blockSize" },
|
||||
{ "blockHeight", "randCubes_blockHeight" },
|
||||
{ "spread", "randCubes_spread" },
|
||||
{ "seed", "randCubes_seed" },
|
||||
{ "density", "randCubes_density" },
|
||||
{ "radius", "concentric_radius" },
|
||||
//{ "density", "concentric_density" },//Can't have two, which means you can never properly paste from Apophysis with both of these in one xform.
|
||||
{ "R_blur", "concentric_R_blur" },
|
||||
{ "Z_blur", "concentric_Z_blur" }
|
||||
};
|
||||
m_FlattenNames =
|
||||
{
|
||||
@@ -191,6 +200,7 @@ XmlToEmber<T>::XmlToEmber()
|
||||
"post_rotate_x",
|
||||
"post_rotate_y",
|
||||
"curl3D_cz",
|
||||
"flatten"//Of course don't flatten if it's already present.
|
||||
};
|
||||
//This is a vector of the incorrect variation names and their param names as they are in the legacy, badly named flam3/Apophysis code.
|
||||
vector<string> badParams =
|
||||
@@ -284,7 +294,6 @@ template <typename T>
|
||||
template <typename Alloc, template <typename, typename> class C>
|
||||
bool XmlToEmber<T>::Parse(byte* buf, const char* filename, C<Ember<T>, Alloc>& embers, bool useDefaults)
|
||||
{
|
||||
char* bn;
|
||||
const char* xmlPtr;
|
||||
const char* loc = __FUNCTION__;
|
||||
size_t emberSize;
|
||||
@@ -298,16 +307,17 @@ bool XmlToEmber<T>::Parse(byte* buf, const char* filename, C<Ember<T>, Alloc>& e
|
||||
xmlPtr = CX(&buf[0]);
|
||||
bufSize = strlen(xmlPtr);
|
||||
//embers.reserve(bufSize / 2500);//The Xml text for an ember is around 2500 bytes, but can be much more. Pre-allocate to aovid unnecessary resizing.
|
||||
doc = xmlReadMemory(xmlPtr, int(bufSize), filename, "ISO-8859-1", XML_PARSE_HUGE);
|
||||
int flags = XML_PARSE_HUGE;// | XML_PARSE_RECOVER;
|
||||
doc = xmlReadMemory(xmlPtr, int(bufSize), filename, "ISO-8859-1", flags);
|
||||
//t.Toc("xmlReadMemory");
|
||||
|
||||
if (doc == nullptr)
|
||||
{
|
||||
doc = xmlReadMemory(xmlPtr, int(bufSize), filename, "UTF-8", XML_PARSE_HUGE);
|
||||
doc = xmlReadMemory(xmlPtr, int(bufSize), filename, "UTF-8", flags);
|
||||
|
||||
if (doc == nullptr)
|
||||
{
|
||||
doc = xmlReadMemory(xmlPtr, int(bufSize), filename, "UTF-16", XML_PARSE_HUGE);
|
||||
doc = xmlReadMemory(xmlPtr, int(bufSize), filename, "UTF-16", flags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,8 +331,7 @@ bool XmlToEmber<T>::Parse(byte* buf, const char* filename, C<Ember<T>, Alloc>& e
|
||||
rootnode = xmlDocGetRootElement(doc);
|
||||
//Scan for <flame> nodes, starting with this node.
|
||||
//t.Tic();
|
||||
bn = basename(const_cast<char*>(filename));
|
||||
ScanForEmberNodes(rootnode, bn, embers, useDefaults);
|
||||
ScanForEmberNodes(rootnode, filename, embers, useDefaults);
|
||||
xmlFreeDoc(doc);
|
||||
emberSize = embers.size();
|
||||
auto first = embers.begin();
|
||||
@@ -345,6 +354,11 @@ bool XmlToEmber<T>::Parse(byte* buf, const char* filename, C<Ember<T>, Alloc>& e
|
||||
secondToLast->m_Interp = eInterp::EMBER_INTERP_LINEAR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddToReport(string(loc) + " : Error parsing xml file " + string(filename) + ", no flames present.");
|
||||
return false;
|
||||
}
|
||||
|
||||
//Finally, ensure that consecutive 'rotate' parameters never exceed
|
||||
//a difference of more than 180 degrees (+/-) for interpolation.
|
||||
@@ -438,7 +452,7 @@ bool XmlToEmber<T>::Aton(const char* str, valT& val)
|
||||
/// <param name="useDefaults">True to use defaults if they are not present in the file, else false to use invalid values as placeholders to indicate the values were not present.</param>
|
||||
template <typename T>
|
||||
template <typename Alloc, template <typename, typename> class C>
|
||||
void XmlToEmber<T>::ScanForEmberNodes(xmlNode* curNode, char* parentFile, C<Ember<T>, Alloc>& embers, bool useDefaults)
|
||||
void XmlToEmber<T>::ScanForEmberNodes(xmlNode* curNode, const char* parentFile, C<Ember<T>, Alloc>& embers, bool useDefaults)
|
||||
{
|
||||
bool parseEmberSuccess;
|
||||
xmlNodePtr thisNode = nullptr;
|
||||
@@ -1025,6 +1039,7 @@ bool XmlToEmber<T>::ParseEmberElement(xmlNode* emberNode, Ember<T>& currentEmber
|
||||
}
|
||||
}
|
||||
|
||||
//If new_linear == 0, manually add a linear
|
||||
if (!fromEmber && !newLinear)
|
||||
currentEmber.Flatten(m_FlattenNames);
|
||||
|
||||
@@ -1107,7 +1122,7 @@ bool XmlToEmber<T>::ParseXform(xmlNode* childNode, Xform<T>& xform, bool motion,
|
||||
xform.m_Name = string(attStr);
|
||||
std::replace(xform.m_Name.begin(), xform.m_Name.end(), ' ', '_');
|
||||
}
|
||||
else if (!Compare(curAtt->name, "symmetry"))//Legacy support.
|
||||
else if (!fromEmber && !Compare(curAtt->name, "symmetry"))//Legacy support.
|
||||
{
|
||||
//Deprecated, set both color_speed and animate to this value.
|
||||
//Huh? Either set it or not?
|
||||
@@ -1284,6 +1299,8 @@ bool XmlToEmber<T>::ParseXform(xmlNode* childNode, Xform<T>& xform, bool motion,
|
||||
if (Aton(attStr, val))
|
||||
{
|
||||
parVar->SetParamVal(name, val);
|
||||
//if (!parVar->SetParamVal(name, val))
|
||||
// AddToReport(string(loc) + " : Failed to set parametric variation parameter " + name);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1382,7 +1399,7 @@ bool XmlToEmber<T>::XmlContainsTag(xmlAttrPtr att, const char* name)
|
||||
/// <param name="chan">The number of channels in each color</param>
|
||||
/// <returns>True if there were no errors, else false.</returns>
|
||||
template <typename T>
|
||||
bool XmlToEmber<T>::ParseHexColors(char* colstr, Ember<T>& ember, size_t numColors, intmax_t chan)
|
||||
bool XmlToEmber<T>::ParseHexColors(const char* colstr, Ember<T>& ember, size_t numColors, intmax_t chan)
|
||||
{
|
||||
stringstream ss, temp(colstr); ss >> std::hex;
|
||||
string s1, s;
|
||||
|
||||
@@ -47,23 +47,23 @@ class EMBER_API XmlToEmber : public EmberReport
|
||||
public:
|
||||
XmlToEmber();
|
||||
template <typename Alloc, template <typename, typename> class C>
|
||||
bool Parse(byte* buf, const char* filename, C<Ember<T>, Alloc>& embers, bool useDefaults = true);
|
||||
bool Parse(byte* buf, const char* filename, C<Ember<T>, Alloc>& embers, bool useDefaults);
|
||||
template <typename Alloc, template <typename, typename> class C>
|
||||
bool Parse(const char* filename, C<Ember<T>, Alloc>& embers, bool useDefaults = true);
|
||||
bool Parse(const char* filename, C<Ember<T>, Alloc>& embers, bool useDefaults);
|
||||
template <typename valT>
|
||||
bool Aton(const char* str, valT& val);
|
||||
static vector<string> m_FlattenNames;
|
||||
|
||||
private:
|
||||
template <typename Alloc, template <typename, typename> class C>
|
||||
void ScanForEmberNodes(xmlNode* curNode, char* parentFile, C<Ember<T>, Alloc>& embers, bool useDefaults);
|
||||
void ScanForEmberNodes(xmlNode* curNode, const char* parentFile, C<Ember<T>, Alloc>& embers, bool useDefaults);
|
||||
bool ParseEmberElement(xmlNode* emberNode, Ember<T>& currentEmber);
|
||||
bool AttToEmberMotionFloat(xmlAttrPtr att, const char* attStr, eEmberMotionParam param, EmberMotion<T>& motion);
|
||||
bool ParseXform(xmlNode* childNode, Xform<T>& xform, bool motion, bool fromEmber);
|
||||
static string GetCorrectedParamName(const unordered_map<string, string>& names, const char* name);
|
||||
static string GetCorrectedVariationName(vector<pair<pair<string, string>, vector<string>>>& vec, xmlAttrPtr att);
|
||||
static bool XmlContainsTag(xmlAttrPtr att, const char* name);
|
||||
bool ParseHexColors(char* colstr, Ember<T>& ember, size_t numColors, intmax_t chan);
|
||||
bool ParseHexColors(const char* colstr, Ember<T>& ember, size_t numColors, intmax_t chan);
|
||||
template <typename valT>
|
||||
bool ParseAndAssign(const xmlChar* name, const char* attStr, const char* str, valT& val, bool& b);
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ static string ConstantDefinesString(bool doublePrecision)
|
||||
"#define COLORMAP_LENGTH 256u\n"
|
||||
"#define COLORMAP_LENGTH_MINUS_1 255\n"
|
||||
"#define DE_THRESH 100u\n"
|
||||
"#define BadVal(x) (((x) != (x)) || ((x) > 1e10) || ((x) < -1e10))\n"
|
||||
"#define BadVal(x) (((x) != (x)) || ((x) > 1e20) || ((x) < -1e20))\n"
|
||||
"#define SQR(x) ((x) * (x))\n"
|
||||
"#define CUBE(x) ((x) * (x) * (x))\n"
|
||||
"#define MPI ((real_t)M_PI)\n"
|
||||
@@ -158,9 +158,6 @@ static const char* PointCLStructString =
|
||||
"} Point;\n"
|
||||
"\n";
|
||||
|
||||
#define MAX_CL_VARS 8//These must always match.
|
||||
#define MAX_CL_VARS_STRING "8"
|
||||
|
||||
/// <summary>
|
||||
/// A structure on the host used to hold all of the needed information for an xform used on the device to iterate in OpenCL.
|
||||
/// Template argument expected to be float or double.
|
||||
@@ -169,12 +166,11 @@ template <typename T>
|
||||
struct ALIGN XformCL
|
||||
{
|
||||
T m_A, m_B, m_C, m_D, m_E, m_F;//24 (48)
|
||||
T m_VariationWeights[MAX_CL_VARS];//56 (112)
|
||||
T m_PostA, m_PostB, m_PostC, m_PostD, m_PostE, m_PostF;//80 (160)
|
||||
T m_DirectColor;//84 (168)
|
||||
T m_ColorSpeedCache;//88 (176)
|
||||
T m_OneMinusColorCache;//92 (184)
|
||||
T m_Opacity;//96 (192)
|
||||
T m_PostA, m_PostB, m_PostC, m_PostD, m_PostE, m_PostF;//48 (96)
|
||||
T m_DirectColor;//52 (104)
|
||||
T m_ColorSpeedCache;//56 (112)
|
||||
T m_OneMinusColorCache;//60 (120)
|
||||
T m_Opacity;//64 (128)
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -184,7 +180,6 @@ static const char* XformCLStructString =
|
||||
"typedef struct __attribute__ " ALIGN_CL " _XformCL\n"
|
||||
"{\n"
|
||||
" real_t m_A, m_B, m_C, m_D, m_E, m_F;\n"
|
||||
" real_t m_VariationWeights[" MAX_CL_VARS_STRING "];\n"
|
||||
" real_t m_PostA, m_PostB, m_PostC, m_PostD, m_PostE, m_PostF;\n"
|
||||
" real_t m_DirectColor;\n"
|
||||
" real_t m_ColorSpeedCache;\n"
|
||||
|
||||
@@ -125,6 +125,16 @@ FunctionMapper::FunctionMapper()
|
||||
" *val1 = *val2;\n"
|
||||
" *val2 = tmp;\n"
|
||||
"}\n";
|
||||
s_GlobalMap["Hash"] =
|
||||
"inline real_t Hash(int a)\n"
|
||||
"{\n"
|
||||
" a = (a ^ 61) ^ (a >> 16);\n"
|
||||
" a = a + (a << 3);\n"
|
||||
" a = a ^ (a >> 4);\n"
|
||||
" a = a * 0x27d4eb2d;\n"
|
||||
" a = a ^ (a >> 15);\n"
|
||||
" return (real_t)a / INT_MAX;\n"
|
||||
"}\n";
|
||||
s_GlobalMap["Vratio"] =
|
||||
"inline real_t Vratio(real2* p, real2* q, real2* u)\n"
|
||||
"{\n"
|
||||
|
||||
@@ -96,9 +96,9 @@ string IterOpenCLKernelCreator<T>::CreateIterKernelString(const Ember<T>& ember,
|
||||
if (xform->PreVariationCount() + xform->VariationCount() == 0)
|
||||
{
|
||||
xformFuncs <<
|
||||
" outPoint->m_X = (xform->m_A * inPoint->m_X) + (xform->m_B * inPoint->m_Y) + xform->m_C;\n" <<
|
||||
" outPoint->m_Y = (xform->m_D * inPoint->m_X) + (xform->m_E * inPoint->m_Y) + xform->m_F;\n" <<
|
||||
" outPoint->m_Z = inPoint->m_Z;\n";
|
||||
" outPoint->m_X = 0;\n"
|
||||
" outPoint->m_Y = 0;\n"
|
||||
" outPoint->m_Z = 0;\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -577,7 +577,7 @@ string IterOpenCLKernelCreator<T>::GlobalFunctionsString(const Ember<T>& ember)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an OpenCL string of #defines and a corresponding host side vector for parametric variation values.
|
||||
/// Create an OpenCL string of #defines and a corresponding host side vector for variation weights and parametric variation values.
|
||||
/// Parametric variations present a special problem in the iteration code.
|
||||
/// The values can't be passed in with the array of other xform values because
|
||||
/// the length of the parametric values is unknown.
|
||||
@@ -609,6 +609,7 @@ string IterOpenCLKernelCreator<T>::GlobalFunctionsString(const Ember<T>& ember)
|
||||
/// The variations use these #defines by first looking up the index of the
|
||||
/// xform they belong to in the parent ember and generating the OpenCL string based on that
|
||||
/// in their overridden OpenCLString() functions.
|
||||
/// Note that variation weights are also included in this buffer and are looked up in a similar manner.
|
||||
/// Template argument expected to be float or double.
|
||||
/// </summary>
|
||||
/// <param name="ember">The ember to create the values from</param>
|
||||
@@ -618,7 +619,7 @@ string IterOpenCLKernelCreator<T>::GlobalFunctionsString(const Ember<T>& ember)
|
||||
template <typename T>
|
||||
void IterOpenCLKernelCreator<T>::ParVarIndexDefines(const Ember<T>& ember, pair<string, vector<T>>& params, bool doVals, bool doString)
|
||||
{
|
||||
size_t i = 0, j, k, size = 0;
|
||||
size_t i = 0, size = 0;
|
||||
ostringstream os;
|
||||
|
||||
if (doVals)
|
||||
@@ -626,13 +627,19 @@ void IterOpenCLKernelCreator<T>::ParVarIndexDefines(const Ember<T>& ember, pair<
|
||||
|
||||
while (auto xform = ember.GetTotalXform(i))
|
||||
{
|
||||
size_t varCount = xform->TotalVariationCount();
|
||||
size_t j = 0;
|
||||
|
||||
for (j = 0; j < varCount; j++)
|
||||
while (auto var = xform->GetVariation(j))
|
||||
{
|
||||
if (auto parVar = dynamic_cast<ParametricVariation<T>*>(xform->GetVariation(j)))
|
||||
if (doString)
|
||||
os << "#define WEIGHT_" << i << "_" << j << " " << size++ << "\n";//Uniquely identify the weight of this variation in this xform.
|
||||
|
||||
if (doVals)
|
||||
params.second.push_back(var->m_Weight);
|
||||
|
||||
if (auto parVar = dynamic_cast<ParametricVariation<T>*>(var))
|
||||
{
|
||||
for (k = 0; k < parVar->ParamCount(); k++)
|
||||
for (size_t k = 0; k < parVar->ParamCount(); k++)
|
||||
{
|
||||
if (!parVar->Params()[k].IsState())
|
||||
{
|
||||
@@ -651,6 +658,8 @@ void IterOpenCLKernelCreator<T>::ParVarIndexDefines(const Ember<T>& ember, pair<
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
@@ -1772,9 +1772,6 @@ void RendererCL<T, bucketT>::ConvertEmber(Ember<T>& ember, EmberCL<T>& emberCL,
|
||||
xformsCL[i].m_ColorSpeedCache = xform->ColorSpeedCache();
|
||||
xformsCL[i].m_OneMinusColorCache = xform->OneMinusColorCache();
|
||||
xformsCL[i].m_Opacity = xform->m_Opacity;
|
||||
|
||||
for (size_t varIndex = 0; varIndex < xform->TotalVariationCount() && varIndex < MAX_CL_VARS; varIndex++)//Assign all variation weights for this xform, with a max of MAX_CL_VARS.
|
||||
xformsCL[i].m_VariationWeights[varIndex] = xform->GetVariation(varIndex)->m_Weight;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -669,7 +669,7 @@ bool EmberGenome(EmberOptions& opt)
|
||||
mutMeth = eMutateMode::MUTATE_NOT_SPECIFIED;
|
||||
}
|
||||
|
||||
os << tools.Mutate(orig, mutMeth, vars, opt.Symmetry(), T(opt.Speed()), MAX_CL_VARS);
|
||||
os << tools.Mutate(orig, mutMeth, vars, opt.Symmetry(), T(opt.Speed()), 8);
|
||||
|
||||
//Scan string returned for 'mutate color'.
|
||||
if (strstr(os.str().c_str(), "mutate color"))
|
||||
@@ -718,7 +718,7 @@ bool EmberGenome(EmberOptions& opt)
|
||||
{
|
||||
os << "random";
|
||||
randomMode = true;
|
||||
tools.Random(orig, vars, opt.Symmetry(), 0, MAX_CL_VARS);
|
||||
tools.Random(orig, vars, opt.Symmetry(), 0, 8);
|
||||
orig.m_FinalRasW = 1920;
|
||||
orig.m_FinalRasH = 1080;
|
||||
aselp0 = nullptr;
|
||||
|
||||
@@ -255,7 +255,7 @@ void MakeTestAllVarsRegPrePostComboFile(const string& filename)
|
||||
EmberToXml<float> writer;
|
||||
vector<Ember<float>> embers;
|
||||
MakeTestAllVarsRegPrePost(embers);
|
||||
writer.Save(filename, embers, 0, true, true, false);
|
||||
writer.Save(filename, embers, 0, true, true, false, false, false);
|
||||
}
|
||||
|
||||
void TestAtomicAdd()
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p align="center">Fractorium 1.0.0.6</p><p align="center"><span style=" font-size:10pt;">A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.</span></p><p align="center"><a href="http://fractorium.com"><span style=" text-decoration: underline; color:#0000ff;">fractorium.com</span></a><span style=" font-size:10pt;"><br/>Lead: Matt Feemster<br/>Contributors: Simon Detheridge, Michel Mastriani</span></p></body></html></string>
|
||||
<string><html><head/><body><p align="center">Fractorium 1.0.0.7</p><p align="center"><span style=" font-size:10pt;">A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.</span></p><p align="center"><a href="http://fractorium.com"><span style=" text-decoration: underline; color:#0000ff;">fractorium.com</span></a><span style=" font-size:10pt;"><br/>Lead: Matt Feemster<br/>Contributors: Simon Detheridge, Michel Mastriani</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
|
||||
@@ -118,9 +118,9 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
|
||||
//Save backup Xml.
|
||||
if (doAll)
|
||||
m_XmlWriter.Save(backup.toStdString().c_str(), m_EmberFile.m_Embers, 0, true, false, true);
|
||||
m_XmlWriter.Save(backup.toStdString().c_str(), m_EmberFile.m_Embers, 0, true, false, true, false, false);
|
||||
else
|
||||
m_XmlWriter.Save(backup.toStdString().c_str(), *m_Ember, 0, true, false, true);
|
||||
m_XmlWriter.Save(backup.toStdString().c_str(), *m_Ember, 0, true, false, true, false, false);
|
||||
|
||||
m_FinishedImageCount.store(0);
|
||||
SyncGuiToRenderer();
|
||||
|
||||
@@ -112,10 +112,10 @@ Fractorium::Fractorium(QWidget* p)
|
||||
m_Controller->SetupVariationsTree();
|
||||
m_Controller->FilteredVariations();
|
||||
|
||||
if (m_Info->Ok() && m_Settings->OpenCL() && m_QualitySpin->value() < (30 * m_Settings->Devices().size()))
|
||||
m_QualitySpin->setValue(30 * m_Settings->Devices().size());
|
||||
if (m_Info->Ok() && m_Settings->OpenCL() && m_QualitySpin->value() < (m_Settings->OpenClQuality() * m_Settings->Devices().size()))
|
||||
m_QualitySpin->setValue(m_Settings->OpenClQuality() * m_Settings->Devices().size());
|
||||
|
||||
int statusBarHeight = 20 * devicePixelRatio();
|
||||
int statusBarHeight = 20;// *devicePixelRatio();
|
||||
ui.StatusBar->setMinimumHeight(statusBarHeight);
|
||||
ui.StatusBar->setMaximumHeight(statusBarHeight);
|
||||
m_RenderStatusLabel = new QLabel(this);
|
||||
@@ -222,6 +222,9 @@ Fractorium::~Fractorium()
|
||||
m_Settings->ShowGrid(ui.ActionDrawGrid->isChecked());
|
||||
m_Settings->setValue("windowState", saveState());
|
||||
m_Settings->sync();
|
||||
|
||||
if (m_Settings->LoadLast())
|
||||
m_Controller->SaveCurrentFileOnShutdown();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -330,8 +333,8 @@ bool Fractorium::eventFilter(QObject* o, QEvent* e)
|
||||
{
|
||||
if (o == ui.GLParentScrollArea && e->type() == QEvent::Resize)
|
||||
{
|
||||
m_WidthSpin->DoubleClickNonZero(ui.GLParentScrollArea->width());
|
||||
m_HeightSpin->DoubleClickNonZero(ui.GLParentScrollArea->height());
|
||||
m_WidthSpin->DoubleClickNonZero(ui.GLParentScrollArea->width() * ui.GLDisplay->devicePixelRatioF());
|
||||
m_HeightSpin->DoubleClickNonZero(ui.GLParentScrollArea->height() * ui.GLDisplay->devicePixelRatioF());
|
||||
}
|
||||
else if (auto ke = dynamic_cast<QKeyEvent*>(e))
|
||||
{
|
||||
@@ -368,8 +371,8 @@ bool Fractorium::eventFilter(QObject* o, QEvent* e)
|
||||
/// <param name="e">The event</param>
|
||||
void Fractorium::resizeEvent(QResizeEvent* e)
|
||||
{
|
||||
m_WidthSpin->DoubleClickNonZero(ui.GLParentScrollArea->width());
|
||||
m_HeightSpin->DoubleClickNonZero(ui.GLParentScrollArea->height());
|
||||
m_WidthSpin->DoubleClickNonZero(ui.GLParentScrollArea->width() * ui.GLDisplay->devicePixelRatioF());
|
||||
m_HeightSpin->DoubleClickNonZero(ui.GLParentScrollArea->height() * ui.GLDisplay->devicePixelRatioF());
|
||||
QMainWindow::resizeEvent(e);
|
||||
}
|
||||
|
||||
|
||||
@@ -310,6 +310,7 @@ public slots:
|
||||
void OnXformsSelectAllButtonClicked(bool checked);
|
||||
void OnXformsSelectNoneButtonClicked(bool checked);
|
||||
bool IsXformSelected(size_t i);
|
||||
int SelectedXformCount(bool includeFinal);
|
||||
|
||||
//Xaos.
|
||||
void OnXaosChanged(double d);
|
||||
|
||||
@@ -74,8 +74,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1269</width>
|
||||
<height>987</height>
|
||||
<width>1259</width>
|
||||
<height>980</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@@ -2007,14 +2007,14 @@
|
||||
<rect>
|
||||
<x>770</x>
|
||||
<y>0</y>
|
||||
<width>294</width>
|
||||
<width>295</width>
|
||||
<height>881</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>294</width>
|
||||
<height>617</height>
|
||||
<width>295</width>
|
||||
<height>624</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="features">
|
||||
@@ -2689,13 +2689,13 @@
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>60</width>
|
||||
<width>65</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>60</width>
|
||||
<width>65</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
@@ -3700,8 +3700,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>263</width>
|
||||
<height>722</height>
|
||||
<width>128</width>
|
||||
<height>686</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
@@ -5786,8 +5786,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>259</width>
|
||||
<height>652</height>
|
||||
<width>136</width>
|
||||
<height>58</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@@ -5920,7 +5920,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>291</width>
|
||||
<height>851</height>
|
||||
<height>854</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@@ -7027,8 +7027,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>432</width>
|
||||
<height>589</height>
|
||||
<width>442</width>
|
||||
<height>587</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
||||
@@ -344,7 +344,7 @@ void FractoriumEmberController<T>::SetEmberPrivate(const Ember<U>& ember, bool v
|
||||
dir.mkpath(".");
|
||||
|
||||
string filename = path.toStdString() + "/last.flame";
|
||||
writer.Save(filename.c_str(), m_Ember, 0, true, true, false, true, true);
|
||||
writer.Save(filename, m_Ember, 0, true, true, false, true, true);
|
||||
m_GLController->ResetMouseState();
|
||||
FillXforms();//Must do this first because the palette setup in FillParamTablesAndPalette() uses the xforms combo.
|
||||
FillParamTablesAndPalette();
|
||||
|
||||
@@ -100,6 +100,7 @@ public:
|
||||
virtual void SaveCurrentAsXml() { }
|
||||
virtual void SaveEntireFileAsXml() { }
|
||||
virtual uint SaveCurrentToOpenedFile(bool render = true) { return 0; }
|
||||
virtual void SaveCurrentFileOnShutdown() { }
|
||||
virtual void Undo() { }//Edit.
|
||||
virtual void Redo() { }
|
||||
virtual void CopyXml() { }
|
||||
@@ -362,6 +363,7 @@ public:
|
||||
virtual void SaveCurrentAsXml() override;
|
||||
virtual void SaveEntireFileAsXml() override;
|
||||
virtual uint SaveCurrentToOpenedFile(bool render = true) override;
|
||||
virtual void SaveCurrentFileOnShutdown() override;
|
||||
virtual void Undo() override;
|
||||
virtual void Redo() override;
|
||||
virtual void CopyXml() override;
|
||||
|
||||
@@ -768,7 +768,7 @@ void FractoriumEmberController<T>::SequenceSaveButtonClicked()
|
||||
for (auto& ember : m_SequenceFile.m_Embers)
|
||||
ApplyXmlSavingTemplate(ember);
|
||||
|
||||
if (writer.Save(filename.toStdString().c_str(), m_SequenceFile.m_Embers, 0, true, true))
|
||||
if (writer.Save(filename.toStdString().c_str(), m_SequenceFile.m_Embers, 0, true, true, false, false, false))
|
||||
s->SaveFolder(fileInfo.canonicalPath());
|
||||
else
|
||||
m_Fractorium->ShowCritical("Save Failed", "Could not save sequence file, try saving to a different folder.");
|
||||
@@ -800,7 +800,7 @@ void FractoriumEmberController<T>::SequenceOpenButtonClicked()
|
||||
{
|
||||
embers.clear();
|
||||
|
||||
if (parser.Parse(filename.toStdString().c_str(), embers) && !embers.empty())
|
||||
if (parser.Parse(filename.toStdString().c_str(), embers, true) && !embers.empty())
|
||||
{
|
||||
for (i = 0; i < embers.size(); i++)
|
||||
if (embers[i].m_Name == "" || embers[i].m_Name == "No name")//Ensure it has a name.
|
||||
|
||||
@@ -77,7 +77,7 @@ void FractoriumEmberController<T>::NewFlock(size_t count)
|
||||
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
m_SheepTools->Random(ember, filteredVariationsRef, static_cast<intmax_t>(QTIsaac<ISAAC_SIZE, ISAAC_INT>::LockedFrand<T>(-2, 2)), 0, MAX_CL_VARS);
|
||||
m_SheepTools->Random(ember, filteredVariationsRef, static_cast<intmax_t>(QTIsaac<ISAAC_SIZE, ISAAC_INT>::LockedFrand<T>(-2, 2)), 0, 8);
|
||||
ParamsToEmber(ember);
|
||||
ember.m_Index = i;
|
||||
ember.m_Name = m_EmberFile.m_Filename.toStdString() + "_" + ToString(i + 1ULL).toStdString();
|
||||
@@ -114,6 +114,7 @@ void FractoriumEmberController<T>::NewEmptyFlameInCurrentFile()
|
||||
ParamsToEmber(ember);
|
||||
xform.m_Weight = T(0.25);
|
||||
xform.m_ColorX = m_Rand.Frand01<T>();
|
||||
xform.AddVariation(m_VariationList->GetVariationCopy(eVariationId::VAR_LINEAR));
|
||||
ember.AddXform(xform);
|
||||
ember.m_Palette = *m_PaletteList->GetRandomPalette();
|
||||
ember.m_Name = EmberFile<T>::DefaultEmberName(m_EmberFile.Size() + 1).toStdString();
|
||||
@@ -136,7 +137,7 @@ void FractoriumEmberController<T>::NewRandomFlameInCurrentFile()
|
||||
{
|
||||
Ember<T> ember;
|
||||
StopAllPreviewRenderers();
|
||||
m_SheepTools->Random(ember, m_FilteredVariations, static_cast<int>(QTIsaac<ISAAC_SIZE, ISAAC_INT>::LockedFrand<T>(-2, 2)), 0, MAX_CL_VARS);
|
||||
m_SheepTools->Random(ember, m_FilteredVariations, static_cast<int>(QTIsaac<ISAAC_SIZE, ISAAC_INT>::LockedFrand<T>(-2, 2)), 0, 8);
|
||||
ParamsToEmber(ember);
|
||||
ember.m_Name = EmberFile<T>::DefaultEmberName(m_EmberFile.Size() + 1).toStdString();
|
||||
ember.m_Index = m_EmberFile.Size();
|
||||
@@ -198,7 +199,7 @@ void FractoriumEmberController<T>::OpenAndPrepFiles(const QStringList& filenames
|
||||
{
|
||||
embers.clear();
|
||||
|
||||
if (parser.Parse(filename.toStdString().c_str(), embers) && !embers.empty())
|
||||
if (parser.Parse(filename.toStdString().c_str(), embers, true) && !embers.empty())
|
||||
{
|
||||
for (i = 0; i < embers.size(); i++)
|
||||
{
|
||||
@@ -235,6 +236,12 @@ void FractoriumEmberController<T>::OpenAndPrepFiles(const QStringList& filenames
|
||||
}
|
||||
else if (emberFile.Size() > 0)//Ensure at least something was read.
|
||||
m_EmberFile = std::move(emberFile);//Move the temp to avoid creating dupes because we no longer need it.
|
||||
else if (!m_EmberFile.Size())
|
||||
{
|
||||
//Loading failed, so fill it with a dummy.
|
||||
Ember<T> ember;
|
||||
m_EmberFile.m_Embers.push_back(ember);
|
||||
}
|
||||
|
||||
//Resync indices and names.
|
||||
i = 0;
|
||||
@@ -343,7 +350,7 @@ void FractoriumEmberController<T>::SaveEntireFileAsXml()
|
||||
for (auto& ember : emberFile.m_Embers)
|
||||
ApplyXmlSavingTemplate(ember);
|
||||
|
||||
if (writer.Save(filename.toStdString().c_str(), emberFile.m_Embers, 0, true, true))
|
||||
if (writer.Save(filename.toStdString().c_str(), emberFile.m_Embers, 0, true, true, false, false, false))
|
||||
{
|
||||
if (!s->SaveAutoUnique() || m_LastSaveAll == "")//Only save filename on first time through when doing auto unique names.
|
||||
m_LastSaveAll = filename;
|
||||
@@ -357,6 +364,20 @@ void FractoriumEmberController<T>::SaveEntireFileAsXml()
|
||||
|
||||
void Fractorium::OnActionSaveEntireFileAsXml(bool checked) { m_Controller->SaveEntireFileAsXml(); }
|
||||
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::SaveCurrentFileOnShutdown()
|
||||
{
|
||||
EmberToXml<T> writer;
|
||||
auto path = GetDefaultUserPath();
|
||||
QDir dir(path);
|
||||
|
||||
if (!dir.exists())
|
||||
dir.mkpath(".");
|
||||
|
||||
string filename = path.toStdString() + "/lastonshutdown.flame";
|
||||
writer.Save(filename, m_EmberFile.m_Embers, 0, true, true, false, false, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show a file save dialog and save what is currently shown in the render window to disk as an image.
|
||||
/// </summary>
|
||||
@@ -557,7 +578,7 @@ void FractoriumEmberController<T>::PasteXmlAppend()
|
||||
|
||||
b.clear();
|
||||
StopAllPreviewRenderers();
|
||||
parser.Parse(reinterpret_cast<byte*>(const_cast<char*>(s.c_str())), "", embers);
|
||||
parser.Parse(reinterpret_cast<byte*>(const_cast<char*>(s.c_str())), "", embers, true);
|
||||
errors = parser.ErrorReportString();
|
||||
|
||||
if (errors != "")
|
||||
@@ -598,7 +619,8 @@ void FractoriumEmberController<T>::PasteXmlOver()
|
||||
size_t i = 0;
|
||||
string s, errors;
|
||||
XmlToEmber<T> parser;
|
||||
auto backupEmber = m_EmberFile.m_Embers.begin();
|
||||
list<Ember<T>> embers;
|
||||
auto backupEmber = *m_EmberFile.m_Embers.begin();
|
||||
auto codec = QTextCodec::codecForName("UTF-8");
|
||||
auto b = codec->fromUnicode(QApplication::clipboard()->text());
|
||||
s.reserve(b.size());
|
||||
@@ -611,8 +633,7 @@ void FractoriumEmberController<T>::PasteXmlOver()
|
||||
|
||||
b.clear();
|
||||
StopAllPreviewRenderers();
|
||||
m_EmberFile.m_Embers.clear();//Will invalidate the pointers contained in the EmberTreeWidgetItems, UpdateLibraryTree() will resync.
|
||||
parser.Parse(reinterpret_cast<byte*>(const_cast<char*>(s.c_str())), "", m_EmberFile.m_Embers);
|
||||
parser.Parse(reinterpret_cast<byte*>(const_cast<char*>(s.c_str())), "", embers, true);
|
||||
errors = parser.ErrorReportString();
|
||||
|
||||
if (errors != "")
|
||||
@@ -620,8 +641,10 @@ void FractoriumEmberController<T>::PasteXmlOver()
|
||||
m_Fractorium->ShowCritical("Paste Error", QString::fromStdString(errors));
|
||||
}
|
||||
|
||||
if (m_EmberFile.Size())
|
||||
if (embers.size())
|
||||
{
|
||||
m_EmberFile.m_Embers = std::move(embers);//Will invalidate the pointers contained in the EmberTreeWidgetItems, UpdateLibraryTree() will resync.
|
||||
|
||||
for (auto it : m_EmberFile.m_Embers)
|
||||
{
|
||||
it.m_Index = i++;
|
||||
@@ -631,16 +654,11 @@ void FractoriumEmberController<T>::PasteXmlOver()
|
||||
if (it.m_Name == "" || it.m_Name == "No name")
|
||||
it.m_Name = ToString<qulonglong>(it.m_Index).toStdString();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
backupEmber->m_Index = 0;
|
||||
m_EmberFile.m_Embers.push_back(*backupEmber);
|
||||
}
|
||||
|
||||
m_EmberFile.MakeNamesUnique();
|
||||
FillLibraryTree();
|
||||
SetEmber(0, false);
|
||||
m_EmberFile.MakeNamesUnique();
|
||||
FillLibraryTree();
|
||||
SetEmber(0, false);
|
||||
}
|
||||
}
|
||||
|
||||
void Fractorium::OnActionPasteXmlOver(bool checked) { m_Controller->PasteXmlOver(); }
|
||||
@@ -856,6 +874,7 @@ void FractoriumEmberController<T>::ClearFlame()
|
||||
if (auto xform = m_Ember.GetXform(0))
|
||||
{
|
||||
xform->Clear();
|
||||
xform->AddVariation(m_VariationList->GetVariationCopy(eVariationId::VAR_LINEAR));
|
||||
xform->ParentEmber(&m_Ember);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ void Fractorium::InitParamsUI()
|
||||
//Filter.
|
||||
row = 0;
|
||||
table = ui.FilterTable;
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_SpatialFilterWidthSpin, spinHeight, 0.1, 2, 0.1, SIGNAL(valueChanged(double)), SLOT(OnSpatialFilterWidthChanged(double)), true, 1.0, 1.0, 0.1);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_SpatialFilterWidthSpin, spinHeight, 0, 2, 0.1, SIGNAL(valueChanged(double)), SLOT(OnSpatialFilterWidthChanged(double)), true, 1.0, 1.0, 0);
|
||||
m_SpatialFilterWidthSpin->DoubleClickLowVal(0.1);
|
||||
comboVals = SpatialFilterCreator<float>::FilterTypes();
|
||||
SetupCombo(table, this, row, 1, m_SpatialFilterTypeCombo, comboVals, SIGNAL(currentIndexChanged(const QString&)), SLOT(OnSpatialFilterTypeComboCurrentIndexChanged(const QString&)));
|
||||
@@ -74,10 +74,11 @@ void Fractorium::InitParamsUI()
|
||||
//Iteration.
|
||||
row = 0;
|
||||
table = ui.IterationTable;
|
||||
auto quality = m_Settings->OpenCL() ? m_Settings->OpenClQuality() : m_Settings->CpuQuality();
|
||||
SetupSpinner<SpinBox, int>( table, this, row, 1, m_SbsSpin, spinHeight, 1000, 100000, 100, SIGNAL(valueChanged(int)), SLOT(OnSbsChanged(int)), true, DEFAULT_SBS, DEFAULT_SBS, DEFAULT_SBS);
|
||||
SetupSpinner<SpinBox, int>( table, this, row, 1, m_FuseSpin, spinHeight, 1, 1000, 5, SIGNAL(valueChanged(int)), SLOT(OnFuseChanged(int)), true, 15, 15, 15);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_QualitySpin, spinHeight, 1, dmax, 50, SIGNAL(valueChanged(double)), SLOT(OnQualityChanged(double)), true, 10, 10, 10);
|
||||
SetupSpinner<SpinBox, int>( table, this, row, 1, m_SupersampleSpin, spinHeight, 1, 4, 1, SIGNAL(valueChanged(int)), SLOT(OnSupersampleChanged(int)), true, 1, 1, 1);
|
||||
SetupSpinner<SpinBox, int>( table, this, row, 1, m_FuseSpin, spinHeight, 1, 1000, 5, SIGNAL(valueChanged(int)), SLOT(OnFuseChanged(int)), true, 15, 15, 15);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_QualitySpin, spinHeight, 1, dmax, 50, SIGNAL(valueChanged(double)), SLOT(OnQualityChanged(double)), true, quality, 10, 10);
|
||||
SetupSpinner<SpinBox, int>( table, this, row, 1, m_SupersampleSpin, spinHeight, 1, 4, 1, SIGNAL(valueChanged(int)), SLOT(OnSupersampleChanged(int)), true, 1, 1, 1);
|
||||
//Animation.
|
||||
row = 0;
|
||||
table = ui.AnimationTable;
|
||||
|
||||
@@ -97,7 +97,7 @@ void FractoriumEmberControllerBase::UpdateRender(eProcessAction action)
|
||||
void FractoriumEmberControllerBase::DeleteRenderer()
|
||||
{
|
||||
Shutdown();
|
||||
m_Renderer.reset();
|
||||
m_Renderer = make_unique<EmberNs::Renderer<float, float>>();
|
||||
|
||||
if (GLController())
|
||||
GLController()->ClearWindow();
|
||||
@@ -299,6 +299,9 @@ bool FractoriumEmberController<T>::SyncSizes()
|
||||
template <typename T>
|
||||
bool FractoriumEmberController<T>::Render()
|
||||
{
|
||||
if (!m_Renderer.get())
|
||||
return false;
|
||||
|
||||
m_Rendering = true;
|
||||
bool success = true;
|
||||
auto gl = m_Fractorium->ui.GLDisplay;
|
||||
@@ -567,7 +570,7 @@ bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, cons
|
||||
|
||||
if (m_RenderType == eRendererType::OPENCL_RENDERER)
|
||||
{
|
||||
auto val = 30 * m_Fractorium->m_Settings->Devices().size();
|
||||
auto val = m_Fractorium->m_Settings->OpenClQuality() * m_Fractorium->m_Settings->Devices().size();
|
||||
m_Fractorium->m_QualitySpin->DoubleClickZero(val);
|
||||
m_Fractorium->m_QualitySpin->DoubleClickNonZero(val);
|
||||
|
||||
@@ -576,11 +579,12 @@ bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, cons
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Fractorium->m_QualitySpin->DoubleClickZero(10);
|
||||
m_Fractorium->m_QualitySpin->DoubleClickNonZero(10);
|
||||
auto quality = m_Fractorium->m_Settings->CpuQuality();
|
||||
m_Fractorium->m_QualitySpin->DoubleClickZero(quality);
|
||||
m_Fractorium->m_QualitySpin->DoubleClickNonZero(quality);
|
||||
|
||||
if (m_Fractorium->m_QualitySpin->value() > 10)
|
||||
m_Fractorium->m_QualitySpin->setValue(10);
|
||||
if (m_Fractorium->m_QualitySpin->value() > quality)
|
||||
m_Fractorium->m_QualitySpin->setValue(quality);
|
||||
}
|
||||
|
||||
m_Renderer->Callback(this);
|
||||
|
||||
@@ -57,6 +57,12 @@ void FractoriumSettings::EnsureDefaults()
|
||||
OpenCLSubBatch(std::max(1u, OpenCLSubBatch()));
|
||||
RandomCount(std::max(1u, RandomCount()));
|
||||
|
||||
if (CpuQuality() == 0)
|
||||
CpuQuality(10);
|
||||
|
||||
if (OpenClQuality() == 0)
|
||||
OpenClQuality(30);
|
||||
|
||||
if (FinalScale() > int(eScaleType::SCALE_HEIGHT))
|
||||
FinalScale(0);
|
||||
|
||||
@@ -72,7 +78,11 @@ void FractoriumSettings::EnsureDefaults()
|
||||
if (SaveImageExt() == "")
|
||||
SaveImageExt(".png");
|
||||
|
||||
if (FinalExt() != "jpg" && FinalExt() != "png")
|
||||
if (FinalExt() != "jpg" && FinalExt() != "png" && FinalExt() != "exr"
|
||||
#ifdef _WIN32
|
||||
&& FinalExt() != "bmp"
|
||||
#endif
|
||||
)
|
||||
FinalExt("png");
|
||||
|
||||
auto s = SaveFolder();
|
||||
@@ -148,6 +158,15 @@ void FractoriumSettings::OpenCLSubBatch(uint i) { setValue(OPENCLSUBBATCH,
|
||||
uint FractoriumSettings::RandomCount() { return value(RANDOMCOUNT).toUInt(); }
|
||||
void FractoriumSettings::RandomCount(uint i) { setValue(RANDOMCOUNT, i); }
|
||||
|
||||
uint FractoriumSettings::CpuQuality() { return value(CPU_QUALITY).toUInt(); }
|
||||
void FractoriumSettings::CpuQuality(uint i) { setValue(CPU_QUALITY, i); }
|
||||
|
||||
uint FractoriumSettings::OpenClQuality() { return value(OPENCL_QUALITY).toUInt(); }
|
||||
void FractoriumSettings::OpenClQuality(uint i) { setValue(OPENCL_QUALITY, i); }
|
||||
|
||||
bool FractoriumSettings::LoadLast() { return value(LOAD_LAST).toBool(); }
|
||||
void FractoriumSettings::LoadLast(bool b) { setValue(LOAD_LAST, b); }
|
||||
|
||||
/// <summary>
|
||||
/// Sequence generation settings.
|
||||
/// </summary>
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
#define CPUSUBBATCH "render/cpusubbatch"
|
||||
#define OPENCLSUBBATCH "render/openclsubbatch"
|
||||
#define RANDOMCOUNT "render/randomcount"
|
||||
#define CPU_QUALITY "render/cpuquality"
|
||||
#define OPENCL_QUALITY "render/openclquality"
|
||||
#define LOAD_LAST "render/loadlastonstart"
|
||||
|
||||
#define STAGGER "sequence/stagger"
|
||||
#define STAGGERMAX "sequence/staggermax"
|
||||
@@ -153,6 +156,15 @@ public:
|
||||
uint RandomCount();
|
||||
void RandomCount(uint i);
|
||||
|
||||
uint CpuQuality();
|
||||
void CpuQuality(uint i);
|
||||
|
||||
uint OpenClQuality();
|
||||
void OpenClQuality(uint i);
|
||||
|
||||
bool LoadLast();
|
||||
void LoadLast(bool b);
|
||||
|
||||
double Stagger();
|
||||
void Stagger(double i);
|
||||
|
||||
|
||||
@@ -32,13 +32,13 @@ void Fractorium::InitXaosUI()
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::FillXaos()
|
||||
{
|
||||
for (int i = 0, count = int(XformCount()); i < count; i++)
|
||||
for (int i = 0, count = int(XformCount()); i < count; i++)//Column.
|
||||
{
|
||||
if (auto xform = m_Ember.GetXform(i))
|
||||
{
|
||||
for (int j = 0; j < count; j++)
|
||||
for (int j = 0; j < count; j++)//Row.
|
||||
{
|
||||
QModelIndex index = m_Fractorium->m_XaosTableModel->index(i, j, QModelIndex());
|
||||
QModelIndex index = m_Fractorium->m_XaosTableModel->index(j, i, QModelIndex());//j and i are intentionally swapped here.
|
||||
m_Fractorium->m_XaosTableModel->setData(index, xform->Xaos(j));
|
||||
}
|
||||
}
|
||||
@@ -57,7 +57,9 @@ void FractoriumEmberController<T>::FillXaos()
|
||||
/// xaos value.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="sender">The DoubleSpinBox that triggered this event</param>
|
||||
/// <param name="x">The index of the xform whose xaos value was changed (column)</param>
|
||||
/// <param name="y">The index of the to value that was changed for the xform (row)</param>
|
||||
/// <param name="val">The changed value of the xaos element</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::XaosChanged(int x, int y, double val)
|
||||
{
|
||||
@@ -73,13 +75,13 @@ void Fractorium::OnXaosChanged(double d)
|
||||
if (auto senderSpinBox = qobject_cast<DoubleSpinBox*>(sender()))
|
||||
{
|
||||
auto p = senderSpinBox->property("tableindex").toPoint();
|
||||
m_Controller->XaosChanged(p.x(), p.y(), d);
|
||||
m_Controller->XaosChanged(p.y(), p.x(), d);//Intentionally switched, column is the from xform, row is the to xform.
|
||||
}
|
||||
}
|
||||
|
||||
void Fractorium::OnXaosTableModelDataChanged(const QModelIndex& indexA, const QModelIndex& indexB)
|
||||
{
|
||||
m_Controller->XaosChanged(indexA.row(), indexA.column(), indexA.data().toDouble());
|
||||
m_Controller->XaosChanged(indexA.column(), indexA.row(), indexA.data().toDouble());//Intentionally switched, column is the from xform, row is the to xform.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -190,5 +192,5 @@ void Fractorium::OnXaosColDoubleClicked(int logicalIndex)
|
||||
template class FractoriumEmberController<float>;
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
template class FractoriumEmberController<double>;
|
||||
template class FractoriumEmberController<double>;
|
||||
#endif
|
||||
|
||||
@@ -104,6 +104,7 @@ void FractoriumEmberController<T>::AddXform()
|
||||
Xform<T> newXform;
|
||||
newXform.m_Weight = 0.25;
|
||||
newXform.m_ColorX = m_Rand.Frand01<T>();
|
||||
newXform.AddVariation(m_VariationList->GetVariationCopy(eVariationId::VAR_LINEAR));
|
||||
m_Ember.AddXform(newXform);
|
||||
int index = int(m_Ember.TotalXformCount(forceFinal) - (forceFinal ? 2 : 1));//Set index to the last item before final.
|
||||
FillXforms(index);
|
||||
@@ -115,7 +116,12 @@ void Fractorium::OnAddXformButtonClicked(bool checked) { m_Controller->AddXform(
|
||||
/// <summary>
|
||||
/// Add a new linked xform in the current ember and set it as the current xform.
|
||||
/// Linked means:
|
||||
///
|
||||
/// Add an xform whose xaos values are:
|
||||
/// From: All xaos values from the current xform are zero when going to any xform but the new one added, which is 1.
|
||||
/// To: The xaos value coming from the current xform is 1 and the xaos values from all other xforms are 0, when going to the newly added xform.
|
||||
/// Take different action when a single xform is selected vs. multiple.
|
||||
/// Single: Copy current xform's xaos values to the new one.
|
||||
/// Multiple: Set new xform's xaos values to 1, and except the last entry which is 0.
|
||||
/// Called when the add xform button is clicked.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
@@ -123,40 +129,71 @@ void Fractorium::OnAddXformButtonClicked(bool checked) { m_Controller->AddXform(
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::AddLinkedXform()
|
||||
{
|
||||
bool hasAdded = false;
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
auto selCount = m_Fractorium->SelectedXformCount(false);
|
||||
|
||||
if (!selCount)//If none explicitly selected, use current.
|
||||
selCount = 1;
|
||||
|
||||
Ember<T> ember = m_Ember;
|
||||
m_Ember.Reserve(m_Ember.XformCount() + 1);//Doing this ahead of time ensures pointers remain valid.
|
||||
auto iterCount = 0;
|
||||
UpdateXform([&](Xform<T>* xform)
|
||||
{
|
||||
size_t i, count = m_Ember.XformCount();
|
||||
Xform<T> newXform;
|
||||
newXform.m_Weight = 0.5;
|
||||
newXform.m_Opacity = 1;
|
||||
newXform.m_ColorSpeed = 1;
|
||||
newXform.m_ColorX = xform->m_ColorX;
|
||||
//newXform.m_ColorY = xform->m_ColorY;
|
||||
|
||||
//Set all of the new xform's xaos values to the selected xform's xaos values,
|
||||
//then set the selected xform's xaos values to 0.
|
||||
for (i = 0; i < count; i++)
|
||||
//Covers very strange case where final is selected, but initially not considered because final is excluded,
|
||||
//but after adding the new xform, it thinks its selected index is non-final.
|
||||
if (iterCount < selCount)
|
||||
{
|
||||
newXform.SetXaos(i, xform->Xaos(i));
|
||||
xform->SetXaos(i, 0);
|
||||
size_t i, count = m_Ember.XformCount();
|
||||
|
||||
if (!hasAdded)
|
||||
{
|
||||
Xform<T> newXform;
|
||||
newXform.m_Weight = 0.5;
|
||||
newXform.m_Opacity = xform->m_Opacity;
|
||||
newXform.m_ColorSpeed = 0;
|
||||
newXform.m_ColorX = 0;
|
||||
//newXform.m_ColorY = xform->m_ColorY;
|
||||
newXform.AddVariation(m_VariationList->GetVariationCopy(eVariationId::VAR_LINEAR));
|
||||
|
||||
//Set all of the new xform's xaos values to the selected xform's xaos values,
|
||||
//then set the selected xform's xaos values to 0.
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (selCount == 1)
|
||||
newXform.SetXaos(i, xform->Xaos(i));
|
||||
else
|
||||
newXform.SetXaos(i, 1);
|
||||
}
|
||||
|
||||
//Add the new xform and update the total count.
|
||||
m_Ember.AddXform(newXform);
|
||||
count = m_Ember.XformCount();
|
||||
|
||||
//Set the xaos for all xforms pointing to the new one to zero.
|
||||
//Will set the last element of all linking and non-linking xforms, including the one we just added.
|
||||
//Linking xforms will have their last xaos element set to 1 below.
|
||||
for (i = 0; i < count; i++)
|
||||
if (auto xf = m_Ember.GetXform(i))
|
||||
xf->SetXaos(count - 1, 0);
|
||||
|
||||
hasAdded = true;
|
||||
}
|
||||
|
||||
//Linking xform, so set all xaos elements to 0, except the last.
|
||||
for (i = 0; i < count - 1; i++)
|
||||
xform->SetXaos(i, 0);
|
||||
|
||||
xform->SetXaos(count - 1, 1);//Set the xaos value for the linking xform pointing to the new one to one.
|
||||
xform->m_Opacity = 0;//Clear the opacity of the all linking xform.
|
||||
iterCount++;
|
||||
}
|
||||
|
||||
//Add the new xform and update the total count.
|
||||
m_Ember.AddXform(newXform);
|
||||
count = m_Ember.XformCount();
|
||||
|
||||
//Set the xaos for all xforms pointing to the new one to zero.
|
||||
for (i = 0; i < count; i++)
|
||||
if (auto xf = m_Ember.GetXform(i))
|
||||
xf->SetXaos(count - 1, 0);
|
||||
|
||||
xform->SetXaos(count - 1, 1);//Set the xaos value for the previous xform pointing to the new one to one.
|
||||
xform->m_Opacity = 0;//Clear the opacity of the previous xform.
|
||||
int index = int(m_Ember.TotalXformCount(forceFinal) - (forceFinal ? 2 : 1));//Set index to the last item before final.
|
||||
FillXforms(index);
|
||||
FillXaos();
|
||||
}, eXformUpdate::UPDATE_CURRENT);
|
||||
}, eXformUpdate::UPDATE_SELECTED_EXCEPT_FINAL);
|
||||
//Now update the GUI.
|
||||
int index = int(m_Ember.TotalXformCount(forceFinal) - (forceFinal ? 2 : 1));//Set index to the last item before final.
|
||||
FillXforms(index);
|
||||
FillXaos();
|
||||
}
|
||||
|
||||
void Fractorium::OnAddLinkedXformButtonClicked(bool checked) { m_Controller->AddLinkedXform(); }
|
||||
|
||||
@@ -38,6 +38,25 @@ bool Fractorium::IsXformSelected(size_t i)
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the number of xforms selected, optionally counting the final xform.
|
||||
/// </summary>
|
||||
/// <param name="includeFinal">Whether to include the final in the count if selected.</param>
|
||||
/// <returns>The caption string</returns>
|
||||
int Fractorium::SelectedXformCount(bool includeFinal)
|
||||
{
|
||||
int selCount = 0;
|
||||
ForEachXformCheckbox([&](int index, QCheckBox * cb, bool isFinal)
|
||||
{
|
||||
if (cb->isChecked())
|
||||
{
|
||||
if (!isFinal || includeFinal)
|
||||
selCount++;
|
||||
}
|
||||
});
|
||||
return selCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear all of the dynamically created xform checkboxes.
|
||||
/// </summary>
|
||||
@@ -81,7 +100,7 @@ QString FractoriumEmberController<T>::MakeXformCaption(size_t i)
|
||||
/// <summary>
|
||||
/// Function to perform the specified operation on every dynamically created xform selection checkbox.
|
||||
/// </summary>
|
||||
/// <param name="func">The operation to perform</param>
|
||||
/// <param name="func">The operation to perform which is a function taking the index of the xform, its checkbox, and a bool specifying whether it's final.</param>
|
||||
void Fractorium::ForEachXformCheckbox(std::function<void(int, QCheckBox*, bool)> func)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
@@ -32,13 +32,36 @@ void GLWidget::InitGL()
|
||||
{
|
||||
if (!m_Init)
|
||||
{
|
||||
int w = m_Fractorium->ui.GLParentScrollArea->width();
|
||||
int h = m_Fractorium->ui.GLParentScrollArea->height();
|
||||
int w = std::ceil(m_Fractorium->ui.GLParentScrollArea->width() * devicePixelRatioF());
|
||||
int h = std::ceil(m_Fractorium->ui.GLParentScrollArea->height() * devicePixelRatioF());
|
||||
SetDimensions(w, h);
|
||||
m_Fractorium->m_WidthSpin->setValue(w);
|
||||
m_Fractorium->m_HeightSpin->setValue(h);
|
||||
//Start with a flock of random embers. Can't do this until now because the window wasn't maximized yet, so the sizes would have been off.
|
||||
m_Fractorium->OnActionNewFlock(false);
|
||||
//Start with either a flock of random embers, or the last flame from the previous run.
|
||||
//Can't do this until now because the window wasn't maximized yet, so the sizes would have been off.
|
||||
bool b = m_Fractorium->m_Settings->LoadLast();
|
||||
|
||||
if (b)
|
||||
{
|
||||
auto path = GetDefaultUserPath();
|
||||
QDir dir(path);
|
||||
QString filename = path + "/lastonshutdown.flame";
|
||||
|
||||
if (dir.exists(filename))
|
||||
{
|
||||
QStringList ql;
|
||||
ql << filename;
|
||||
m_Fractorium->m_Controller->OpenAndPrepFiles(ql, false);
|
||||
}
|
||||
else
|
||||
b = false;
|
||||
}
|
||||
|
||||
if (!b)
|
||||
{
|
||||
m_Fractorium->OnActionNewFlock(false);
|
||||
m_Fractorium->m_WidthSpin->setValue(w);
|
||||
m_Fractorium->m_HeightSpin->setValue(h);
|
||||
}
|
||||
|
||||
m_Fractorium->m_Controller->DelayedStartRenderTimer();
|
||||
m_Init = true;
|
||||
}
|
||||
@@ -61,9 +84,14 @@ void GLWidget::DrawQuad()
|
||||
if (m_OutputTexID != 0 && finalImage && !finalImage->empty())
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, m_OutputTexID);//The texture to draw to.
|
||||
auto scaledW = std::ceil(width() * devicePixelRatioF());
|
||||
auto scaledH = std::ceil(height() * devicePixelRatioF());
|
||||
|
||||
//Only draw if the dimensions match exactly.
|
||||
if (m_TexWidth == width() && m_TexHeight == height() && ((m_TexWidth * m_TexHeight) == GLint(finalImage->size())))
|
||||
if (m_TexWidth == m_Fractorium->m_Controller->FinalRasW() &&
|
||||
m_TexHeight == m_Fractorium->m_Controller->FinalRasH() &&
|
||||
((m_TexWidth * m_TexHeight) == GLint(finalImage->size())))
|
||||
//if (m_TexWidth == scaledW && m_TexHeight == scaledH && ((m_TexWidth * m_TexHeight) == GLint(finalImage->size())))
|
||||
{
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
@@ -337,16 +365,16 @@ void GLEmberController<T>::DrawAffines(bool pre, bool post)
|
||||
|
||||
if (dragging)//Draw large yellow dot on select or drag.
|
||||
{
|
||||
m_GL->glPointSize(6.0f);
|
||||
m_GL->glPointSize(6.0f * m_GL->devicePixelRatioF());
|
||||
m_GL->glBegin(GL_POINTS);
|
||||
m_GL->glColor4f(1.0f, 1.0f, 0.5f, 1.0f);
|
||||
m_GL->glVertex2f(m_DragHandlePos.x, m_DragHandlePos.y);
|
||||
m_GL->glEnd();
|
||||
m_GL->glPointSize(1.0f);//Restore point size.
|
||||
m_GL->glPointSize(1.0f * m_GL->devicePixelRatioF());//Restore point size.
|
||||
}
|
||||
else if (m_DragState == eDragState::DragSelect)
|
||||
{
|
||||
m_GL->glLineWidth(2.0f);
|
||||
m_GL->glLineWidth(2.0f * m_GL->devicePixelRatioF());
|
||||
m_GL->glBegin(GL_LINES);
|
||||
m_GL->glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
m_GL->glVertex2f(m_MouseDownWorldPos.x, m_MouseDownWorldPos.y);//UL->UR
|
||||
@@ -358,16 +386,16 @@ void GLEmberController<T>::DrawAffines(bool pre, bool post)
|
||||
m_GL->glVertex2f(m_MouseWorldPos.x, m_MouseDownWorldPos.y);//UR->LR
|
||||
m_GL->glVertex2f(m_MouseWorldPos.x, m_MouseWorldPos.y);
|
||||
m_GL->glEnd();
|
||||
m_GL->glLineWidth(1.0f);
|
||||
m_GL->glLineWidth(1.0f * m_GL->devicePixelRatioF());
|
||||
}
|
||||
else if (m_HoverType != eHoverType::HoverNone && m_HoverXform == m_SelectedXform)//Draw large turquoise dot on hover if they are hovering over the selected xform.
|
||||
{
|
||||
m_GL->glPointSize(6.0f);
|
||||
m_GL->glPointSize(6.0f * m_GL->devicePixelRatioF());
|
||||
m_GL->glBegin(GL_POINTS);
|
||||
m_GL->glColor4f(0.5f, 1.0f, 1.0f, 1.0f);
|
||||
m_GL->glVertex2f(m_HoverHandlePos.x, m_HoverHandlePos.y);
|
||||
m_GL->glEnd();
|
||||
m_GL->glPointSize(1.0f);
|
||||
m_GL->glPointSize(1.0f * m_GL->devicePixelRatioF());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -435,7 +463,7 @@ void GLWidget::keyReleaseEvent(QKeyEvent* e)
|
||||
template <typename T>
|
||||
void GLEmberController<T>::MousePress(QMouseEvent* e)
|
||||
{
|
||||
v3T mouseFlipped(e->x() * m_GL->devicePixelRatio(), m_Viewport[3] - e->y() * m_GL->devicePixelRatio(), 0);//Must flip y because in OpenGL, 0,0 is bottom left, but in windows, it's top left.
|
||||
v3T mouseFlipped(e->x() * m_GL->devicePixelRatioF(), m_Viewport[3] - e->y() * m_GL->devicePixelRatioF(), 0);//Must flip y because in OpenGL, 0,0 is bottom left, but in windows, it's top left.
|
||||
auto ember = m_FractoriumEmberController->CurrentEmber();
|
||||
auto renderer = m_FractoriumEmberController->Renderer();
|
||||
|
||||
@@ -443,7 +471,7 @@ void GLEmberController<T>::MousePress(QMouseEvent* e)
|
||||
if (!renderer)
|
||||
return;
|
||||
|
||||
m_MouseDownPos = glm::ivec2(e->x() * m_GL->devicePixelRatio(), e->y() * m_GL->devicePixelRatio());//Capture the raster coordinates of where the mouse was clicked.
|
||||
m_MouseDownPos = glm::ivec2(e->x() * m_GL->devicePixelRatioF(), e->y() * m_GL->devicePixelRatioF());//Capture the raster coordinates of where the mouse was clicked.
|
||||
m_MouseWorldPos = WindowToWorld(mouseFlipped, false);//Capture the world cartesian coordinates of where the mouse is.
|
||||
m_BoundsDown.w = renderer->LowerLeftX(false);//Need to capture these because they'll be changing if scaling.
|
||||
m_BoundsDown.x = renderer->LowerLeftY(false);
|
||||
@@ -530,7 +558,7 @@ void GLWidget::mousePressEvent(QMouseEvent* e)
|
||||
template <typename T>
|
||||
void GLEmberController<T>::MouseRelease(QMouseEvent* e)
|
||||
{
|
||||
v3T mouseFlipped(e->x() * m_GL->devicePixelRatio(), m_Viewport[3] - e->y() * m_GL->devicePixelRatio(), 0);//Must flip y because in OpenGL, 0,0 is bottom left, but in windows, it's top left.
|
||||
v3T mouseFlipped(e->x() * m_GL->devicePixelRatioF(), m_Viewport[3] - e->y() * m_GL->devicePixelRatioF(), 0);//Must flip y because in OpenGL, 0,0 is bottom left, but in windows, it's top left.
|
||||
m_MouseWorldPos = WindowToWorld(mouseFlipped, false);
|
||||
|
||||
if (m_DragState == eDragState::DragDragging && (e->button() & Qt::LeftButton))
|
||||
@@ -567,8 +595,8 @@ template <typename T>
|
||||
void GLEmberController<T>::MouseMove(QMouseEvent* e)
|
||||
{
|
||||
bool draw = true;
|
||||
glm::ivec2 mouse(e->x() * m_GL->devicePixelRatio(), e->y() * m_GL->devicePixelRatio());
|
||||
v3T mouseFlipped(e->x() * m_GL->devicePixelRatio(), m_Viewport[3] - e->y() * m_GL->devicePixelRatio(), 0);//Must flip y because in OpenGL, 0,0 is bottom left, but in windows, it's top left.
|
||||
glm::ivec2 mouse(e->x() * m_GL->devicePixelRatioF(), e->y() * m_GL->devicePixelRatioF());
|
||||
v3T mouseFlipped(e->x() * m_GL->devicePixelRatioF(), m_Viewport[3] - e->y() * m_GL->devicePixelRatioF(), 0);//Must flip y because in OpenGL, 0,0 is bottom left, but in windows, it's top left.
|
||||
auto ember = m_FractoriumEmberController->CurrentEmber();
|
||||
|
||||
//First check to see if the mouse actually moved.
|
||||
@@ -580,7 +608,7 @@ void GLEmberController<T>::MouseMove(QMouseEvent* e)
|
||||
|
||||
//Update status bar on main window, regardless of whether anything is being dragged.
|
||||
if (m_Fractorium->m_Controller->RenderTimerRunning())
|
||||
m_Fractorium->SetCoordinateStatus(e->x() * m_GL->devicePixelRatio(), e->y() * m_GL->devicePixelRatio(), m_MouseWorldPos.x, m_MouseWorldPos.y);
|
||||
m_Fractorium->SetCoordinateStatus(e->x() * m_GL->devicePixelRatioF(), e->y() * m_GL->devicePixelRatioF(), m_MouseWorldPos.x, m_MouseWorldPos.y);
|
||||
|
||||
if (m_SelectedXform && m_DragState == eDragState::DragDragging)//Dragging and affine.
|
||||
{
|
||||
@@ -723,7 +751,9 @@ void GLWidget::wheelEvent(QWheelEvent* e)
|
||||
/// <param name="h">Height in pixels</param>
|
||||
void GLWidget::SetDimensions(int w, int h)
|
||||
{
|
||||
setFixedSize(w, h);
|
||||
auto downscaledW = std::ceil(w / devicePixelRatioF());
|
||||
auto downscaledH = std::ceil(h / devicePixelRatioF());
|
||||
setFixedSize(downscaledW, downscaledH);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -736,13 +766,18 @@ void GLWidget::SetDimensions(int w, int h)
|
||||
bool GLWidget::Allocate(bool force)
|
||||
{
|
||||
bool alloc = false;
|
||||
bool doResize = force || m_TexWidth != width() || m_TexHeight != height();
|
||||
//auto scaledW = std::ceil(width() * devicePixelRatioF());
|
||||
auto w = m_Fractorium->m_Controller->FinalRasW();
|
||||
auto h = m_Fractorium->m_Controller->FinalRasH();
|
||||
bool doResize = force || m_TexWidth != w || m_TexHeight != h;
|
||||
bool doIt = doResize || m_OutputTexID == 0;
|
||||
|
||||
if (doIt)
|
||||
{
|
||||
m_TexWidth = width();
|
||||
m_TexHeight = height();
|
||||
//m_TexWidth = scaledW;
|
||||
//m_TexHeight = scaledH;
|
||||
m_TexWidth = GLint(w);
|
||||
m_TexHeight = GLint(h);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
|
||||
@@ -811,12 +846,12 @@ void GLWidget::SetViewport()
|
||||
template <typename T>
|
||||
bool GLEmberController<T>::SizesMatch()
|
||||
{
|
||||
//auto scaledW = std::ceil(m_GL->width() * m_GL->devicePixelRatioF());
|
||||
//auto scaledH = std::ceil(m_GL->height() * m_GL->devicePixelRatioF());
|
||||
auto ember = m_FractoriumEmberController->CurrentEmber();
|
||||
return (ember &&
|
||||
ember->m_FinalRasW == m_GL->width() &&
|
||||
ember->m_FinalRasH == m_GL->height() &&
|
||||
m_GL->width() == m_GL->m_TexWidth &&
|
||||
m_GL->height() == m_GL->m_TexHeight &&
|
||||
ember->m_FinalRasW == m_GL->m_TexWidth &&
|
||||
ember->m_FinalRasH == m_GL->m_TexHeight &&
|
||||
m_GL->m_TexWidth == m_GL->m_ViewWidth &&
|
||||
m_GL->m_TexHeight == m_GL->m_ViewHeight);
|
||||
}
|
||||
@@ -826,7 +861,7 @@ bool GLEmberController<T>::SizesMatch()
|
||||
/// </summary>
|
||||
void GLWidget::DrawUnitSquare()
|
||||
{
|
||||
glLineWidth(1.0f);
|
||||
glLineWidth(1.0f * devicePixelRatioF());
|
||||
glBegin(GL_LINES);
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 0.25f);
|
||||
glVertex2f(-1, -1);
|
||||
@@ -868,7 +903,7 @@ void GLEmberController<T>::DrawGrid()
|
||||
m_GL->glPushMatrix();
|
||||
m_GL->glLoadIdentity();
|
||||
MultMatrix(mat);
|
||||
m_GL->glLineWidth(1.0f);
|
||||
m_GL->glLineWidth(1.0f * m_GL->devicePixelRatioF());
|
||||
m_GL->glBegin(GL_LINES);
|
||||
m_GL->glColor4f(0.5f, 0.5f, 0.5f, alpha);
|
||||
|
||||
@@ -924,24 +959,24 @@ void GLEmberController<T>::DrawAffine(Xform<T>* xform, bool pre, bool selected)
|
||||
m_GL->glPushMatrix();
|
||||
m_GL->glLoadIdentity();
|
||||
MultMatrix(mat);
|
||||
m_GL->glLineWidth(3.0f);//One 3px wide, colored black, except green on x axis for post affine.
|
||||
m_GL->glLineWidth(3.0f * m_GL->devicePixelRatioF());//One 3px wide, colored black, except green on x axis for post affine.
|
||||
m_GL->DrawAffineHelper(index, selected, pre, final, true);
|
||||
m_GL->glLineWidth(1.0f);//Again 1px wide, colored white, to give a white middle with black outline effect.
|
||||
m_GL->glLineWidth(1.0f * m_GL->devicePixelRatioF());//Again 1px wide, colored white, to give a white middle with black outline effect.
|
||||
m_GL->DrawAffineHelper(index, selected, pre, final, false);
|
||||
m_GL->glPointSize(5.0f);//Three black points, one in the center and two on the circle. Drawn big 5px first to give a black outline.
|
||||
m_GL->glPointSize(5.0f * m_GL->devicePixelRatioF());//Three black points, one in the center and two on the circle. Drawn big 5px first to give a black outline.
|
||||
m_GL->glBegin(GL_POINTS);
|
||||
m_GL->glColor4f(0.0f, 0.0f, 0.0f, selected ? 1.0f : 0.5f);
|
||||
m_GL->glVertex2f(0.0f, 0.0f);
|
||||
m_GL->glVertex2f(1.0f, 0.0f);
|
||||
m_GL->glVertex2f(0.0f, 1.0f);
|
||||
m_GL->glEnd();
|
||||
m_GL->glLineWidth(2.0f);//Draw lines again for y axis only, without drawing the circle, using the color of the selected xform.
|
||||
m_GL->glLineWidth(2.0f * m_GL->devicePixelRatioF());//Draw lines again for y axis only, without drawing the circle, using the color of the selected xform.
|
||||
m_GL->glBegin(GL_LINES);
|
||||
m_GL->glColor4f(color.r, color.g, color.b, 1.0f);
|
||||
m_GL->glVertex2f(0.0f, 0.0f);
|
||||
m_GL->glVertex2f(0.0f, 1.0f);
|
||||
m_GL->glEnd();
|
||||
m_GL->glPointSize(3.0f);//Draw smaller white points, to give a black outline effect.
|
||||
m_GL->glPointSize(3.0f * m_GL->devicePixelRatioF());//Draw smaller white points, to give a black outline effect.
|
||||
m_GL->glBegin(GL_POINTS);
|
||||
m_GL->glColor4f(1.0f, 1.0f, 1.0f, selected ? 1.0f : 0.5f);
|
||||
m_GL->glVertex2f(0.0f, 0.0f);
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int rv = -1;
|
||||
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
QApplication a(argc, argv);
|
||||
#ifdef TEST_CL
|
||||
QMessageBox::critical(QApplication::desktop(), "Error", "Fractorium cannot be run in test mode, undefine TEST_CL first.");
|
||||
|
||||
@@ -46,6 +46,7 @@ FractoriumOptionsDialog::FractoriumOptionsDialog(QWidget* p, Qt::WindowFlags f)
|
||||
ui.OpenCLCheckBox->setChecked(false);
|
||||
ui.OpenCLCheckBox->setEnabled(false);
|
||||
ui.OpenCLSubBatchSpin->setEnabled(false);
|
||||
ui.OpenCLQualitySpin->setEnabled(false);
|
||||
ui.OpenCLFilteringDERadioButton->setEnabled(false);
|
||||
ui.OpenCLFilteringLogRadioButton->setEnabled(false);
|
||||
ui.InteraciveGpuFilteringGroupBox->setEnabled(false);
|
||||
@@ -69,8 +70,11 @@ bool FractoriumOptionsDialog::ShowAllXforms() { return ui.ShowAllXformsCheckBox-
|
||||
bool FractoriumOptionsDialog::ToggleType() { return ui.ToggleTypeCheckBox->isChecked(); }
|
||||
bool FractoriumOptionsDialog::Png16Bit() { return ui.Png16BitCheckBox->isChecked(); }
|
||||
bool FractoriumOptionsDialog::AutoUnique() { return ui.AutoUniqueCheckBox->isChecked(); }
|
||||
bool FractoriumOptionsDialog::LoadLast() { return ui.LoadLastOnStartCheckBox->isChecked(); }
|
||||
uint FractoriumOptionsDialog::ThreadCount() { return ui.ThreadCountSpin->value(); }
|
||||
uint FractoriumOptionsDialog::RandomCount() { return ui.RandomCountSpin->value(); }
|
||||
uint FractoriumOptionsDialog::CpuQuality() { return ui.CpuQualitySpin->value(); }
|
||||
uint FractoriumOptionsDialog::OpenClQuality() { return ui.OpenCLQualitySpin->value(); }
|
||||
|
||||
/// <summary>
|
||||
/// The check state of one of the OpenCL devices was changed.
|
||||
@@ -122,6 +126,8 @@ void FractoriumOptionsDialog::OnOpenCLCheckBoxStateChanged(int state)
|
||||
ui.ThreadCountSpin->setEnabled(!checked);
|
||||
ui.CpuSubBatchSpin->setEnabled(!checked);
|
||||
ui.OpenCLSubBatchSpin->setEnabled(checked);
|
||||
ui.OpenCLQualitySpin->setEnabled(checked);
|
||||
ui.CpuQualitySpin->setEnabled(!checked);
|
||||
ui.CpuFilteringDERadioButton->setEnabled(!checked);
|
||||
ui.CpuFilteringLogRadioButton->setEnabled(!checked);
|
||||
ui.OpenCLFilteringDERadioButton->setEnabled(checked);
|
||||
@@ -178,6 +184,9 @@ void FractoriumOptionsDialog::GuiToData()
|
||||
m_Settings->Png16Bit(Png16Bit());
|
||||
m_Settings->ThreadCount(ThreadCount());
|
||||
m_Settings->RandomCount(RandomCount());
|
||||
m_Settings->LoadLast(LoadLast());
|
||||
m_Settings->CpuQuality(CpuQuality());
|
||||
m_Settings->OpenClQuality(OpenClQuality());
|
||||
m_Settings->CpuSubBatch(ui.CpuSubBatchSpin->value());
|
||||
m_Settings->OpenCLSubBatch(ui.OpenCLSubBatchSpin->value());
|
||||
m_Settings->CpuDEFilter(ui.CpuFilteringDERadioButton->isChecked());
|
||||
@@ -212,6 +221,9 @@ void FractoriumOptionsDialog::DataToGui()
|
||||
ui.Png16BitCheckBox->setChecked(m_Settings->Png16Bit());
|
||||
ui.ThreadCountSpin->setValue(m_Settings->ThreadCount());
|
||||
ui.RandomCountSpin->setValue(m_Settings->RandomCount());
|
||||
ui.LoadLastOnStartCheckBox->setChecked(m_Settings->LoadLast());
|
||||
ui.CpuQualitySpin->setValue(m_Settings->CpuQuality());
|
||||
ui.OpenCLQualitySpin->setValue(m_Settings->OpenClQuality());
|
||||
ui.CpuSubBatchSpin->setValue(m_Settings->CpuSubBatch());
|
||||
ui.OpenCLSubBatchSpin->setValue(m_Settings->OpenCLSubBatch());
|
||||
SettingsToDeviceTable(ui.DeviceTable, devices);
|
||||
|
||||
@@ -47,8 +47,11 @@ private:
|
||||
bool ToggleType();
|
||||
bool Png16Bit();
|
||||
bool AutoUnique();
|
||||
bool LoadLast();
|
||||
uint ThreadCount();
|
||||
uint RandomCount();
|
||||
uint CpuQuality();
|
||||
uint OpenClQuality();
|
||||
void DataToGui();
|
||||
void GuiToData();
|
||||
|
||||
|
||||
+225
-170
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>427</width>
|
||||
<height>487</height>
|
||||
<height>475</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@@ -169,6 +169,26 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="ToggleTypeCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Checked: right clicking toggles spin boxes, right button dragging disabled.</p><p>Unchecked: double clicking toggles spin boxes, right button dragging enabled.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Right Click Toggles Spinboxes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="Png16BitCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Save each RGBA component as 16-bits when saving Png files.</p><p>This leads to greater color precision for use in high end rendering and display on HDR monitors, however it makes the file size larger.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save 16-bit Png</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QTableWidget" name="DeviceTable">
|
||||
<property name="sizePolicy">
|
||||
@@ -257,180 +277,212 @@
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QSpinBox" name="ThreadCountSpin">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The number of threads to use with CPU rendering.</p><p>Decrease for more responsive editing, increase for better performance.</p></body></html></string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>Threads </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>64</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QSpinBox" name="CpuSubBatchSpin">
|
||||
<property name="toolTip">
|
||||
<string>The number of 10,000 iteration chunks ran per thread on the CPU
|
||||
<item row="15" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="InteractiveRenderingTabGridLayout">
|
||||
<item row="3" column="1">
|
||||
<widget class="QGroupBox" name="InteraciveGpuFilteringGroupBox">
|
||||
<property name="title">
|
||||
<string>OpenCL Filtering</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="OpenCLFilteringLogRadioButton">
|
||||
<property name="toolTip">
|
||||
<string>Use log scale filtering for interactive editing using OpenCL.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Log Scale</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="OpenCLFilteringDERadioButton">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Use full density estimation filtering for interactive editing using OpenCL.</p><p>This is slower, but gives better feedback.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Full DE</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QGroupBox" name="InteraciveCpuFilteringGroupBox">
|
||||
<property name="title">
|
||||
<string>CPU Filtering</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="CpuFilteringLogRadioButton">
|
||||
<property name="toolTip">
|
||||
<string>Use log scale filtering for interactive editing on the CPU.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Log Scale</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="CpuFilteringDERadioButton">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Use full density estimation filtering for interactive editing on the CPU.</p><p>This is slower, but gives better feedback.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Full DE</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QSpinBox" name="OpenCLSubBatchSpin">
|
||||
<property name="toolTip">
|
||||
<string>The number of ~8M iteration chunks ran using OpenCL
|
||||
in interactive mode for each mouse movement</string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>CPU Sub Batch </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QSpinBox" name="OpenCLSubBatchSpin">
|
||||
<property name="toolTip">
|
||||
<string>The number of ~8M iteration chunks ran using OpenCL
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>OpenCL Sub Batch </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="OpenCLQualitySpin">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The default quality to use for the interactive renderer when using OpenCL.</p><p>30 is a good number for this, but you can use a larger value if you have a faster GPU.</p></body></html></string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>OpenCL Quality </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>30</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="CpuQualitySpin">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The default quality to use for the interactive renderer when using the CPU.</p><p>10 is a good number for this, but you can use a larger value if you have a faster system.</p></body></html></string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>CPU Quality </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="CpuSubBatchSpin">
|
||||
<property name="toolTip">
|
||||
<string>The number of 10,000 iteration chunks ran per thread on the CPU
|
||||
in interactive mode for each mouse movement</string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>OpenCL Sub Batch </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>CPU Sub Batch </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QSpinBox" name="RandomCountSpin">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The number of random flames to generate on startup.</p><p>These are usually of low quality, so leave the count as 1 unless you are searching for good randoms.</p></body></html></string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>Randoms </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QSpinBox" name="ThreadCountSpin">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The number of threads to use with CPU rendering.</p><p>Decrease for more responsive editing, increase for better performance.</p></body></html></string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>Threads </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>64</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QGroupBox" name="InteraciveCpuFilteringGroupBox">
|
||||
<property name="title">
|
||||
<string>CPU Filtering</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="CpuFilteringLogRadioButton">
|
||||
<property name="toolTip">
|
||||
<string>Use log scale filtering for interactive editing on the CPU.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Log Scale</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="CpuFilteringDERadioButton">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Use full density estimation filtering for interactive editing on the CPU.</p><p>This is slower, but gives better feedback.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Full DE</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QGroupBox" name="InteraciveGpuFilteringGroupBox">
|
||||
<property name="title">
|
||||
<string>OpenCL Filtering</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="OpenCLFilteringLogRadioButton">
|
||||
<property name="toolTip">
|
||||
<string>Use log scale filtering for interactive editing using OpenCL.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Log Scale</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="OpenCLFilteringDERadioButton">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Use full density estimation filtering for interactive editing using OpenCL.</p><p>This is slower, but gives better feedback.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Full DE</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QSpinBox" name="RandomCountSpin">
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="LoadLastOnStartCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The number of random flames to generate on startup.</p><p>These are usually of low quality, so leave the count as 1 unless you are searching for good randoms.</p></body></html></string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>Randoms </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="ToggleTypeCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Checked: right clicking toggles spin boxes, right button dragging disabled.</p><p>Unchecked: double clicking toggles spin boxes, right button dragging enabled.</p></body></html></string>
|
||||
<string><html><head/><body><p>Checked: load the flame from the previous run on startup.</p><p>Unchecked: create randoms on startup.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Right Click Toggles Spinboxes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="Png16BitCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Save each RGBA component as 16-bits when saving Png files.</p><p>This leads to greater color precision for use in high end rendering and display on HDR monitors, however it makes the file size larger.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save 16-bit Png</string>
|
||||
<string>Load Last on Start</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -858,10 +910,13 @@ in interactive mode for each mouse movement</string>
|
||||
<tabstop>ContinuousUpdateCheckBox</tabstop>
|
||||
<tabstop>ToggleTypeCheckBox</tabstop>
|
||||
<tabstop>Png16BitCheckBox</tabstop>
|
||||
<tabstop>RandomCountSpin</tabstop>
|
||||
<tabstop>LoadLastOnStartCheckBox</tabstop>
|
||||
<tabstop>ThreadCountSpin</tabstop>
|
||||
<tabstop>CpuSubBatchSpin</tabstop>
|
||||
<tabstop>RandomCountSpin</tabstop>
|
||||
<tabstop>OpenCLQualitySpin</tabstop>
|
||||
<tabstop>OpenCLSubBatchSpin</tabstop>
|
||||
<tabstop>CpuQualitySpin</tabstop>
|
||||
<tabstop>CpuFilteringLogRadioButton</tabstop>
|
||||
<tabstop>CpuFilteringDERadioButton</tabstop>
|
||||
<tabstop>OpenCLFilteringLogRadioButton</tabstop>
|
||||
|
||||
Reference in New Issue
Block a user