mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-01-21 21:20:07 -05:00
745f06d29d
-Remove the Type field from the variations tree and instead just put the type indicator icon next to the variation name. -Double clicking to toggle variation parameter spinners now resets the value to the default if there is one, else it uses zero. If it is already using the default, it is toggled to 0. -Add a new button to toggle xaos on and off. -When duplicating a flame, insert it immediately after the one being duplicated instead of at the end of the file. -When switching between flames in a file, keep the same xform index selected rather than resetting it to the first xform each time. -Create a threaded writer for the final render and EmberAnimate so the rendering process does not get delayed by file saving which may take a long time. -Remove warning which said "Frames per rot cannot be greater than one while Rotations is zero" when generating a sequence. -Add the Circle_Rand variation from Chaotica. -Add tool tips to clarify the following items: --Auto Unique Filenames checkbox in the options dialog. --Xaos table headers. --Bug fixes -Generating sequences using the following variations would be done incorrectly: circletrans1, collideoscope, crob, curlsp, glynnsim1, glynnsim2, hypercrop, julian, julian, mobiusn, nblur, waves2, wavesn. -Adding/removing nodes from the color curve had accidentally been disabled. -The applied xaos weight table was not showing normalized weight values. -Changing the size of a flame was not observing the Apply To All checkbox. -Do not clamp the Rotate field to +/-180, because this causes the rotation to switch from CW to CCW during sequence generation. Instead, leave it exactly as the user entered it so the rotations proceed in the same direction.
4371 lines
148 KiB
C++
4371 lines
148 KiB
C++
#pragma once
|
|
|
|
#include "Variation.h"
|
|
|
|
namespace EmberNs
|
|
{
|
|
/// <summary>
|
|
/// bubble2.
|
|
/// </summary>
|
|
template <typename T>
|
|
class Bubble2Variation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
Bubble2Variation(T weight = 1.0) : ParametricVariation<T>("bubble2", eVariationId::VAR_BUBBLE2, weight, true)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(Bubble2Variation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
T t = Zeps(T(0.25) * (helper.m_PrecalcSumSquares + SQR(helper.In.z)) + 1);
|
|
T r = m_Weight / t;
|
|
helper.Out.x = helper.In.x * r * m_X;
|
|
helper.Out.y = helper.In.y * r * m_Y;
|
|
|
|
if (helper.In.z >= 0)
|
|
helper.Out.z = m_Weight * (helper.In.z + m_Z);
|
|
else
|
|
helper.Out.z = m_Weight * (helper.In.z - m_Z);
|
|
|
|
helper.Out.z += helper.In.z * r * m_Z;//The += is intentional.
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
intmax_t i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string index = ss2.str();
|
|
string weight = WeightDefineString();
|
|
string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string z = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\treal_t t = Zeps(fma((real_t)(0.25), fma(vIn.z, vIn.z, precalcSumSquares), (real_t)(1.0)));\n"
|
|
<< "\t\treal_t r = " << weight << " / t;\n"
|
|
<< "\n"
|
|
<< "\t\tvOut.x = vIn.x * r * " << x << ";\n"
|
|
<< "\t\tvOut.y = vIn.y * r * " << y << ";\n"
|
|
<< "\n"
|
|
<< "\t\tif (vIn.z >= 0)\n"
|
|
<< "\t\t vOut.z = " << weight << " * (vIn.z + " << z << ");\n"
|
|
<< "\t\telse\n"
|
|
<< "\t\t vOut.z = " << weight << " * (vIn.z - " << z << ");\n"
|
|
<< "\n"
|
|
<< "\t\tvOut.z += vIn.z * r * " << z << ";\n"
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual vector<string> OpenCLGlobalFuncNames() const override
|
|
{
|
|
return vector<string> { "Zeps" };
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(&m_X, prefix + "bubble2_x", 1));//Original used a prefix of bubble_, which is incompatible with Ember's design.
|
|
m_Params.push_back(ParamWithName<T>(&m_Y, prefix + "bubble2_y", 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_Z, prefix + "bubble2_z"));
|
|
}
|
|
|
|
private:
|
|
T m_X;
|
|
T m_Y;
|
|
T m_Z;
|
|
};
|
|
|
|
/// <summary>
|
|
/// CircleLinear.
|
|
/// </summary>
|
|
template <typename T>
|
|
class CircleLinearVariation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
CircleLinearVariation(T weight = 1.0) : ParametricVariation<T>("CircleLinear", eVariationId::VAR_CIRCLELINEAR, weight)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(CircleLinearVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
int m = int(Floor<T>(T(0.5) * helper.In.x / m_Sc));
|
|
int n = int(Floor<T>(T(0.5) * helper.In.y / m_Sc));
|
|
int m21 = m * 2 + 1;
|
|
int n21 = n * 2 + 1;
|
|
T x = helper.In.x - m21 * m_Sc;
|
|
T y = helper.In.y - n21 * m_Sc;
|
|
T u = Zeps(VarFuncs<T>::Hypot(x, y));
|
|
T v = (T(0.3) + T(0.7) * DiscreteNoise2(m + 10, n + 3)) * m_Sc;
|
|
T z1 = DiscreteNoise2(int(m + m_Seed), n);
|
|
|
|
if ((z1 < m_Dens1) && (u < v))
|
|
{
|
|
if (m_Reverse > 0)
|
|
{
|
|
if (z1 < m_Dens1 * m_Dens2)
|
|
{
|
|
x *= m_K;
|
|
y *= m_K;
|
|
}
|
|
else
|
|
{
|
|
T z = v / u * (1 - m_K) + m_K;
|
|
x *= z;
|
|
y *= z;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (z1 > m_Dens1 * m_Dens2)
|
|
{
|
|
x *= m_K;
|
|
y *= m_K;
|
|
}
|
|
else
|
|
{
|
|
T z = v / u * (1 - m_K) + m_K;
|
|
x *= z;
|
|
y *= z;
|
|
}
|
|
}
|
|
}
|
|
|
|
helper.Out.x = m_Weight * (x + m21 * m_Sc);
|
|
helper.Out.y = m_Weight * (y + n21 * m_Sc);
|
|
helper.Out.z = DefaultZ(helper);
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
intmax_t i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string index = ss2.str();
|
|
string weight = WeightDefineString();
|
|
string sc = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string k = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string dens1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string dens2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string reverse = "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 seed = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\tint m = (int)floor((real_t)(0.5) * vIn.x / " << sc << ");\n"
|
|
<< "\t\tint n = (int)floor((real_t)(0.5) * vIn.y / " << sc << ");\n"
|
|
<< "\t\tint m21 = m * 2 + 1;\n"
|
|
<< "\t\tint n21 = n * 2 + 1;\n"
|
|
<< "\t\treal_t x = vIn.x - m21 * " << sc << ";\n"
|
|
<< "\t\treal_t y = vIn.y - n21 * " << sc << ";\n"
|
|
<< "\t\treal_t u = Zeps(Hypot(x, y));\n"
|
|
<< "\t\treal_t v = fma(CircleLinearDiscreteNoise2(m + 10, n + 3), (real_t)(0.7), (real_t)(0.3)) * " << sc << ";\n"
|
|
<< "\t\treal_t z1 = CircleLinearDiscreteNoise2((int)(m + " << seed << "), n);\n"
|
|
<< "\n"
|
|
<< "\t\tif ((z1 < " << dens1 << ") && (u < v))\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t if (" << reverse << " > 0)\n"
|
|
<< "\t\t {\n"
|
|
<< "\t\t if (z1 < " << dens1 << " * " << dens2 << ")\n"
|
|
<< "\t\t {\n"
|
|
<< "\t\t x *= " << k << ";\n"
|
|
<< "\t\t y *= " << k << ";\n"
|
|
<< "\t\t }\n"
|
|
<< "\t\t else\n"
|
|
<< "\t\t {\n"
|
|
<< "\t\t real_t z = fma(v / u, (1 - " << k << "), " << k << ");\n"
|
|
<< "\n"
|
|
<< "\t\t x *= z;\n"
|
|
<< "\t\t y *= z;\n"
|
|
<< "\t\t }\n"
|
|
<< "\t\t }\n"
|
|
<< "\t\t else\n"
|
|
<< "\t\t {\n"
|
|
<< "\t\t if (z1 > " << dens1 << " * " << dens2 << ")\n"
|
|
<< "\t\t {\n"
|
|
<< "\t\t x *= " << k << ";\n"
|
|
<< "\t\t y *= " << k << ";\n"
|
|
<< "\t\t }\n"
|
|
<< "\t\t else\n"
|
|
<< "\t\t {\n"
|
|
<< "\t\t real_t z = fma(v / u, (1 - " << k << "), " << k << ");\n"
|
|
<< "\n"
|
|
<< "\t\t x *= z;\n"
|
|
<< "\t\t y *= z;\n"
|
|
<< "\t\t }\n"
|
|
<< "\t\t }\n"
|
|
<< "\t\t}\n"
|
|
<< "\n"
|
|
<< "\t\tvOut.x = " << weight << " * fma((real_t)m21, " << sc << ", x);\n"
|
|
<< "\t\tvOut.y = " << weight << " * fma((real_t)n21, " << sc << ", y);\n"
|
|
<< "\t\tvOut.z = " << DefaultZCl()
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual vector<string> OpenCLGlobalFuncNames() const override
|
|
{
|
|
return vector<string> { "Hypot", "Zeps" };
|
|
}
|
|
|
|
virtual string OpenCLFuncsString() const override
|
|
{
|
|
return
|
|
"real_t CircleLinearDiscreteNoise2(int x, int y)\n"
|
|
"{\n"
|
|
" const real_t im = 2147483647;\n"
|
|
" const real_t am = 1 / im;\n"
|
|
"\n"
|
|
" int n = x + y * 57;\n"
|
|
" n = (n << 13) ^ n;\n"
|
|
" return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) * am;\n"
|
|
"}\n"
|
|
"\n";
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(&m_Sc, prefix + "CircleLinear_Sc", 1, eParamType::REAL_NONZERO));
|
|
m_Params.push_back(ParamWithName<T>(&m_K, prefix + "CircleLinear_K", T(0.5)));
|
|
m_Params.push_back(ParamWithName<T>(&m_Dens1, prefix + "CircleLinear_Dens1", T(0.5)));
|
|
m_Params.push_back(ParamWithName<T>(&m_Dens2, prefix + "CircleLinear_Dens2", T(0.5)));
|
|
m_Params.push_back(ParamWithName<T>(&m_Reverse, prefix + "CircleLinear_Reverse", 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_X, prefix + "CircleLinear_X", 10));
|
|
m_Params.push_back(ParamWithName<T>(&m_Y, prefix + "CircleLinear_Y", 10));
|
|
m_Params.push_back(ParamWithName<T>(&m_Seed, prefix + "CircleLinear_Seed", 0, eParamType::INTEGER));
|
|
}
|
|
|
|
private:
|
|
T DiscreteNoise2(int x, int y)
|
|
{
|
|
const T im = T(2147483647);
|
|
const T am = (1 / im);
|
|
int n = x + y * 57;
|
|
n = (n << 13) ^ n;
|
|
return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) * am;
|
|
}
|
|
|
|
T m_Sc;
|
|
T m_K;
|
|
T m_Dens1;
|
|
T m_Dens2;
|
|
T m_Reverse;
|
|
T m_X;
|
|
T m_Y;
|
|
T m_Seed;
|
|
};
|
|
|
|
/// <summary>
|
|
/// CircleRand.
|
|
/// The original would loop infinitely as x and y approached zero, so put a check for a max of 10 iters.
|
|
/// </summary>
|
|
template <typename T>
|
|
class CircleRandVariation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
CircleRandVariation(T weight = 1.0) : ParametricVariation<T>("CircleRand", eVariationId::VAR_CIRCLERAND, weight)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(CircleRandVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
intmax_t m, n, iters = 0;
|
|
T x, y, u;
|
|
|
|
do
|
|
{
|
|
x = m_X * (1 - 2 * rand.Frand01<T>());
|
|
y = m_Y * (1 - 2 * rand.Frand01<T>());
|
|
m = Floor<T>(T(0.5) * x / m_Sc);
|
|
n = Floor<T>(T(0.5) * y / m_Sc);
|
|
x -= (m * 2 + 1) * m_Sc;
|
|
y -= (n * 2 + 1) * m_Sc;
|
|
u = VarFuncs<T>::Hypot(x, y);
|
|
|
|
if (++iters > 10)
|
|
break;
|
|
}
|
|
while ((DiscreteNoise2(int(m + m_Seed), int(n)) > m_Dens) || (u > (T(0.3) + T(0.7) * DiscreteNoise2(int(m + 10), int(n + 3))) * m_Sc));
|
|
|
|
helper.Out.x = m_Weight * (x + (m * 2 + 1) * m_Sc);
|
|
helper.Out.y = m_Weight * (y + (n * 2 + 1) * m_Sc);
|
|
helper.Out.z = DefaultZ(helper);
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
intmax_t i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string index = ss2.str();
|
|
string weight = WeightDefineString();
|
|
string sc = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string dens = "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 seed = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\tint m, n, iters = 0;\n"
|
|
<< "\t\treal_t x, y, u;\n"
|
|
<< "\n"
|
|
<< "\t\tdo\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t x = " << x << " * (1 - 2 * MwcNext01(mwc));\n"
|
|
<< "\t\t y = " << y << " * (1 - 2 * MwcNext01(mwc));\n"
|
|
<< "\t\t m = (int)floor((real_t)(0.5) * x / " << sc << ");\n"
|
|
<< "\t\t n = (int)floor((real_t)(0.5) * y / " << sc << ");\n"
|
|
<< "\t\t x = x - (m * 2 + 1) * " << sc << ";\n"
|
|
<< "\t\t y = y - (n * 2 + 1) * " << sc << ";\n"
|
|
<< "\t\t u = Hypot(x, y);\n"
|
|
<< "\n"
|
|
<< "\t\t if (++iters > 10)\n"
|
|
<< "\t\t break;\n"
|
|
<< "\t\t}\n"
|
|
<< "\t\twhile ((CircleRandDiscreteNoise2((int)(m + " << seed << "), n) > " << dens << ") || (u > fma(CircleRandDiscreteNoise2(m + 10, n + 3), (real_t)(0.7), (real_t)(0.3)) * " << sc << "));\n"
|
|
<< "\n"
|
|
<< "\t\tvOut.x = " << weight << " * fma((real_t)(m * 2 + 1), " << sc << ", x);\n"
|
|
<< "\t\tvOut.y = " << weight << " * fma((real_t)(n * 2 + 1), " << sc << ", y);\n"
|
|
<< "\t\tvOut.z = " << DefaultZCl()
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual vector<string> OpenCLGlobalFuncNames() const override
|
|
{
|
|
return vector<string> { "Hypot" };
|
|
}
|
|
|
|
virtual string OpenCLFuncsString() const override
|
|
{
|
|
return
|
|
"real_t CircleRandDiscreteNoise2(int x, int y)\n"
|
|
"{\n"
|
|
" const real_t im = 2147483647;\n"
|
|
" const real_t am = 1 / im;\n"
|
|
"\n"
|
|
" int n = x + y * 57;\n"
|
|
" n = (n << 13) ^ n;\n"
|
|
" return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) * am;\n"
|
|
"}\n"
|
|
"\n";
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(&m_Sc, prefix + "CircleRand_Sc", 1, eParamType::REAL_NONZERO));
|
|
m_Params.push_back(ParamWithName<T>(&m_Dens, prefix + "CircleRand_Dens", T(0.5)));
|
|
m_Params.push_back(ParamWithName<T>(&m_X, prefix + "CircleRand_X", 10));
|
|
m_Params.push_back(ParamWithName<T>(&m_Y, prefix + "CircleRand_Y", 10));
|
|
m_Params.push_back(ParamWithName<T>(&m_Seed, prefix + "CircleRand_Seed", 0, eParamType::INTEGER));
|
|
}
|
|
|
|
private:
|
|
T DiscreteNoise2(int x, int y)
|
|
{
|
|
const T im = T(2147483647);
|
|
const T am = (1 / im);
|
|
int n = x + y * 57;
|
|
n = (n << 13) ^ n;
|
|
return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) * am;
|
|
}
|
|
|
|
T m_Sc;
|
|
T m_Dens;
|
|
T m_X;
|
|
T m_Y;
|
|
T m_Seed;
|
|
};
|
|
|
|
/// <summary>
|
|
/// CircleTrans1.
|
|
/// The original would loop infinitely as x and y approached zero, so put a check for a max of 10 iters.
|
|
/// </summary>
|
|
template <typename T>
|
|
class CircleTrans1Variation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
CircleTrans1Variation(T weight = 1.0) : ParametricVariation<T>("CircleTrans1", eVariationId::VAR_CIRCLETRANS1, weight)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(CircleTrans1Variation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
T ux, uy, u, x, y;
|
|
Trans(m_X, m_Y, helper.In.x, helper.In.y, &ux, &uy);
|
|
intmax_t m = Floor<T>(T(0.5) * ux / m_Sc);
|
|
intmax_t n = Floor<T>(T(0.5) * uy / m_Sc);
|
|
x = ux - (m * 2 + 1) * m_Sc;
|
|
y = uy - (n * 2 + 1) * m_Sc;
|
|
u = VarFuncs<T>::Hypot(x, y);
|
|
|
|
if ((DiscreteNoise2(int(m + m_Seed), int(n)) > m_Dens) || (u > (T(0.3) + T(0.7) * DiscreteNoise2(int(m + 10), int(n + 3))) * m_Sc))
|
|
{
|
|
ux = ux;
|
|
uy = uy;
|
|
}
|
|
else
|
|
{
|
|
CircleR(&ux, &uy, rand);
|
|
}
|
|
|
|
helper.Out.x = m_Weight * ux;
|
|
helper.Out.y = m_Weight * uy;
|
|
helper.Out.z = DefaultZ(helper);
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
intmax_t i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string index = ss2.str();
|
|
string weight = WeightDefineString();
|
|
string sc = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string dens = "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 seed = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\treal_t ux, uy, u, x, y;\n"
|
|
<< "\n"
|
|
<< "\t\tCircleTrans1Trans(" << x << ", " << y << ", vIn.x, vIn.y, &ux, &uy);\n"
|
|
<< "\n"
|
|
<< "\t\tint m = (int)floor((real_t)(0.5) * ux / " << sc << ");\n"
|
|
<< "\t\tint n = (int)floor((real_t)(0.5) * uy / " << sc << ");\n"
|
|
<< "\n"
|
|
<< "\t\tx = ux - (m * 2 + 1) * " << sc << ";\n"
|
|
<< "\t\ty = uy - (n * 2 + 1) * " << sc << ";\n"
|
|
<< "\t\tu = Hypot(x, y);\n"
|
|
<< "\n"
|
|
<< "\t\tif ((CircleTrans1DiscreteNoise2((int)(m + " << seed << "), n) > " << dens << ") || (u > fma(CircleTrans1DiscreteNoise2(m + 10, n + 3), (real_t)(0.7), (real_t)(0.3)) * " << sc << "))\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t ux = ux;\n"
|
|
<< "\t\t uy = uy;\n"
|
|
<< "\t\t}\n"
|
|
<< "\t\telse\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t CircleTrans1CircleR(" << x << ", " << y << ", " << sc << ", " << seed << ", " << dens << ", &ux, &uy, mwc);\n"
|
|
<< "\t\t}\n"
|
|
<< "\n"
|
|
<< "\t\tvOut.x = " << weight << " * ux;\n"
|
|
<< "\t\tvOut.y = " << weight << " * uy;\n"
|
|
<< "\t\tvOut.z = " << DefaultZCl()
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual string OpenCLFuncsString() const override
|
|
{
|
|
return
|
|
"real_t CircleTrans1DiscreteNoise2(int x, int y)\n"
|
|
"{\n"
|
|
" const real_t im = 2147483647;\n"
|
|
" const real_t am = 1 / im;\n"
|
|
"\n"
|
|
" int n = x + y * 57;\n"
|
|
" n = (n << 13) ^ n;\n"
|
|
" return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) * am;\n"
|
|
"}\n"
|
|
"\n"
|
|
"void CircleTrans1Trans(real_t a, real_t b, real_t x, real_t y, real_t* x1, real_t* y1)\n"
|
|
"{\n"
|
|
" *x1 = fma((x - a), (real_t)(0.5), a);\n"
|
|
" *y1 = fma((y - b), (real_t)(0.5), b);\n"
|
|
"}\n"
|
|
"\n"
|
|
"void CircleTrans1CircleR(real_t mx, real_t my, real_t sc, real_t seed, real_t dens, real_t* ux, real_t* vy, uint2* mwc)\n"
|
|
"{\n"
|
|
" int m, n, iters = 0;\n"
|
|
" real_t x, y, alpha, u;\n"
|
|
"\n"
|
|
" do\n"
|
|
" {\n"
|
|
" x = fabs(mx) * (1 - 2 * MwcNext01(mwc));\n"
|
|
" y = fabs(my) * (1 - 2 * MwcNext01(mwc));\n"
|
|
" m = (int)floor((real_t)(0.5) * x / sc);\n"
|
|
" n = (int)floor((real_t)(0.5) * y / sc);\n"
|
|
" alpha = M_2PI * MwcNext01(mwc);\n"
|
|
" u = fma(CircleTrans1DiscreteNoise2(m + 10, n + 3), (real_t)(0.7), (real_t)(0.3));\n"
|
|
" x = u * cos(alpha);\n"
|
|
" y = u * sin(alpha);\n"
|
|
"\n"
|
|
" if (++iters > 10)\n"
|
|
" break;\n"
|
|
" }\n"
|
|
" while (CircleTrans1DiscreteNoise2((int)(m + seed), n) > dens);\n"
|
|
"\n"
|
|
" *ux = fma((real_t)(m * 2 + 1), sc, x);\n"
|
|
" *vy = fma((real_t)(n * 2 + 1), sc, y);\n"
|
|
"}\n"
|
|
"\n";
|
|
}
|
|
|
|
virtual vector<string> OpenCLGlobalFuncNames() const override
|
|
{
|
|
return vector<string> { "Hypot" };
|
|
}
|
|
|
|
virtual void Precalc() override
|
|
{
|
|
m_Sc = Zeps(m_Sc);
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(&m_Sc, prefix + "CircleTrans1_Sc", 1, eParamType::REAL_NONZERO));
|
|
m_Params.push_back(ParamWithName<T>(&m_Dens, prefix + "CircleTrans1_Dens", T(0.5)));
|
|
m_Params.push_back(ParamWithName<T>(&m_X, prefix + "CircleTrans1_X", 10));
|
|
m_Params.push_back(ParamWithName<T>(&m_Y, prefix + "CircleTrans1_Y", 10));
|
|
m_Params.push_back(ParamWithName<T>(&m_Seed, prefix + "CircleTrans1_Seed", 0, eParamType::INTEGER));
|
|
}
|
|
|
|
private:
|
|
T DiscreteNoise2(int x, int y)
|
|
{
|
|
const T im = T(2147483647);
|
|
const T am = (1 / im);
|
|
int n = x + y * 57;
|
|
n = (n << 13) ^ n;
|
|
return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) * am;
|
|
}
|
|
|
|
void Trans(T a, T b, T x, T y, T* x1, T* y1)
|
|
{
|
|
*x1 = (x - a) * T(0.5) + a;
|
|
*y1 = (y - b) * T(0.5) + b;
|
|
}
|
|
|
|
void CircleR(T* ux, T* vy, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand)
|
|
{
|
|
intmax_t m, n, iters = 0;
|
|
T x, y, alpha, u;
|
|
|
|
do
|
|
{
|
|
x = std::abs(m_X) * (1 - 2 * rand.Frand01<T>());
|
|
y = std::abs(m_Y) * (1 - 2 * rand.Frand01<T>());
|
|
m = Floor<T>(T(0.5) * x / m_Sc);
|
|
n = Floor<T>(T(0.5) * y / m_Sc);
|
|
alpha = M_2PI * rand.Frand01<T>();
|
|
u = T(0.3) + T(0.7) * DiscreteNoise2(int(m + 10), int(n + 3));
|
|
x = u * std::cos(alpha);
|
|
y = u * std::sin(alpha);
|
|
|
|
if (++iters > 10)
|
|
break;
|
|
}
|
|
while (DiscreteNoise2(int(m + m_Seed), int(n)) > m_Dens);
|
|
|
|
*ux = x + (m * 2 + 1) * m_Sc;
|
|
*vy = y + (n * 2 + 1) * m_Sc;
|
|
}
|
|
|
|
T m_Sc;
|
|
T m_Dens;
|
|
T m_X;
|
|
T m_Y;
|
|
T m_Seed;
|
|
};
|
|
|
|
/// <summary>
|
|
/// cubic3D.
|
|
/// </summary>
|
|
template <typename T>
|
|
class Cubic3DVariation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
Cubic3DVariation(T weight = 1.0) : ParametricVariation<T>("cubic3D", eVariationId::VAR_CUBIC3D, weight)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(Cubic3DVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
int useNode = rand.Rand() & 7;//Faster than % 8.
|
|
T exnze, wynze, znxy;
|
|
T px, py, pz;
|
|
exnze = 1 - (m_SmoothStyle * (1 - (std::cos(std::atan2(helper.In.x, helper.In.z)))));
|
|
wynze = 1 - (m_SmoothStyle * (1 - (std::sin(std::atan2(helper.In.y, helper.In.z)))));
|
|
|
|
if (m_SmoothStyle > 1)
|
|
znxy = 1 - (m_SmoothStyle * (1 - ((exnze + wynze) / 2 * m_SmoothStyle)));
|
|
else
|
|
znxy = 1 - (m_SmoothStyle * (1 - ((exnze + wynze) * T(0.5))));
|
|
|
|
if (m_VarType == eVariationType::VARTYPE_PRE)
|
|
{
|
|
px = helper.In.x;
|
|
py = helper.In.y;
|
|
pz = helper.In.z;
|
|
}
|
|
else
|
|
{
|
|
px = outPoint.m_X;
|
|
py = outPoint.m_Y;
|
|
pz = outPoint.m_Z;
|
|
}
|
|
|
|
T val1 = (px - (m_Smooth1mFill * px * exnze)) + (helper.In.x * m_SmoothFill * exnze);
|
|
T val2 = (py - (m_Smooth1mFill * py * wynze)) + (helper.In.y * m_SmoothFill * wynze);
|
|
T val3 = (pz - (m_Smooth1mFill * pz * znxy)) + (helper.In.z * m_SmoothFill * znxy);
|
|
|
|
switch (useNode)
|
|
{
|
|
case 0:
|
|
helper.Out.x = val1 + m_HalfWeight;
|
|
helper.Out.y = val2 + m_HalfWeight;
|
|
helper.Out.z = val3 + m_HalfWeight;
|
|
break;
|
|
|
|
case 1:
|
|
helper.Out.x = val1 + m_HalfWeight;
|
|
helper.Out.y = val2 - m_HalfWeight;
|
|
helper.Out.z = val3 + m_HalfWeight;
|
|
break;
|
|
|
|
case 2:
|
|
helper.Out.x = val1 + m_HalfWeight;
|
|
helper.Out.y = val2 + m_HalfWeight;
|
|
helper.Out.z = val3 - m_HalfWeight;
|
|
break;
|
|
|
|
case 3:
|
|
helper.Out.x = val1 + m_HalfWeight;
|
|
helper.Out.y = val2 - m_HalfWeight;
|
|
helper.Out.z = val3 - m_HalfWeight;
|
|
break;
|
|
|
|
case 4:
|
|
helper.Out.x = val1 - m_HalfWeight;
|
|
helper.Out.y = val2 + m_HalfWeight;
|
|
helper.Out.z = val3 + m_HalfWeight;
|
|
break;
|
|
|
|
case 5:
|
|
helper.Out.x = val1 - m_HalfWeight;
|
|
helper.Out.y = val2 - m_HalfWeight;
|
|
helper.Out.z = val3 + m_HalfWeight;
|
|
break;
|
|
|
|
case 6:
|
|
helper.Out.x = val1 - m_HalfWeight;
|
|
helper.Out.y = val2 + m_HalfWeight;
|
|
helper.Out.z = val3 - m_HalfWeight;
|
|
break;
|
|
|
|
case 7:
|
|
default:
|
|
helper.Out.x = val1 - m_HalfWeight;
|
|
helper.Out.y = val2 - m_HalfWeight;
|
|
helper.Out.z = val3 - m_HalfWeight;
|
|
break;
|
|
}
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
intmax_t i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string index = ss2.str();
|
|
string weight = WeightDefineString();
|
|
string xpand = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string style = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string fill = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string smooth = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string smoothStyle = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string smoothfill = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string smooth1mfill = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string halfweight = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\tint useNode = MwcNext(mwc) & 7;\n"
|
|
<< "\t\treal_t exnze, wynze, znxy;\n"
|
|
<< "\t\treal_t px, py, pz;\n"
|
|
<< "\n"
|
|
<< "\t\texnze = 1 - (" << smoothStyle << " * (1 - (cos(atan2(vIn.x, vIn.z)))));\n"
|
|
<< "\t\twynze = 1 - (" << smoothStyle << " * (1 - (sin(atan2(vIn.y, vIn.z)))));\n"
|
|
<< "\n"
|
|
<< "\t\tif (" << smoothStyle << " > 1)\n"
|
|
<< "\t\t znxy = 1 - (" << smoothStyle << " * (1 - ((exnze + wynze) / 2 * " << smoothStyle << ")));\n"
|
|
<< "\t\telse\n"
|
|
<< "\t\t znxy = 1 - (" << smoothStyle << " * (1 - ((exnze + wynze) * (real_t)(0.5))));\n\n";
|
|
|
|
if (m_VarType == eVariationType::VARTYPE_PRE)
|
|
{
|
|
ss <<
|
|
"\t\tpx = vIn.x;\n"
|
|
"\t\tpy = vIn.y;\n"
|
|
"\t\tpz = vIn.z;\n\n";
|
|
}
|
|
else
|
|
{
|
|
ss <<
|
|
"\t\tpx = outPoint->m_X;\n"
|
|
"\t\tpy = outPoint->m_Y;\n"
|
|
"\t\tpz = outPoint->m_Z;\n\n";
|
|
}
|
|
|
|
ss <<
|
|
"\t\treal_t val1 = (px - (" << smooth1mfill << " * px * exnze)) + (vIn.x * " << smoothfill << " * exnze);\n"
|
|
"\t\treal_t val2 = (py - (" << smooth1mfill << " * py * wynze)) + (vIn.y * " << smoothfill << " * wynze);\n"
|
|
"\t\treal_t val3 = (pz - (" << smooth1mfill << " * pz * znxy)) + (vIn.z * " << smoothfill << " * znxy);\n"
|
|
"\n"
|
|
"\t\tswitch (useNode)\n"
|
|
"\t\t{\n"
|
|
"\t\t case 0:\n"
|
|
"\t\t vOut.x = val1 + " << halfweight << ";\n"
|
|
"\t\t vOut.y = val2 + " << halfweight << ";\n"
|
|
"\t\t vOut.z = val3 + " << halfweight << ";\n"
|
|
"\t\t break;\n"
|
|
"\t\t case 1:\n"
|
|
"\t\t vOut.x = val1 + " << halfweight << ";\n"
|
|
"\t\t vOut.y = val2 - " << halfweight << ";\n"
|
|
"\t\t vOut.z = val3 + " << halfweight << ";\n"
|
|
"\t\t break;\n"
|
|
"\t\t case 2:\n"
|
|
"\t\t vOut.x = val1 + " << halfweight << ";\n"
|
|
"\t\t vOut.y = val2 + " << halfweight << ";\n"
|
|
"\t\t vOut.z = val3 - " << halfweight << ";\n"
|
|
"\t\t break;\n"
|
|
"\t\t case 3:\n"
|
|
"\t\t vOut.x = val1 + " << halfweight << ";\n"
|
|
"\t\t vOut.y = val2 - " << halfweight << ";\n"
|
|
"\t\t vOut.z = val3 - " << halfweight << ";\n"
|
|
"\t\t break;\n"
|
|
"\t\t case 4:\n"
|
|
"\t\t vOut.x = val1 - " << halfweight << ";\n"
|
|
"\t\t vOut.y = val2 + " << halfweight << ";\n"
|
|
"\t\t vOut.z = val3 + " << halfweight << ";\n"
|
|
"\t\t break;\n"
|
|
"\t\t case 5:\n"
|
|
"\t\t vOut.x = val1 - " << halfweight << ";\n"
|
|
"\t\t vOut.y = val2 - " << halfweight << ";\n"
|
|
"\t\t vOut.z = val3 + " << halfweight << ";\n"
|
|
"\t\t break;\n"
|
|
"\t\t case 6:\n"
|
|
"\t\t vOut.x = val1 - " << halfweight << ";\n"
|
|
"\t\t vOut.y = val2 + " << halfweight << ";\n"
|
|
"\t\t vOut.z = val3 - " << halfweight << ";\n"
|
|
"\t\t break;\n"
|
|
"\t\t case 7:\n"
|
|
"\t\t default:\n"
|
|
"\t\t vOut.x = val1 - " << halfweight << ";\n"
|
|
"\t\t vOut.y = val2 - " << halfweight << ";\n"
|
|
"\t\t vOut.z = val3 - " << halfweight << ";\n"
|
|
"\t\t break;\n"
|
|
"\t\t}\n"
|
|
"\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual void Precalc() override
|
|
{
|
|
if (std::abs(m_Xpand) <= 1)
|
|
m_Fill = m_Xpand * T(0.5);
|
|
else
|
|
m_Fill = std::sqrt(m_Xpand) * T(0.5);
|
|
|
|
if (std::abs(m_Weight) <= T(0.5))
|
|
m_Smooth = m_Weight * 2;//Causes full effect above m_Weight = 0.5.
|
|
else
|
|
m_Smooth = 1;
|
|
|
|
if (std::abs(m_Style) <= 1)
|
|
{
|
|
m_SmoothStyle = m_Style;
|
|
}
|
|
else
|
|
{
|
|
if (m_Style > 1)
|
|
m_SmoothStyle = 1 + (m_Style - 1) * T(0.25);
|
|
else
|
|
m_SmoothStyle = (m_Style + 1) * T(0.25) - 1;
|
|
}
|
|
|
|
m_SmoothFill = m_Smooth * m_Fill;
|
|
m_Smooth1mFill = m_Smooth * (1 - m_Fill);
|
|
m_HalfWeight = m_Weight * T(0.5);
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(&m_Xpand, prefix + "cubic3D_xpand", T(0.25)));
|
|
m_Params.push_back(ParamWithName<T>(&m_Style, prefix + "cubic3D_style"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Fill, prefix + "cubic3D_fill"));//Precalc.
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Smooth, prefix + "cubic3D_smooth"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_SmoothStyle, prefix + "cubic3D_smooth_style"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_SmoothFill, prefix + "cubic3D_smooth_fill"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Smooth1mFill, prefix + "cubic3D_smooth_1m_fill"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_HalfWeight, prefix + "cubic3D_half_weight"));
|
|
}
|
|
|
|
private:
|
|
T m_Xpand;
|
|
T m_Style;
|
|
T m_Fill;//Precalc.
|
|
T m_Smooth;
|
|
T m_SmoothStyle;
|
|
T m_SmoothFill;
|
|
T m_Smooth1mFill;
|
|
T m_HalfWeight;
|
|
};
|
|
|
|
/// <summary>
|
|
/// cubicLattice_3D.
|
|
/// </summary>
|
|
template <typename T>
|
|
class CubicLattice3DVariation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
CubicLattice3DVariation(T weight = 1.0) : ParametricVariation<T>("cubicLattice_3D", eVariationId::VAR_CUBIC_LATTICE3D, weight)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(CubicLattice3DVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
int useNode = rand.Rand() & 7;//Faster than % 8.
|
|
T exnze, wynze, znxy, px, py, pz;
|
|
|
|
if (m_Style == 2)
|
|
{
|
|
exnze = std::cos(std::atan2(helper.In.x, helper.In.z));
|
|
wynze = std::sin(std::atan2(helper.In.y, helper.In.z));
|
|
znxy = (exnze + wynze) * T(0.5);
|
|
}
|
|
else
|
|
{
|
|
exnze = 1;
|
|
wynze = 1;
|
|
znxy = 1;
|
|
}
|
|
|
|
if (m_VarType == eVariationType::VARTYPE_PRE)
|
|
{
|
|
px = helper.In.x;
|
|
py = helper.In.y;
|
|
pz = helper.In.z;
|
|
}
|
|
else
|
|
{
|
|
px = outPoint.m_X;
|
|
py = outPoint.m_Y;
|
|
pz = outPoint.m_Z;
|
|
}
|
|
|
|
T pxtx = (px + helper.In.x) * m_Fill * exnze;
|
|
T pyty = (py + helper.In.y) * m_Fill * wynze;
|
|
T pztz = (pz + helper.In.z) * m_Fill * znxy;
|
|
|
|
switch (useNode)
|
|
{
|
|
case 0:
|
|
helper.Out.x = pxtx + m_Weight;
|
|
helper.Out.y = pyty + m_Weight;
|
|
helper.Out.z = pztz + m_Weight;
|
|
break;
|
|
|
|
case 1:
|
|
helper.Out.x = pxtx + m_Weight;
|
|
helper.Out.y = pyty - m_Weight;
|
|
helper.Out.z = pztz + m_Weight;
|
|
break;
|
|
|
|
case 2:
|
|
helper.Out.x = pxtx + m_Weight;
|
|
helper.Out.y = pyty + m_Weight;
|
|
helper.Out.z = pztz - m_Weight;
|
|
break;
|
|
|
|
case 3:
|
|
helper.Out.x = pxtx + m_Weight;
|
|
helper.Out.y = pyty - m_Weight;
|
|
helper.Out.z = pztz - m_Weight;
|
|
break;
|
|
|
|
case 4:
|
|
helper.Out.x = pxtx - m_Weight;
|
|
helper.Out.y = pyty + m_Weight;
|
|
helper.Out.z = pztz + m_Weight;
|
|
break;
|
|
|
|
case 5:
|
|
helper.Out.x = pxtx - m_Weight;
|
|
helper.Out.y = pyty - m_Weight;
|
|
helper.Out.z = pztz + m_Weight;
|
|
break;
|
|
|
|
case 6:
|
|
helper.Out.x = pxtx - m_Weight;
|
|
helper.Out.y = pyty + m_Weight;
|
|
helper.Out.z = pztz - m_Weight;
|
|
break;
|
|
|
|
case 7:
|
|
default:
|
|
helper.Out.x = pxtx - m_Weight;
|
|
helper.Out.y = pyty - m_Weight;
|
|
helper.Out.z = pztz - m_Weight;
|
|
break;
|
|
}
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
intmax_t i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string index = ss2.str();
|
|
string weight = WeightDefineString();
|
|
string xpand = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string style = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string fill = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\tint useNode = MwcNext(mwc) & 7;\n"
|
|
<< "\t\treal_t exnze, wynze, znxy, px, py, pz;\n"
|
|
<< "\n"
|
|
<< "\t\tif (" << style << " == 2)\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t exnze = cos(atan2(vIn.x, vIn.z));\n"
|
|
<< "\t\t wynze = sin(atan2(vIn.y, vIn.z));\n"
|
|
<< "\t\t znxy = (exnze + wynze) * (real_t)(0.5);\n"
|
|
<< "\t\t}\n"
|
|
<< "\t\telse\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t exnze = 1;\n"
|
|
<< "\t\t wynze = 1;\n"
|
|
<< "\t\t znxy = 1;\n"
|
|
<< "\t\t}\n";
|
|
|
|
if (m_VarType == eVariationType::VARTYPE_PRE)
|
|
{
|
|
ss <<
|
|
"\t\tpx = vIn.x;\n"
|
|
"\t\tpy = vIn.y;\n"
|
|
"\t\tpz = vIn.z;\n";
|
|
}
|
|
else
|
|
{
|
|
ss <<
|
|
"\t\tpx = outPoint->m_X;\n"
|
|
"\t\tpy = outPoint->m_Y;\n"
|
|
"\t\tpz = outPoint->m_Z;\n";
|
|
}
|
|
|
|
ss << "\t\treal_t pxtx = (px + vIn.x) * " << fill << " * exnze;\n"
|
|
<< "\t\treal_t pyty = (py + vIn.y) * " << fill << " * wynze;\n"
|
|
<< "\t\treal_t pztz = (pz + vIn.z) * " << fill << " * znxy ;\n"
|
|
<< "\n"
|
|
<< "\t\tswitch (useNode)\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t case 0:\n"
|
|
<< "\t\t vOut.x = pxtx + " << weight << ";\n"
|
|
<< "\t\t vOut.y = pyty + " << weight << ";\n"
|
|
<< "\t\t vOut.z = pztz + " << weight << ";\n"
|
|
<< "\t\t break;\n"
|
|
<< "\t\t case 1:\n"
|
|
<< "\t\t vOut.x = pxtx + " << weight << ";\n"
|
|
<< "\t\t vOut.y = pyty - " << weight << ";\n"
|
|
<< "\t\t vOut.z = pztz + " << weight << ";\n"
|
|
<< "\t\t break;\n"
|
|
<< "\t\t case 2:\n"
|
|
<< "\t\t vOut.x = pxtx + " << weight << ";\n"
|
|
<< "\t\t vOut.y = pyty + " << weight << ";\n"
|
|
<< "\t\t vOut.z = pztz - " << weight << ";\n"
|
|
<< "\t\t break;\n"
|
|
<< "\t\t case 3:\n"
|
|
<< "\t\t vOut.x = pxtx + " << weight << ";\n"
|
|
<< "\t\t vOut.y = pyty - " << weight << ";\n"
|
|
<< "\t\t vOut.z = pztz - " << weight << ";\n"
|
|
<< "\t\t break;\n"
|
|
<< "\t\t case 4:\n"
|
|
<< "\t\t vOut.x = pxtx - " << weight << ";\n"
|
|
<< "\t\t vOut.y = pyty + " << weight << ";\n"
|
|
<< "\t\t vOut.z = pztz + " << weight << ";\n"
|
|
<< "\t\t break;\n"
|
|
<< "\t\t case 5:\n"
|
|
<< "\t\t vOut.x = pxtx - " << weight << ";\n"
|
|
<< "\t\t vOut.y = pyty - " << weight << ";\n"
|
|
<< "\t\t vOut.z = pztz + " << weight << ";\n"
|
|
<< "\t\t break;\n"
|
|
<< "\t\t case 6:\n"
|
|
<< "\t\t vOut.x = pxtx - " << weight << ";\n"
|
|
<< "\t\t vOut.y = pyty + " << weight << ";\n"
|
|
<< "\t\t vOut.z = pztz - " << weight << ";\n"
|
|
<< "\t\t break;\n"
|
|
<< "\t\t case 7:\n"
|
|
<< "\t\t default:\n"
|
|
<< "\t\t vOut.x = pxtx - " << weight << ";\n"
|
|
<< "\t\t vOut.y = pyty - " << weight << ";\n"
|
|
<< "\t\t vOut.z = pztz - " << weight << ";\n"
|
|
<< "\t\t break;\n"
|
|
<< "\t\t}\n"
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual void Precalc() override
|
|
{
|
|
if (std::abs(m_Xpand) <= 1)
|
|
m_Fill = m_Xpand * T(0.5);
|
|
else
|
|
m_Fill = std::sqrt(m_Xpand) * T(0.5);
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(&m_Xpand, prefix + "cubicLattice_3D_xpand", T(0.2)));//Original used a prefix of cubic3D_, which is incompatible with Ember's design.
|
|
m_Params.push_back(ParamWithName<T>(&m_Style, prefix + "cubicLattice_3D_style", 1, eParamType::INTEGER, 1, 2));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Fill, prefix + "cubicLattice_3D_fill"));//Precalc.
|
|
}
|
|
|
|
private:
|
|
T m_Xpand;
|
|
T m_Style;
|
|
T m_Fill;//Precalc.
|
|
};
|
|
|
|
/// <summary>
|
|
/// foci_3D.
|
|
/// </summary>
|
|
template <typename T>
|
|
class Foci3DVariation : public Variation<T>
|
|
{
|
|
public:
|
|
Foci3DVariation(T weight = 1.0) : Variation<T>("foci_3D", eVariationId::VAR_FOCI3D, weight, false, false, false, false, true) { }
|
|
|
|
VARCOPY(Foci3DVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
T expx = std::exp(helper.In.x) * T(0.5);
|
|
T expnx = T(0.25) / Zeps(expx);
|
|
T boot = helper.In.z == 0 ? helper.m_PrecalcAtanyx : helper.In.z;
|
|
T tmp = m_Weight / Zeps(expx + expnx - (std::cos(helper.In.y) * std::cos(boot)));
|
|
helper.Out.x = (expx - expnx) * tmp;
|
|
helper.Out.y = std::sin(helper.In.y) * tmp;
|
|
helper.Out.z = std::sin(boot) * tmp;
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss;
|
|
string weight = WeightDefineString();
|
|
ss << "\t{\n"
|
|
<< "\t\treal_t expx = exp(vIn.x) * (real_t)(0.5);\n"
|
|
<< "\t\treal_t expnx = (real_t)(0.25) / Zeps(expx);\n"
|
|
<< "\t\treal_t boot = vIn.z == 0 ? precalcAtanyx : vIn.z;\n"
|
|
<< "\t\treal_t tmp = " << weight << " / Zeps(expx + expnx - (cos(vIn.y) * cos(boot)));\n"
|
|
<< "\n"
|
|
<< "\t\tvOut.x = (expx - expnx) * tmp;\n"
|
|
<< "\t\tvOut.y = sin(vIn.y) * tmp;\n"
|
|
<< "\t\tvOut.z = sin(boot) * tmp;\n"
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual vector<string> OpenCLGlobalFuncNames() const override
|
|
{
|
|
return vector<string> { "Zeps" };
|
|
}
|
|
};
|
|
|
|
/// <summary>
|
|
/// foci_p.
|
|
/// Idea by Chaosfissure.
|
|
/// </summary>
|
|
template <typename T>
|
|
class FociPVariation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
FociPVariation(T weight = 1.0) : ParametricVariation<T>("foci_p", eVariationId::VAR_FOCI_P, weight)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(FociPVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
T exp_x = Zeps(std::exp(helper.In.x));
|
|
T exp_x_2 = exp_x * m_C1;
|
|
T exp_nz = m_C2 / exp_x;
|
|
T cos_y = std::cos(helper.In.y);
|
|
T sin_y = std::sin(helper.In.y);
|
|
T r = m_Weight / Zeps(exp_x_2 + exp_nz - cos_y);
|
|
helper.Out.x = (exp_x_2 - exp_nz) * r;
|
|
helper.Out.y = sin_y * r;
|
|
helper.Out.z = DefaultZ(helper);
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
intmax_t i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string index = ss2.str();
|
|
string weight = WeightDefineString();
|
|
string c1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string c2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\treal_t exp_x = Zeps(exp(vIn.x));\n"
|
|
<< "\t\treal_t exp_x_2 = exp_x * " << c1 << ";\n"
|
|
<< "\t\treal_t exp_nz = " << c2 << " / exp_x;\n"
|
|
<< "\t\treal_t cos_y = cos(vIn.y);\n"
|
|
<< "\t\treal_t sin_y = sin(vIn.y);\n"
|
|
<< "\t\treal_t r = " << weight << " / Zeps(exp_x_2 + exp_nz - cos_y);\n"
|
|
<< "\n"
|
|
<< "\t\tvOut.x = (exp_x_2 - exp_nz) * r;\n"
|
|
<< "\t\tvOut.y = sin_y * r;\n"
|
|
<< "\t\tvOut.z = " << DefaultZCl()
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual vector<string> OpenCLGlobalFuncNames() const override
|
|
{
|
|
return vector<string> { "Zeps" };
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(&m_C1, prefix + "foci_p_c1", T(0.5)));
|
|
m_Params.push_back(ParamWithName<T>(&m_C2, prefix + "foci_p_c2", T(0.5)));
|
|
}
|
|
|
|
private:
|
|
T m_C1;
|
|
T m_C2;
|
|
};
|
|
|
|
/// <summary>
|
|
/// ho.
|
|
/// </summary>
|
|
template <typename T>
|
|
class HoVariation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
HoVariation(T weight = 1.0) : ParametricVariation<T>("ho", eVariationId::VAR_HO, weight)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(HoVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
T uu = SQR(helper.In.x);
|
|
T vv = SQR(helper.In.y);
|
|
T ww = SQR(helper.In.z);
|
|
T atOmegaX = std::atan2(vv, ww);
|
|
T atOmegaY = std::atan2(uu, ww);
|
|
T su = std::sin(helper.In.x);
|
|
T cu = std::cos(helper.In.x);
|
|
T sv = std::sin(helper.In.y);
|
|
T cv = std::cos(helper.In.y);
|
|
T cucv = cu * cv;
|
|
T sucv = su * cv;
|
|
T x = std::pow(std::abs(cucv), m_XPow) + (cucv * m_XPow) + (T(0.25) * atOmegaX);//Must fabs first argument to pow, because negative values will return NaN.
|
|
T y = std::pow(std::abs(sucv), m_YPow) + (sucv * m_YPow) + (T(0.25) * atOmegaY);//Original did not do this and would frequently return bad values.
|
|
T z = std::pow(std::abs(sv), m_ZPow) + sv * m_ZPow;
|
|
helper.Out.x = m_Weight * x;
|
|
helper.Out.y = m_Weight * y;
|
|
helper.Out.z = m_Weight * z;
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
intmax_t i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string index = ss2.str();
|
|
string weight = WeightDefineString();
|
|
string xpow = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string ypow = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string zpow = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\treal_t uu = SQR(vIn.x);\n"
|
|
<< "\t\treal_t vv = SQR(vIn.y);\n"
|
|
<< "\t\treal_t ww = SQR(vIn.z);\n"
|
|
<< "\t\treal_t atOmegaX = atan2(vv, ww);\n"
|
|
<< "\t\treal_t atOmegaY = atan2(uu, ww);\n"
|
|
<< "\t\treal_t su = sin(vIn.x);\n"
|
|
<< "\t\treal_t cu = cos(vIn.x);\n"
|
|
<< "\t\treal_t sv = sin(vIn.y);\n"
|
|
<< "\t\treal_t cv = cos(vIn.y);\n"
|
|
<< "\t\treal_t cucv = cu * cv;\n"
|
|
<< "\t\treal_t sucv = su * cv;\n"
|
|
<< "\t\treal_t x = pow(fabs(cucv), " << xpow << ") + fma(cucv, " << xpow << ", (real_t)(0.25) * atOmegaX);\n"
|
|
<< "\t\treal_t y = pow(fabs(sucv), " << ypow << ") + fma(sucv, " << ypow << ", (real_t)(0.25) * atOmegaY);\n"
|
|
<< "\t\treal_t z = fma(sv, " << zpow << ", pow(fabs(sv), " << zpow << "));\n"
|
|
<< "\n"
|
|
<< "\t\tvOut.x = " << weight << " * x;\n"
|
|
<< "\t\tvOut.y = " << weight << " * y;\n"
|
|
<< "\t\tvOut.z = " << weight << " * z;\n"
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(&m_XPow, prefix + "ho_xpow", 3));
|
|
m_Params.push_back(ParamWithName<T>(&m_YPow, prefix + "ho_ypow", 3));
|
|
m_Params.push_back(ParamWithName<T>(&m_ZPow, prefix + "ho_zpow", 3));
|
|
}
|
|
|
|
private:
|
|
T m_XPow;
|
|
T m_YPow;
|
|
T m_ZPow;
|
|
};
|
|
|
|
/// <summary>
|
|
/// Julia3Dq.
|
|
/// </summary>
|
|
template <typename T>
|
|
class Julia3DqVariation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
Julia3DqVariation(T weight = 1.0) : ParametricVariation<T>("julia3Dq", eVariationId::VAR_JULIA3DQ, weight, true, true, false, false, true)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(Julia3DqVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
T temp = helper.m_PrecalcAtanyx * m_InvPower + rand.Crand() * m_InvPower2pi;
|
|
T sina = std::sin(temp);
|
|
T cosa = std::cos(temp);
|
|
T z = helper.In.z * m_AbsInvPower;
|
|
T r2d = helper.m_PrecalcSumSquares;
|
|
T r = m_Weight * std::pow(r2d + SQR(z), m_HalfInvPower);
|
|
T rsss = r * helper.m_PrecalcSqrtSumSquares;
|
|
helper.Out.x = rsss * cosa;
|
|
helper.Out.y = rsss * sina;
|
|
helper.Out.z = r * z;
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
intmax_t i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string index = ss2.str();
|
|
string weight = WeightDefineString();
|
|
string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string divisor = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string invPower = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string absInvPower = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string halfInvPower = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string invPower2pi = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\treal_t temp = fma(precalcAtanyx, " << invPower << ", MwcNextCrand(mwc) * " << invPower2pi << ");\n"
|
|
<< "\t\treal_t sina = sin(temp);\n"
|
|
<< "\t\treal_t cosa = cos(temp);\n"
|
|
<< "\t\treal_t z = vIn.z * " << absInvPower << ";\n"
|
|
<< "\t\treal_t r2d = precalcSumSquares;\n"
|
|
<< "\t\treal_t r = " << weight << " * pow(fma(z, z, r2d), " << halfInvPower << ");\n"
|
|
<< "\t\treal_t rsss = r * precalcSqrtSumSquares;\n"
|
|
<< "\n"
|
|
<< "\t\tvOut.x = rsss * cosa;\n"
|
|
<< "\t\tvOut.y = rsss * sina;\n"
|
|
<< "\t\tvOut.z = r * z;\n"
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual void Precalc() override
|
|
{
|
|
m_InvPower = m_Divisor / m_Power;
|
|
m_AbsInvPower = std::abs(m_InvPower);
|
|
m_HalfInvPower = T(0.5) * m_InvPower - T(0.5);
|
|
m_InvPower2pi = M_2PI / m_Power;
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(&m_Power, prefix + "julia3Dq_power", 3, eParamType::INTEGER_NONZERO));
|
|
m_Params.push_back(ParamWithName<T>(&m_Divisor, prefix + "julia3Dq_divisor", 2, eParamType::INTEGER_NONZERO));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_InvPower, prefix + "julia3Dq_inv_power"));//Precalc.
|
|
m_Params.push_back(ParamWithName<T>(true, &m_AbsInvPower, prefix + "julia3Dq_abs_inv_power"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_HalfInvPower, prefix + "julia3Dq_half_inv_power"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_InvPower2pi, prefix + "julia3Dq_inv_power_2pi"));
|
|
}
|
|
|
|
private:
|
|
T m_Power;
|
|
T m_Divisor;
|
|
T m_InvPower;//Precalc.
|
|
T m_AbsInvPower;
|
|
T m_HalfInvPower;
|
|
T m_InvPower2pi;
|
|
};
|
|
|
|
/// <summary>
|
|
/// line.
|
|
/// </summary>
|
|
template <typename T>
|
|
class LineVariation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
LineVariation(T weight = 1.0) : ParametricVariation<T>("line", eVariationId::VAR_LINE, weight)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(LineVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
T r = rand.Frand01<T>() * m_Weight;
|
|
helper.Out.x = m_Ux * r;
|
|
helper.Out.y = m_Uy * r;
|
|
helper.Out.z = m_Uz * r;
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
intmax_t i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string index = ss2.str();
|
|
string weight = WeightDefineString();
|
|
string delta = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string phi = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string ux = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string uy = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string uz = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\treal_t r = MwcNext01(mwc) * " << weight << ";\n"
|
|
<< "\n"
|
|
<< "\t\tvOut.x = " << ux << " * r;\n"
|
|
<< "\t\tvOut.y = " << uy << " * r;\n"
|
|
<< "\t\tvOut.z = " << uz << " * r;\n"
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual void Precalc() override
|
|
{
|
|
//Unit vector of the line.
|
|
m_Ux = std::cos(m_Delta * T(M_PI)) * std::cos(m_Phi * T(M_PI));
|
|
m_Uy = std::sin(m_Delta * T(M_PI)) * std::cos(m_Phi * T(M_PI));
|
|
m_Uz = std::sin(m_Phi * T(M_PI));
|
|
T r = std::sqrt(SQR(m_Ux) + SQR(m_Uy) + SQR(m_Uz));
|
|
//Normalize.
|
|
m_Ux /= r;
|
|
m_Uy /= r;
|
|
m_Uz /= r;
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(&m_Delta, prefix + "line_delta"));
|
|
m_Params.push_back(ParamWithName<T>(&m_Phi, prefix + "line_phi"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Ux, prefix + "line_ux"));//Precalc.
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Uy, prefix + "line_uy"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Uz, prefix + "line_uz"));
|
|
}
|
|
|
|
private:
|
|
T m_Delta;
|
|
T m_Phi;
|
|
T m_Ux;//Precalc.
|
|
T m_Uy;
|
|
T m_Uz;
|
|
};
|
|
|
|
/// <summary>
|
|
/// Loonie2.
|
|
/// </summary>
|
|
template <typename T>
|
|
class Loonie2Variation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
Loonie2Variation(T weight = 1.0) : ParametricVariation<T>("loonie2", eVariationId::VAR_LOONIE2, weight, true, true)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(Loonie2Variation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
int i;
|
|
T xrt = helper.In.x, yrt = helper.In.y, swp;
|
|
T r2 = xrt * m_Coss + std::abs(yrt) * m_Sins;
|
|
T circle = helper.m_PrecalcSqrtSumSquares;
|
|
|
|
for (i = 0; i < m_Sides - 1; i++)
|
|
{
|
|
swp = xrt * m_Cosa - yrt * m_Sina;
|
|
yrt = xrt * m_Sina + yrt * m_Cosa;
|
|
xrt = swp;
|
|
r2 = std::max(r2, xrt * m_Coss + std::abs(yrt) * m_Sins);
|
|
}
|
|
|
|
r2 = r2 * m_Cosc + circle * m_Sinc;
|
|
|
|
if (i > 1)
|
|
r2 = SQR(r2);
|
|
else
|
|
r2 = std::abs(r2) * r2;
|
|
|
|
if (r2 > 0 && (r2 < m_W2))
|
|
{
|
|
T r = m_Weight * std::sqrt(std::abs(m_W2 / r2 - 1));
|
|
helper.Out.x = r * helper.In.x;
|
|
helper.Out.y = r * helper.In.y;
|
|
}
|
|
else if (r2 < 0)
|
|
{
|
|
T r = m_Weight / std::sqrt(std::abs(m_W2 / r2) - 1);
|
|
helper.Out.x = r * helper.In.x;
|
|
helper.Out.y = r * helper.In.y;
|
|
}
|
|
else
|
|
{
|
|
helper.Out.x = m_Weight * helper.In.x;
|
|
helper.Out.y = m_Weight * helper.In.y;
|
|
}
|
|
|
|
helper.Out.z = DefaultZ(helper);
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
intmax_t i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string weight = WeightDefineString();
|
|
string index = ss2.str();
|
|
string sides = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string star = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string circle = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string w2 = "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 sins = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string coss = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string sinc = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string cosc = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\tint i;\n"
|
|
<< "\t\treal_t xrt = vIn.x, yrt = vIn.y, swp;\n"
|
|
<< "\t\treal_t r2 = fma(xrt, " << coss << ", fabs(yrt) * " << sins << ");\n"
|
|
<< "\t\treal_t circle = precalcSqrtSumSquares;\n"
|
|
<< "\n"
|
|
<< "\t\tfor (i = 0; i < " << sides << " - 1; i++)\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t swp = fma(xrt, " << cosa << ", -(yrt * " << sina << "));\n"
|
|
<< "\t\t yrt = fma(xrt, " << sina << ", yrt * " << cosa << ");\n"
|
|
<< "\t\t xrt = swp;\n"
|
|
<< "\n"
|
|
<< "\t\t r2 = max(r2, fma(xrt, " << coss << ", fabs(yrt) * " << sins << "));\n"
|
|
<< "\t\t}\n"
|
|
<< "\n"
|
|
<< "\t\tr2 = fma(r2, " << cosc << ", circle * " << sinc << ");\n"
|
|
<< "\n"
|
|
<< "\t\tif (i > 1)\n"
|
|
<< "\t\t r2 = SQR(r2);\n"
|
|
<< "\t\telse\n"
|
|
<< "\t\t r2 = fabs(r2) * r2;\n"
|
|
<< "\n"
|
|
<< "\t\tif (r2 > 0 && (r2 < " << w2 << "))\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t real_t r = " << weight << " * sqrt(fabs(" << w2 << " / r2 - 1));\n"
|
|
<< "\n"
|
|
<< "\t\t vOut.x = r * vIn.x;\n"
|
|
<< "\t\t vOut.y = r * vIn.y;\n"
|
|
<< "\t\t}\n"
|
|
<< "\t\telse if (r2 < 0)\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t real_t r = " << weight << " / sqrt(fabs(" << w2 << " / r2) - 1);\n"
|
|
<< "\n"
|
|
<< "\t\t vOut.x = r * vIn.x;\n"
|
|
<< "\t\t vOut.y = r * vIn.y;\n"
|
|
<< "\t\t}\n"
|
|
<< "\t\telse\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t vOut.x = " << weight << " * vIn.x;\n"
|
|
<< "\t\t vOut.y = " << weight << " * vIn.y;\n"
|
|
<< "\t\t}\n"
|
|
<< "\n"
|
|
<< "\t\tvOut.z = " << DefaultZCl()
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual void Precalc() override
|
|
{
|
|
auto a = M_2PI / m_Sides;
|
|
auto s = T(-M_PI_2) * m_Star;
|
|
auto c = T(M_PI_2) * m_Circle;
|
|
m_W2 = SQR(m_Weight);
|
|
sincos(a, &m_Sina, &m_Cosa);
|
|
sincos(s, &m_Sins, &m_Coss);
|
|
sincos(c, &m_Sinc, &m_Cosc);
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(&m_Sides, prefix + "loonie2_sides", 4, eParamType::INTEGER, 1, 50));
|
|
m_Params.push_back(ParamWithName<T>(&m_Star, prefix + "loonie2_star", 0, eParamType::REAL, -1, 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_Circle, prefix + "loonie2_circle", 0, eParamType::REAL, -1, 1));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_W2, prefix + "loonie2_w2"));//Precalc.
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Sina, prefix + "loonie2_sina"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Cosa, prefix + "loonie2_cosa"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Sins, prefix + "loonie2_sins"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Coss, prefix + "loonie2_coss"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Sinc, prefix + "loonie2_sinc"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Cosc, prefix + "loonie2_cosc"));
|
|
}
|
|
|
|
private:
|
|
T m_Sides;
|
|
T m_Star;
|
|
T m_Circle;
|
|
T m_W2;//Precalc.
|
|
T m_Sina;
|
|
T m_Cosa;
|
|
T m_Sins;
|
|
T m_Coss;
|
|
T m_Sinc;
|
|
T m_Cosc;
|
|
};
|
|
|
|
/// <summary>
|
|
/// Loonie3.
|
|
/// </summary>
|
|
template <typename T>
|
|
class Loonie3Variation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
Loonie3Variation(T weight = 1.0) : ParametricVariation<T>("loonie3", eVariationId::VAR_LOONIE3, weight, true)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(Loonie3Variation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
T r2;
|
|
|
|
if (helper.In.x > EPS)
|
|
r2 = SQR(helper.m_PrecalcSumSquares / helper.In.x);
|
|
else
|
|
r2 = 2 * m_W2;
|
|
|
|
if (r2 < m_W2)
|
|
{
|
|
T r = m_Weight * std::sqrt(m_W2 / r2 - 1);
|
|
helper.Out.x = r * helper.In.x;
|
|
helper.Out.y = r * helper.In.y;
|
|
}
|
|
else
|
|
{
|
|
helper.Out.x = m_Weight * helper.In.x;
|
|
helper.Out.y = m_Weight * helper.In.y;
|
|
}
|
|
|
|
helper.Out.z = DefaultZ(helper);
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
intmax_t i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string index = ss2.str();
|
|
string weight = WeightDefineString();
|
|
string w2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\treal_t r2;\n"
|
|
<< "\n"
|
|
<< "\t\tif (vIn.x > EPS)\n"
|
|
<< "\t\t r2 = SQR(precalcSumSquares / vIn.x);\n"
|
|
<< "\t\telse\n"
|
|
<< "\t\t r2 = 2 * " << w2 << ";\n"
|
|
<< "\n"
|
|
<< "\t\tif (r2 < " << w2 << ")\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t real_t r = " << weight << " * sqrt(" << w2 << " / r2 - 1);\n"
|
|
<< "\n"
|
|
<< "\t\t vOut.x = r * vIn.x;\n"
|
|
<< "\t\t vOut.y = r * vIn.y;\n"
|
|
<< "\t\t}\n"
|
|
<< "\t\telse\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t vOut.x = " << weight << " * vIn.x;\n"
|
|
<< "\t\t vOut.y = " << weight << " * vIn.y;\n"
|
|
<< "\t\t}\n"
|
|
<< "\n"
|
|
<< "\t\tvOut.z = " << DefaultZCl()
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual void Precalc() override
|
|
{
|
|
m_W2 = SQR(m_Weight);
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(true, &m_W2, prefix + "loonie3_w2"));//Precalc.
|
|
}
|
|
|
|
private:
|
|
T m_W2;//Precalc.
|
|
};
|
|
|
|
/// <summary>
|
|
/// loonie_3D.
|
|
/// </summary>
|
|
template <typename T>
|
|
class Loonie3DVariation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
Loonie3DVariation(T weight = 1.0) : ParametricVariation<T>("loonie_3D", eVariationId::VAR_LOONIE3D, weight, true, false, false, false, true)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(Loonie3DVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
T kikr = helper.m_PrecalcAtanyx;
|
|
T efTez = helper.In.z == 0 ? kikr : helper.In.z;
|
|
T r2 = helper.m_PrecalcSumSquares + SQR(efTez);
|
|
|
|
if (r2 < m_Vv)
|
|
{
|
|
T r = m_Weight * std::sqrt(m_Vv / r2 - 1);
|
|
helper.Out.x = r * helper.In.x;
|
|
helper.Out.y = r * helper.In.y;
|
|
helper.Out.z = r * efTez * T(0.5);
|
|
}
|
|
else
|
|
{
|
|
helper.Out.x = m_Weight * helper.In.x;
|
|
helper.Out.y = m_Weight * helper.In.y;
|
|
helper.Out.z = m_Weight * efTez * T(0.5);
|
|
}
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
intmax_t i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string index = ss2.str();
|
|
string weight = WeightDefineString();
|
|
string vv = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\treal_t kikr = precalcAtanyx;\n"
|
|
<< "\t\treal_t efTez = vIn.z == 0 ? kikr : vIn.z;\n"
|
|
<< "\t\treal_t r2 = fma(efTez, efTez, precalcSumSquares);\n"
|
|
<< "\n"
|
|
<< "\t\tif (r2 < " << vv << ")\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t real_t r = " << weight << " * sqrt(" << vv << " / r2 - 1);\n"
|
|
<< "\n"
|
|
<< "\t\t vOut.x = r * vIn.x;\n"
|
|
<< "\t\t vOut.y = r * vIn.y;\n"
|
|
<< "\t\t vOut.z = r * efTez * (real_t)(0.5);\n"
|
|
<< "\t\t}\n"
|
|
<< "\t\telse\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t vOut.x = " << weight << " * vIn.x;\n"
|
|
<< "\t\t vOut.y = " << weight << " * vIn.y;\n"
|
|
<< "\t\t vOut.z = " << weight << " * efTez * (real_t)(0.5);\n"
|
|
<< "\t\t}\n"
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual void Precalc() override
|
|
{
|
|
m_Vv = SQR(m_Weight);
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Vv, prefix + "loonie_3D_vv"));//Precalcs only, no params.
|
|
}
|
|
|
|
private:
|
|
T m_Vv;//Precalcs only, no params.
|
|
};
|
|
|
|
/// <summary>
|
|
/// mcarpet.
|
|
/// </summary>
|
|
template <typename T>
|
|
class McarpetVariation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
McarpetVariation(T weight = 1.0) : ParametricVariation<T>("mcarpet", eVariationId::VAR_MCARPET, weight, true)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(McarpetVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
T t = helper.m_PrecalcSumSquares * T(0.25) + 1;
|
|
T r = m_Weight / t;
|
|
helper.Out.x = helper.In.x * r * m_X;
|
|
helper.Out.y = helper.In.y * r * m_Y;
|
|
helper.Out.x += (1 - (m_Twist * SQR(helper.In.x)) + helper.In.y) * m_Weight;//The += is intentional.
|
|
helper.Out.y += m_Tilt * helper.In.x * m_Weight;
|
|
helper.Out.z = DefaultZ(helper);
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
intmax_t i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string index = ss2.str();
|
|
string weight = WeightDefineString();
|
|
string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string twist = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string tilt = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\treal_t t = fma(precalcSumSquares, (real_t)(0.25), (real_t)(1.0));\n"
|
|
<< "\t\treal_t r = " << weight << " / t;\n"
|
|
<< "\n"
|
|
<< "\t\tvOut.x = vIn.x * r * " << x << ";\n"
|
|
<< "\t\tvOut.y = vIn.y * r * " << y << ";\n"
|
|
<< "\t\tvOut.x += (1 - (" << twist << " * SQR(vIn.x)) + vIn.y) * " << weight << ";\n"
|
|
<< "\t\tvOut.y += " << tilt << " * vIn.x * " << weight << ";\n"
|
|
<< "\t\tvOut.z = " << DefaultZCl()
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(&m_X, prefix + "mcarpet_x"));
|
|
m_Params.push_back(ParamWithName<T>(&m_Y, prefix + "mcarpet_y"));
|
|
m_Params.push_back(ParamWithName<T>(&m_Twist, prefix + "mcarpet_twist"));
|
|
m_Params.push_back(ParamWithName<T>(&m_Tilt, prefix + "mcarpet_tilt"));
|
|
}
|
|
|
|
private:
|
|
T m_X;
|
|
T m_Y;
|
|
T m_Twist;
|
|
T m_Tilt;
|
|
};
|
|
|
|
/// <summary>
|
|
/// waves2_3D.
|
|
/// Original used a precalc for the input points, but it doesn't
|
|
/// work with Ember's design (and is also likely wrong), so it gets calculated on every iter
|
|
/// which is slightly slower, but more correct.
|
|
/// </summary>
|
|
template <typename T>
|
|
class Waves23DVariation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
Waves23DVariation(T weight = 1.0) : ParametricVariation<T>("waves2_3D", eVariationId::VAR_WAVES23D, weight)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(Waves23DVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
T avgxy = (helper.In.x + helper.In.y) * T(0.5);
|
|
helper.Out.x = m_Weight * (helper.In.x + m_Scale * std::sin(helper.In.y * m_Freq));
|
|
helper.Out.y = m_Weight * (helper.In.y + m_Scale * std::sin(helper.In.x * m_Freq));
|
|
helper.Out.z = m_Weight * (helper.In.z + m_Scale * std::sin(avgxy * m_Freq));//Averages the XY to get Z.
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
intmax_t i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string index = ss2.str();
|
|
string weight = WeightDefineString();
|
|
string freq = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\treal_t avgxy = (vIn.x + vIn.y) * (real_t)(0.5);\n"
|
|
<< "\n"
|
|
<< "\t\tvOut.x = " << weight << " * fma(" << scale << ", sin(vIn.y * " << freq << "), vIn.x);\n"
|
|
<< "\t\tvOut.y = " << weight << " * fma(" << scale << ", sin(vIn.x * " << freq << "), vIn.y);\n"
|
|
<< "\t\tvOut.z = " << weight << " * fma(" << scale << ", sin(avgxy * " << freq << "), vIn.z);\n"
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(&m_Freq, prefix + "waves2_3D_freq", 2));
|
|
m_Params.push_back(ParamWithName<T>(&m_Scale, prefix + "waves2_3D_scale", 1));
|
|
}
|
|
|
|
private:
|
|
T m_Freq;
|
|
T m_Scale;
|
|
};
|
|
|
|
/// <summary>
|
|
/// Pie3D.
|
|
/// </summary>
|
|
template <typename T>
|
|
class Pie3DVariation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
Pie3DVariation(T weight = 1.0) : ParametricVariation<T>("pie3D", eVariationId::VAR_PIE3D, weight)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(Pie3DVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
int sl = int(rand.Frand01<T>() * m_Slices + T(0.5));
|
|
T a = m_Rotation + M_2PI * (sl + rand.Frand01<T>() * m_Thickness) / m_Slices;
|
|
T r = m_Weight * rand.Frand01<T>();
|
|
helper.Out.x = r * std::cos(a);
|
|
helper.Out.y = r * std::sin(a);
|
|
helper.Out.z = m_Weight * std::sin(r);
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
intmax_t i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string index = ss2.str();
|
|
string weight = WeightDefineString();
|
|
string slices = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string rotation = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string thickness = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\tint sl = (int)fma(MwcNext01(mwc), " << slices << ", (real_t)(0.5));\n"
|
|
<< "\t\treal_t a = fma(M_2PI, fma(MwcNext01(mwc), " << thickness << ", (real_t)(sl)) / " << slices << ", " << rotation << ");\n"
|
|
<< "\t\treal_t r = " << weight << " * MwcNext01(mwc);\n"
|
|
<< "\n"
|
|
<< "\t\tvOut.x = r * cos(a);\n"
|
|
<< "\t\tvOut.y = r * sin(a);\n"
|
|
<< "\t\tvOut.z = " << weight << " * sin(r);\n"
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual void Random(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
m_Params[0].Set(10 * rand.Frand01<T>());//Slices.
|
|
m_Params[1].Set(M_2PI * rand.Frand11<T>());//Rotation.
|
|
m_Thickness = rand.Frand01<T>();
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(&m_Slices, prefix + "pie3D_slices", 6, eParamType::INTEGER_NONZERO, 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_Rotation, prefix + "pie3D_rotation", T(0.5), eParamType::REAL_CYCLIC, 0, M_2PI));
|
|
m_Params.push_back(ParamWithName<T>(&m_Thickness, prefix + "pie3D_thickness", T(0.5), eParamType::REAL, 0, 1));
|
|
}
|
|
|
|
private:
|
|
T m_Slices;
|
|
T m_Rotation;
|
|
T m_Thickness;
|
|
};
|
|
|
|
/// <summary>
|
|
/// popcorn2_3D.
|
|
/// </summary>
|
|
template <typename T>
|
|
class Popcorn23DVariation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
Popcorn23DVariation(T weight = 1.0) : ParametricVariation<T>("popcorn2_3D", eVariationId::VAR_POPCORN23D, weight, false, false, false, false, true)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(Popcorn23DVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
T otherZ, tempPZ = 0;
|
|
T tempTZ = helper.In.z == 0 ? m_Vv * m_SinTanC * helper.m_PrecalcAtanyx : helper.In.z;
|
|
|
|
if (m_VarType == eVariationType::VARTYPE_PRE)
|
|
otherZ = helper.In.z;
|
|
else
|
|
otherZ = outPoint.m_Z;
|
|
|
|
if (otherZ == 0)
|
|
tempPZ = m_Vv * m_SinTanC * helper.m_PrecalcAtanyx;
|
|
|
|
helper.Out.x = m_HalfWeight * (helper.In.x + m_X * std::sin(SafeTan<T>(m_C * helper.In.y)));
|
|
helper.Out.y = m_HalfWeight * (helper.In.y + m_Y * std::sin(SafeTan<T>(m_C * helper.In.x)));
|
|
helper.Out.z = tempPZ + m_Vv * (m_Z * m_SinTanC * tempTZ);
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
int i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string index = ss2.str();
|
|
string weight = WeightDefineString();
|
|
string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string z = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string c = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string stc = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string hw = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string vv = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\treal_t otherZ, tempPZ = 0;\n"
|
|
<< "\t\treal_t tempTZ = vIn.z == 0 ? " << vv << " * " << stc << " * precalcAtanyx : vIn.z;\n";
|
|
|
|
if (m_VarType == eVariationType::VARTYPE_PRE)
|
|
ss << "\t\totherZ = vIn.z;\n";
|
|
else
|
|
ss << "\t\totherZ = outPoint->m_Z;\n";
|
|
|
|
ss << "\t\tif (otherZ == 0)\n"
|
|
<< "\t\t tempPZ = " << vv << " * " << stc << " * precalcAtanyx;\n"
|
|
<< "\n"
|
|
<< "\t\tvOut.x = " << hw << " * fma(" << x << ", sin(tan(" << c << " * vIn.y)), vIn.x);\n"
|
|
<< "\t\tvOut.y = " << hw << " * fma(" << y << ", sin(tan(" << c << " * vIn.x)), vIn.y);\n"
|
|
<< "\t\tvOut.z = fma(" << vv << ", (" << z << " * " << stc << " * tempTZ), tempPZ);\n"
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual void Precalc() override
|
|
{
|
|
m_SinTanC = std::sin(SafeTan<T>(m_C));
|
|
m_HalfWeight = m_Weight * T(0.5);
|
|
|
|
if (std::abs(m_Weight) <= 1)
|
|
m_Vv = std::abs(m_Weight) * m_Weight;//Sqr(m_Weight) value retaining sign.
|
|
else
|
|
m_Vv = m_Weight;
|
|
}
|
|
|
|
virtual void Random(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
m_X = T(0.2) + rand.Frand01<T>();
|
|
m_Y = T(0.2) * rand.Frand01<T>();
|
|
m_Z = T(0.2) * rand.Frand01<T>();
|
|
m_C = 5 * rand.Frand01<T>();
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(&m_X, prefix + "popcorn2_3D_x", T(0.1)));
|
|
m_Params.push_back(ParamWithName<T>(&m_Y, prefix + "popcorn2_3D_y", T(0.1)));
|
|
m_Params.push_back(ParamWithName<T>(&m_Z, prefix + "popcorn2_3D_z", T(0.1)));
|
|
m_Params.push_back(ParamWithName<T>(&m_C, prefix + "popcorn2_3D_c", 3));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_SinTanC, prefix + "popcorn2_3D_sintanc"));//Precalc.
|
|
m_Params.push_back(ParamWithName<T>(true, &m_HalfWeight, prefix + "popcorn2_3D_half_weight"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Vv, prefix + "popcorn2_3D_vv"));
|
|
}
|
|
|
|
private:
|
|
T m_X;
|
|
T m_Y;
|
|
T m_Z;
|
|
T m_C;
|
|
T m_SinTanC;//Precalcs.
|
|
T m_HalfWeight;
|
|
T m_Vv;
|
|
};
|
|
|
|
/// <summary>
|
|
/// sinusoidal3d.
|
|
/// </summary>
|
|
template <typename T>
|
|
class Sinusoidal3DVariation : public Variation<T>
|
|
{
|
|
public:
|
|
Sinusoidal3DVariation(T weight = 1.0) : Variation<T>("sinusoidal3D", eVariationId::VAR_SINUSOIDAL3D, weight) { }
|
|
|
|
VARCOPY(Sinusoidal3DVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
helper.Out.x = m_Weight * std::sin(helper.In.x);
|
|
helper.Out.y = m_Weight * std::sin(helper.In.y);
|
|
helper.Out.z = m_Weight * (std::atan2(SQR(helper.In.x), SQR(helper.In.y)) * std::cos(helper.In.z));
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss;
|
|
string weight = WeightDefineString();
|
|
ss << "\t{\n"
|
|
<< "\t\tvOut.x = " << weight << " * sin(vIn.x);\n"
|
|
<< "\t\tvOut.y = " << weight << " * sin(vIn.y);\n"
|
|
<< "\t\tvOut.z = " << weight << " * (atan2(SQR(vIn.x), SQR(vIn.y)) * cos(vIn.z));\n"
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
};
|
|
|
|
/// <summary>
|
|
/// scry_3D.
|
|
/// </summary>
|
|
template <typename T>
|
|
class Scry3DVariation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
Scry3DVariation(T weight = 1.0) : ParametricVariation<T>("scry_3D", eVariationId::VAR_SCRY3D, weight, true, false, false, false, true)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(Scry3DVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
T t = helper.m_PrecalcSumSquares + SQR(helper.In.z);
|
|
T r = 1 / Zeps(std::sqrt(t) * (t + m_InvWeight));
|
|
T z = helper.In.z == 0 ? helper.m_PrecalcAtanyx : helper.In.z;
|
|
helper.Out.x = helper.In.x * r;
|
|
helper.Out.y = helper.In.y * r;
|
|
helper.Out.z = z * r;
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
int i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string index = ss2.str();
|
|
string weight = WeightDefineString();
|
|
string invWeight = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\treal_t t = fma(vIn.z, vIn.z, precalcSumSquares);\n"
|
|
<< "\t\treal_t r = 1 / Zeps(sqrt(t) * (t + " << invWeight << "));\n"
|
|
<< "\t\treal_t z = vIn.z == 0 ? precalcAtanyx : vIn.z;\n"
|
|
<< "\n"
|
|
<< "\t\tvOut.x = vIn.x * r;\n"
|
|
<< "\t\tvOut.y = vIn.y * r;\n"
|
|
<< "\t\tvOut.z = z * r;\n"
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual void Precalc() override
|
|
{
|
|
m_InvWeight = 1 / Zeps(m_Weight);
|
|
}
|
|
|
|
virtual vector<string> OpenCLGlobalFuncNames() const override
|
|
{
|
|
return vector<string> { "Zeps" };
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(true, &m_InvWeight, prefix + "scry_3D_inv_weight"));//Precalcs only, no params.
|
|
}
|
|
|
|
private:
|
|
T m_InvWeight;//Precalcs only, no params.
|
|
};
|
|
|
|
/// <summary>
|
|
/// shredlin.
|
|
/// </summary>
|
|
template <typename T>
|
|
class ShredlinVariation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
ShredlinVariation(T weight = 1.0) : ParametricVariation<T>("shredlin", eVariationId::VAR_SHRED_LIN, weight)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(ShredlinVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
const int xpos = helper.In.x < 0;
|
|
const int ypos = helper.In.y < 0;
|
|
const T xrng = helper.In.x / m_XDistance;
|
|
const T yrng = helper.In.y / m_YDistance;
|
|
helper.Out.x = m_Xw * ((xrng - int(xrng)) * m_XWidth + int(xrng) + (T(0.5) - xpos) * m_1mX);
|
|
helper.Out.y = m_Yw * ((yrng - int(yrng)) * m_YWidth + int(yrng) + (T(0.5) - ypos) * m_1mY);
|
|
helper.Out.z = m_Weight * helper.In.z;
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
intmax_t i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string index = ss2.str();
|
|
string weight = WeightDefineString();
|
|
string xdist = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string xwidth = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string ydist = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string ywidth = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string xw = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string yw = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string onemx = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string onemy = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\tconst int xpos = vIn.x < 0;\n"
|
|
<< "\t\tconst int ypos = vIn.y < 0;\n"
|
|
<< "\t\tconst real_t xrng = vIn.x / " << xdist << ";\n"
|
|
<< "\t\tconst real_t yrng = vIn.y / " << ydist << ";\n"
|
|
<< "\n"
|
|
<< "\t\tvOut.x = " << xw << " * fma((xrng - (int)xrng), " << xwidth << ", (int)xrng + ((real_t)(0.5) - xpos) * " << onemx << ");\n"
|
|
<< "\t\tvOut.y = " << yw << " * fma((yrng - (int)yrng), " << ywidth << ", (int)yrng + ((real_t)(0.5) - ypos) * " << onemy << ");\n"
|
|
<< "\t\tvOut.z = " << weight << " * vIn.z;\n"
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual void Precalc() override
|
|
{
|
|
m_Xw = m_Weight * m_XDistance;
|
|
m_Yw = m_Weight * m_YDistance;
|
|
m_1mX = 1 - m_XWidth;
|
|
m_1mY = 1 - m_YWidth;
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(&m_XDistance, prefix + "shredlin_xdistance", 1, eParamType::REAL_NONZERO));
|
|
m_Params.push_back(ParamWithName<T>(&m_XWidth, prefix + "shredlin_xwidth", T(0.5), eParamType::REAL, -1, 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_YDistance, prefix + "shredlin_ydistance", 1, eParamType::REAL_NONZERO));
|
|
m_Params.push_back(ParamWithName<T>(&m_YWidth, prefix + "shredlin_ywidth", T(0.5), eParamType::REAL, -1, 1));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Xw, prefix + "shredlin_xw"));//Precalc.
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Yw, prefix + "shredlin_yw"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_1mX, prefix + "shredlin_1mx"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_1mY, prefix + "shredlin_1my"));
|
|
}
|
|
|
|
private:
|
|
T m_XDistance;
|
|
T m_XWidth;
|
|
T m_YDistance;
|
|
T m_YWidth;
|
|
T m_Xw;//Precalc.
|
|
T m_Yw;
|
|
T m_1mX;
|
|
T m_1mY;
|
|
};
|
|
|
|
/// <summary>
|
|
/// splitbrdr.
|
|
/// </summary>
|
|
template <typename T>
|
|
class SplitBrdrVariation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
SplitBrdrVariation(T weight = 1.0) : ParametricVariation<T>("SplitBrdr", eVariationId::VAR_SPLIT_BRDR, weight, true)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(SplitBrdrVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
T b = m_Weight / (helper.m_PrecalcSumSquares * T(0.25) + 1);
|
|
T roundX = std::rint(helper.In.x);
|
|
T roundY = std::rint(helper.In.y);
|
|
T offsetX = helper.In.x - roundX;
|
|
T offsetY = helper.In.y - roundY;
|
|
helper.Out.x = helper.In.x * b;
|
|
helper.Out.y = helper.In.y * b;
|
|
|
|
if (rand.Frand01<T>() >= T(0.75))
|
|
{
|
|
helper.Out.x += m_Weight * (offsetX * T(0.5) + roundX);
|
|
helper.Out.y += m_Weight * (offsetY * T(0.5) + roundY);
|
|
}
|
|
else
|
|
{
|
|
if (std::abs(offsetX) >= std::abs(offsetY))
|
|
{
|
|
if (offsetX >= 0)
|
|
{
|
|
helper.Out.x += m_Weight * (offsetX * T(0.5) + roundX + m_X);
|
|
helper.Out.y += m_Weight * (offsetY * T(0.5) + roundY + m_Y * offsetY / Zeps(offsetX));
|
|
}
|
|
else
|
|
{
|
|
helper.Out.x += m_Weight * (offsetX * T(0.5) + roundX - m_Y);
|
|
helper.Out.y += m_Weight * (offsetY * T(0.5) + roundY - m_Y * offsetY / Zeps(offsetX));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (offsetY >= 0)
|
|
{
|
|
helper.Out.y += m_Weight * (offsetY * T(0.5) + roundY + m_Y);
|
|
helper.Out.x += m_Weight * (offsetX * T(0.5) + roundX + offsetX / Zeps(offsetY) * m_Y);
|
|
}
|
|
else
|
|
{
|
|
helper.Out.y += m_Weight * (offsetY * T(0.5) + roundY - m_Y);
|
|
helper.Out.x += m_Weight * (offsetX * T(0.5) + roundX - offsetX / Zeps(offsetY) * m_X);
|
|
}
|
|
}
|
|
}
|
|
|
|
helper.Out.x += helper.In.x * m_Px;
|
|
helper.Out.y += helper.In.y * m_Py;
|
|
helper.Out.z = DefaultZ(helper);
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
intmax_t i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string index = ss2.str();
|
|
string weight = WeightDefineString();
|
|
string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string px = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string py = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\treal_t b = " << weight << " / fma(precalcSumSquares, (real_t)(0.25), (real_t)(1.0));\n"
|
|
<< "\t\treal_t roundX = rint(vIn.x);\n"
|
|
<< "\t\treal_t roundY = rint(vIn.y);\n"
|
|
<< "\t\treal_t offsetX = vIn.x - roundX;\n"
|
|
<< "\t\treal_t offsetY = vIn.y - roundY;\n"
|
|
<< "\n"
|
|
<< "\t\tvOut.x = vIn.x * b;\n"
|
|
<< "\t\tvOut.y = vIn.y * b;\n"
|
|
<< "\n"
|
|
<< "\t\tif (MwcNext01(mwc) >= (real_t)(0.75))\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t vOut.x += " << weight << " * fma(offsetX, (real_t)(0.5), roundX);\n"
|
|
<< "\t\t vOut.y += " << weight << " * fma(offsetY, (real_t)(0.5), roundY);\n"
|
|
<< "\t\t}\n"
|
|
<< "\t\telse\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t if (fabs(offsetX) >= fabs(offsetY))\n"
|
|
<< "\t\t {\n"
|
|
<< "\t\t if (offsetX >= 0)\n"
|
|
<< "\t\t {\n"
|
|
<< "\t\t vOut.x += " << weight << " * fma(offsetX, (real_t)(0.5), roundX + " << x << ");\n"
|
|
<< "\t\t vOut.y += " << weight << " * fma(offsetY, (real_t)(0.5), fma(" << y << ", offsetY / Zeps(offsetX), roundY));\n"
|
|
<< "\t\t }\n"
|
|
<< "\t\t else\n"
|
|
<< "\t\t {\n"
|
|
<< "\t\t vOut.x += " << weight << " * fma(offsetX, (real_t)(0.5), roundX - " << y << ");\n"
|
|
<< "\t\t vOut.y += " << weight << " * fma(offsetY, (real_t)(0.5), roundY - " << y << " * offsetY / Zeps(offsetX));\n"
|
|
<< "\t\t }\n"
|
|
<< "\t\t }\n"
|
|
<< "\t\t else\n"
|
|
<< "\t\t {\n"
|
|
<< "\t\t if (offsetY >= 0)\n"
|
|
<< "\t\t {\n"
|
|
<< "\t\t vOut.y += " << weight << " * fma(offsetY, (real_t)(0.5), roundY + " << y << ");\n"
|
|
<< "\t\t vOut.x += " << weight << " * fma(offsetX, (real_t)(0.5), roundX + offsetX / Zeps(offsetY) * " << y << ");\n"
|
|
<< "\t\t }\n"
|
|
<< "\t\t else\n"
|
|
<< "\t\t {\n"
|
|
<< "\t\t vOut.y += " << weight << " * fma(offsetY, (real_t)(0.5), roundY - " << y << ");\n"
|
|
<< "\t\t vOut.x += " << weight << " * fma(offsetX, (real_t)(0.5), roundX - offsetX / Zeps(offsetY) * " << x << ");\n"
|
|
<< "\t\t }\n"
|
|
<< "\t\t }\n"
|
|
<< "\t\t}\n"
|
|
<< "\n"
|
|
<< "\t\tvOut.x += vIn.x * " << px << ";\n"
|
|
<< "\t\tvOut.y += vIn.y * " << py << ";\n"
|
|
<< "\t\tvOut.z = " << DefaultZCl()
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual vector<string> OpenCLGlobalFuncNames() const override
|
|
{
|
|
return vector<string> { "Zeps" };
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(&m_X, prefix + "SplitBrdr_x", T(0.25)));//Original used a prefix of splitb_, which is incompatible with Ember's design.
|
|
m_Params.push_back(ParamWithName<T>(&m_Y, prefix + "SplitBrdr_y", T(0.25)));
|
|
m_Params.push_back(ParamWithName<T>(&m_Px, prefix + "SplitBrdr_px"));
|
|
m_Params.push_back(ParamWithName<T>(&m_Py, prefix + "SplitBrdr_py"));
|
|
}
|
|
|
|
private:
|
|
T m_X;
|
|
T m_Y;
|
|
T m_Px;
|
|
T m_Py;
|
|
};
|
|
|
|
/// <summary>
|
|
/// wdisc.
|
|
/// </summary>
|
|
template <typename T>
|
|
class WdiscVariation : public Variation<T>
|
|
{
|
|
public:
|
|
WdiscVariation(T weight = 1.0) : Variation<T>("wdisc", eVariationId::VAR_WDISC, weight, true, true, false, false, true) { }
|
|
|
|
VARCOPY(WdiscVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
T a = T(M_PI) / (helper.m_PrecalcSqrtSumSquares + 1);
|
|
T r = helper.m_PrecalcAtanyx * T(M_1_PI);
|
|
|
|
if (r > 0)
|
|
a = T(M_PI) - a;
|
|
|
|
helper.Out.x = m_Weight * r * std::cos(a);
|
|
helper.Out.y = m_Weight * r * std::sin(a);
|
|
helper.Out.z = DefaultZ(helper);
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss;
|
|
string weight = WeightDefineString();
|
|
ss << "\t{\n"
|
|
<< "\t\treal_t a = MPI / (precalcSqrtSumSquares + 1);\n"
|
|
<< "\t\treal_t r = precalcAtanyx * M1PI;\n"
|
|
<< "\n"
|
|
<< "\t\tif (r > 0)\n"
|
|
<< "\t\t a = MPI - a;\n"
|
|
<< "\n"
|
|
<< "\t\tvOut.x = " << weight << " * r * cos(a);\n"
|
|
<< "\t\tvOut.y = " << weight << " * r * sin(a);\n"
|
|
<< "\t\tvOut.z = " << DefaultZCl()
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
};
|
|
|
|
/// <summary>
|
|
/// falloff.
|
|
/// </summary>
|
|
template <typename T>
|
|
class FalloffVariation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
FalloffVariation(T weight = 1.0) : ParametricVariation<T>("falloff", eVariationId::VAR_FALLOFF, weight, false, false, false, false, true)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(FalloffVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
const T ax = rand.Frand<T>(T(-0.5), T(0.5));
|
|
const T ay = rand.Frand<T>(T(-0.5), T(0.5));
|
|
const T az = rand.Frand<T>(T(-0.5), T(0.5));
|
|
const T r = std::sqrt(Sqr(helper.In.x - m_X0) + Sqr(helper.In.y - m_Y0) + Sqr(helper.In.z - m_Z0));
|
|
const T rc = ((m_Invert != 0 ? std::max<T>(1 - r, 0) : std::max<T>(r, 0)) - m_MinDist) * m_InternalScatter;//Original called a macro named min, which internally performed max.
|
|
const T rs = std::max<T>(rc, 0);
|
|
T sigma, phi, rad, sigmas, sigmac, phis, phic;
|
|
T scale, denom;
|
|
|
|
switch (int(m_Type))
|
|
{
|
|
case 0://Linear.
|
|
helper.Out.x = m_Weight * (helper.In.x + m_MulX * ax * rs);
|
|
helper.Out.y = m_Weight * (helper.In.y + m_MulY * ay * rs);
|
|
helper.Out.z = m_Weight * (helper.In.z + m_MulZ * az * rs);
|
|
break;
|
|
|
|
case 1://Radial.
|
|
rad = r + m_MulX * ax * rs;
|
|
phi = helper.m_PrecalcAtanyx + m_MulY * ay * rs;
|
|
sigma = std::asin(r == 0 ? 0 : helper.In.z / r) + m_MulZ * az * rs;
|
|
sigmas = std::sin(sigma) * m_Weight;
|
|
sigmac = std::cos(sigma) * m_Weight;
|
|
phis = std::sin(phi);
|
|
phic = std::cos(phi);
|
|
helper.Out.x = rad * sigmac * phic;
|
|
helper.Out.y = rad * sigmac * phis;
|
|
helper.Out.z = rad * sigmas;
|
|
break;
|
|
|
|
case 2://Box.
|
|
default:
|
|
scale = Clamp<T>(rs, 0, T(0.9)) + T(0.1);
|
|
denom = 1 / scale;
|
|
helper.Out.x = m_Weight * Lerp<T>(helper.In.x, std::floor(helper.In.x * denom) + scale * ax, m_MulX * rs) + m_MulX * std::pow(ax, m_BoxPow) * rs * denom;//m_BoxPow should be an integer value held in T,
|
|
helper.Out.y = m_Weight * Lerp<T>(helper.In.y, std::floor(helper.In.y * denom) + scale * ay, m_MulY * rs) + m_MulY * std::pow(ay, m_BoxPow) * rs * denom;//so std::abs() shouldn't be necessary.
|
|
helper.Out.z = m_Weight * Lerp<T>(helper.In.z, std::floor(helper.In.z * denom) + scale * az, m_MulZ * rs) + m_MulZ * std::pow(az, m_BoxPow) * rs * denom;
|
|
break;
|
|
}
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
intmax_t i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string index = ss2.str();
|
|
string weight = WeightDefineString();
|
|
string scatter = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string minDist = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string mulX = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string mulY = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string mulZ = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string x0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string y0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string z0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string invert = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string type = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string boxPow = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string internalScatter = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\tconst real_t ax = MwcNext0505(mwc);\n"
|
|
<< "\t\tconst real_t ay = MwcNext0505(mwc);\n"
|
|
<< "\t\tconst real_t az = MwcNext0505(mwc);\n"
|
|
<< "\t\tconst real_t xmx = vIn.x - " << x0 << ";\n"
|
|
<< "\t\tconst real_t ymy = vIn.y - " << y0 << ";\n"
|
|
<< "\t\tconst real_t zmz = vIn.z - " << z0 << ";\n"
|
|
<< "\t\tconst real_t r = sqrt(fma(xmx, xmx, fma(ymy, ymy, SQR(zmz))));\n"
|
|
<< "\t\tconst real_t rc = ((" << invert << " != 0 ? max(1 - r, (real_t)(0.0)) : max(r, (real_t)(0.0))) - " << minDist << ") * " << internalScatter << ";\n"
|
|
<< "\t\tconst real_t rs = max(rc, (real_t)(0.0));\n"
|
|
<< "\n"
|
|
<< "\t\treal_t sigma, phi, rad, sigmas, sigmac, phis, phic;\n"
|
|
<< "\t\treal_t scale, denom;\n"
|
|
<< "\n"
|
|
<< "\t\tswitch ((int)" << type << ")\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t case 0:\n"
|
|
<< "\t\t vOut.x = " << weight << " * fma(" << mulX << ", ax * rs, vIn.x);\n"
|
|
<< "\t\t vOut.y = " << weight << " * fma(" << mulY << ", ay * rs, vIn.y);\n"
|
|
<< "\t\t vOut.z = " << weight << " * fma(" << mulZ << ", az * rs, vIn.z);\n"
|
|
<< "\t\t break;\n"
|
|
<< "\t\t case 1:\n"
|
|
<< "\t\t rad = fma(" << mulX << ", ax * rs, r);\n"
|
|
<< "\t\t phi = fma(" << mulY << ", ay * rs, precalcAtanyx);\n"
|
|
<< "\t\t sigma = fma(" << mulZ << ", az * rs, asin(r == 0 ? (real_t)(0.0) : vIn.z / r));\n"
|
|
<< "\n"
|
|
<< "\t\t sigmas = sin(sigma) * " << weight << ";\n"
|
|
<< "\t\t sigmac = cos(sigma) * " << weight << ";\n"
|
|
<< "\t\t phis = sin(phi);\n"
|
|
<< "\t\t phic = cos(phi);\n"
|
|
<< "\n"
|
|
<< "\t\t vOut.x = rad * sigmac * phic;\n"
|
|
<< "\t\t vOut.y = rad * sigmac * phis;\n"
|
|
<< "\t\t vOut.z = rad * sigmas;\n"
|
|
<< "\t\t break;\n"
|
|
<< "\t\t case 2:\n"
|
|
<< "\t\t default:\n"
|
|
<< "\t\t scale = clamp(rs, (real_t)(0.0), (real_t)(0.9)) + (real_t)(0.1);\n"
|
|
<< "\t\t denom = 1 / scale;\n"
|
|
<< "\t\t vOut.x = fma(" << weight << ", Lerp(vIn.x, fma(scale, ax, floor(vIn.x * denom)), " << mulX << " * rs), " << mulX << " * pow(ax, " << boxPow << ") * rs * denom);\n"
|
|
<< "\t\t vOut.y = fma(" << weight << ", Lerp(vIn.y, fma(scale, ay, floor(vIn.y * denom)), " << mulY << " * rs), " << mulY << " * pow(ay, " << boxPow << ") * rs * denom);\n"
|
|
<< "\t\t vOut.z = fma(" << weight << ", Lerp(vIn.z, fma(scale, az, floor(vIn.z * denom)), " << mulZ << " * rs), " << mulZ << " * pow(az, " << boxPow << ") * rs * denom);\n"
|
|
<< "\t\t break;\n"
|
|
<< "\t\t}\n"
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual vector<string> OpenCLGlobalFuncNames() const override
|
|
{
|
|
return vector<string> { "Lerp" };
|
|
}
|
|
|
|
virtual void Precalc() override
|
|
{
|
|
m_InternalScatter = T(0.04) * m_Scatter;
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(&m_Scatter, prefix + "falloff_scatter", 1, eParamType::REAL, EPS, TMAX));
|
|
m_Params.push_back(ParamWithName<T>(&m_MinDist, prefix + "falloff_mindist", T(0.5), eParamType::REAL, 0, TMAX));
|
|
m_Params.push_back(ParamWithName<T>(&m_MulX, prefix + "falloff_mul_x", 1, eParamType::REAL, 0, 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_MulY, prefix + "falloff_mul_y", 1, eParamType::REAL, 0, 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_MulZ, prefix + "falloff_mul_z", 0, eParamType::REAL, 0, 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_X0, prefix + "falloff_x0"));
|
|
m_Params.push_back(ParamWithName<T>(&m_Y0, prefix + "falloff_y0"));
|
|
m_Params.push_back(ParamWithName<T>(&m_Z0, prefix + "falloff_z0"));
|
|
m_Params.push_back(ParamWithName<T>(&m_Invert, prefix + "falloff_invert", 0, eParamType::INTEGER, 0, 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_Type, prefix + "falloff_type", 0, eParamType::INTEGER, 0, 2));
|
|
m_Params.push_back(ParamWithName<T>(&m_BoxPow, prefix + "falloff_boxpow", 2, eParamType::INTEGER, 2, 32));//Original defaulted this to 0 which directly contradicts the specified range of 2-32.
|
|
m_Params.push_back(ParamWithName<T>(true, &m_InternalScatter, prefix + "falloff_internal_scatter"));//Precalc.
|
|
}
|
|
|
|
private:
|
|
T m_Scatter;
|
|
T m_MinDist;
|
|
T m_MulX;
|
|
T m_MulY;
|
|
T m_MulZ;
|
|
T m_X0;
|
|
T m_Y0;
|
|
T m_Z0;
|
|
T m_Invert;
|
|
T m_Type;
|
|
T m_BoxPow;
|
|
T m_InternalScatter;
|
|
};
|
|
|
|
/// <summary>
|
|
/// falloff2.
|
|
/// </summary>
|
|
template <typename T>
|
|
class Falloff2Variation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
Falloff2Variation(T weight = 1.0) : ParametricVariation<T>("falloff2", eVariationId::VAR_FALLOFF2, weight, true, false, false, false, true)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(Falloff2Variation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
const v4T random(rand.Frand<T>(T(-0.5), T(0.5)), rand.Frand<T>(T(-0.5), T(0.5)), rand.Frand<T>(T(-0.5), T(0.5)), rand.Frand<T>(T(-0.5), T(0.5)));
|
|
const T distA = std::sqrt(Sqr(helper.In.x - m_X0) + Sqr(helper.In.y - m_Y0) + Sqr(helper.In.z - m_Z0));
|
|
const T distB = m_Invert != 0 ? std::max<T>(1 - distA, 0) : std::max<T>(distA, 0);//Original called a macro named min, which internally performed max.
|
|
const T dist = std::max<T>((distB - m_MinDist) * m_RMax, 0);
|
|
|
|
switch (int(m_Type))
|
|
{
|
|
case 0://Linear.
|
|
{
|
|
helper.Out.x = (helper.In.x + m_MulX * random.x * dist) * m_Weight;
|
|
helper.Out.y = (helper.In.y + m_MulY * random.y * dist) * m_Weight;
|
|
helper.Out.z = (helper.In.z + m_MulZ * random.z * dist) * m_Weight;
|
|
}
|
|
break;
|
|
|
|
case 1://Radial.
|
|
{
|
|
if (helper.In.x == 0 && helper.In.y == 0 && helper.In.z == 0)
|
|
{
|
|
helper.Out.x = helper.In.x * m_Weight;
|
|
helper.Out.y = helper.In.y * m_Weight;
|
|
helper.Out.z = helper.In.z * m_Weight;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
const T rIn = Zeps(std::sqrt(helper.m_PrecalcSumSquares + SQR(helper.In.z)));
|
|
const T r = rIn + m_MulX * random.x * dist;
|
|
const T phi = helper.m_PrecalcAtanyx + m_MulY * random.y * dist;
|
|
const T sigma = std::asin(helper.In.z / rIn) + m_MulZ * random.z * dist;
|
|
const T sigmas = std::sin(sigma) * m_Weight;
|
|
const T sigmac = std::cos(sigma) * m_Weight;
|
|
const T phis = std::sin(phi);
|
|
const T phic = std::cos(phi);
|
|
helper.Out.x = r * sigmac * phic;
|
|
helper.Out.y = r * sigmac * phis;
|
|
helper.Out.z = r * sigmas;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 2://Gaussian.
|
|
default:
|
|
{
|
|
const T sigma = dist * random.y * M_2PI;
|
|
const T phi = dist * random.z * T(M_PI);
|
|
const T rad = dist * random.x;
|
|
const T sigmas = std::sin(sigma);
|
|
const T sigmac = std::cos(sigma);
|
|
const T phis = std::sin(phi);
|
|
const T phic = std::cos(phi);
|
|
helper.Out.x = (helper.In.x + m_MulX * rad * sigmac * phic) * m_Weight;
|
|
helper.Out.y = (helper.In.y + m_MulY * rad * sigmac * phis) * m_Weight;
|
|
helper.Out.z = (helper.In.z + m_MulZ * rad * sigmas) * m_Weight;
|
|
}
|
|
break;
|
|
}
|
|
|
|
outPoint.m_ColorX = std::abs(fmod(outPoint.m_ColorX + m_MulC * random.w * dist, T(1)));
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
int i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string index = ss2.str();
|
|
string weight = WeightDefineString();
|
|
string scatter = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string minDist = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string mulX = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string mulY = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string mulZ = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string mulC = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string x0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string y0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string z0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string invert = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string type = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string rMax = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\tconst real_t randx = MwcNext0505(mwc);\n"
|
|
<< "\t\tconst real_t randy = MwcNext0505(mwc);\n"
|
|
<< "\t\tconst real_t randz = MwcNext0505(mwc);\n"
|
|
<< "\t\tconst real_t randc = MwcNext0505(mwc);\n"
|
|
<< "\t\tconst real_t xmx = vIn.x - " << x0 << ";\n"
|
|
<< "\t\tconst real_t ymy = vIn.y - " << y0 << ";\n"
|
|
<< "\t\tconst real_t zmz = vIn.z - " << z0 << ";\n"
|
|
<< "\t\tconst real_t distA = sqrt(fma(xmx, xmx, fma(ymy, ymy, SQR(zmz))));\n"
|
|
<< "\t\tconst real_t distB = " << invert << " != 0 ? max(1 - distA, (real_t)(0.0)) : max(distA, (real_t)(0.0));\n"
|
|
<< "\t\tconst real_t dist = max((distB - " << minDist << ") * " << rMax << ", (real_t)(0.0));\n"
|
|
<< "\n"
|
|
<< "\t\tswitch ((int)" << type << ")\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t case 0:\n"
|
|
<< "\t\t vOut.x = fma(" << mulX << ", randx * dist, vIn.x) * " << weight << ";\n"
|
|
<< "\t\t vOut.y = fma(" << mulY << ", randy * dist, vIn.y) * " << weight << ";\n"
|
|
<< "\t\t vOut.z = fma(" << mulZ << ", randz * dist, vIn.z) * " << weight << ";\n"
|
|
<< "\t\t outPoint->m_ColorX = fabs(fmod(fma(" << mulC << ", randc * dist, outPoint->m_ColorX), (real_t)(1.0)));\n"
|
|
<< "\t\t break;\n"
|
|
<< "\t\t case 1:\n"
|
|
<< "\t\t if (vIn.x == 0 && vIn.y == 0 && vIn.z == 0)\n"
|
|
<< "\t\t {\n"
|
|
<< "\t\t vOut.x = vIn.x * " << weight << ";\n"
|
|
<< "\t\t vOut.y = vIn.y * " << weight << ";\n"
|
|
<< "\t\t vOut.z = vIn.z * " << weight << ";\n"
|
|
<< "\t\t }\n"
|
|
<< "\t\t else\n"
|
|
<< "\t\t {\n"
|
|
<< "\t\t real_t rIn = Zeps(sqrt(fma(vIn.z, vIn.z, precalcSumSquares)));\n"
|
|
<< "\t\t real_t r = fma(" << mulX << ", randx * dist, rIn);\n"
|
|
<< "\t\t real_t phi = fma(" << mulY << ", randy * dist, precalcAtanyx);\n"
|
|
<< "\t\t real_t sigma = fma(" << mulZ << ", randz * dist, asin(vIn.z / rIn));\n"
|
|
<< "\t\t real_t sigmas = sin(sigma) * " << weight << ";\n"
|
|
<< "\t\t real_t sigmac = cos(sigma) * " << weight << ";\n"
|
|
<< "\t\t real_t phis = sin(phi);\n"
|
|
<< "\t\t real_t phic = cos(phi);\n"
|
|
<< "\n"
|
|
<< "\t\t vOut.x = r * sigmac * phic;\n"
|
|
<< "\t\t vOut.y = r * sigmac * phis;\n"
|
|
<< "\t\t vOut.z = r * sigmas;\n"
|
|
<< "\t\t outPoint->m_ColorX = fabs(fmod(fma(" << mulC << ", randc * dist, outPoint->m_ColorX), (real_t)(1.0)));\n"
|
|
<< "\t\t }\n"
|
|
<< "\t\t break;\n"
|
|
<< "\t\t case 2:\n"
|
|
<< "\t\t default:\n"
|
|
<< "\t\t {\n"
|
|
<< "\t\t real_t sigma = dist * randy * M_2PI;\n"
|
|
<< "\t\t real_t phi = dist * randz * MPI;\n"
|
|
<< "\t\t real_t rad = dist * randx;\n"
|
|
<< "\t\t real_t sigmas = sin(sigma);\n"
|
|
<< "\t\t real_t sigmac = cos(sigma);\n"
|
|
<< "\t\t real_t phis = sin(phi);\n"
|
|
<< "\t\t real_t phic = cos(phi);\n"
|
|
<< "\n"
|
|
<< "\t\t vOut.x = fma(" << mulX << " * rad, sigmac * phic, vIn.x) * " << weight << ";\n"
|
|
<< "\t\t vOut.y = fma(" << mulY << " * rad, sigmac * phis, vIn.y) * " << weight << ";\n"
|
|
<< "\t\t vOut.z = fma(" << mulZ << " * rad, sigmas, vIn.z) * " << weight << ";\n"
|
|
<< "\t\t outPoint->m_ColorX = fabs(fmod(fma(" << mulC << ", randc * dist, outPoint->m_ColorX), (real_t)(1.0)));\n"
|
|
<< "\t\t break;\n"
|
|
<< "\t\t }\n"
|
|
<< "\t\t}\n"
|
|
<< "\n"
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual vector<string> OpenCLGlobalFuncNames() const override
|
|
{
|
|
return vector<string> { "Zeps" };
|
|
}
|
|
|
|
virtual void Precalc() override
|
|
{
|
|
m_RMax = T(0.04) * m_Scatter;
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(&m_Scatter, prefix + "falloff2_scatter", 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_MinDist, prefix + "falloff2_mindist", T(0.5)));
|
|
m_Params.push_back(ParamWithName<T>(&m_MulX, prefix + "falloff2_mul_x", 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_MulY, prefix + "falloff2_mul_y", 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_MulZ, prefix + "falloff2_mul_z", 0));
|
|
m_Params.push_back(ParamWithName<T>(&m_MulC, prefix + "falloff2_mul_c", 0));
|
|
m_Params.push_back(ParamWithName<T>(&m_X0, prefix + "falloff2_x0"));
|
|
m_Params.push_back(ParamWithName<T>(&m_Y0, prefix + "falloff2_y0"));
|
|
m_Params.push_back(ParamWithName<T>(&m_Z0, prefix + "falloff2_z0"));
|
|
m_Params.push_back(ParamWithName<T>(&m_Invert, prefix + "falloff2_invert", 0, eParamType::INTEGER, 0, 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_Type, prefix + "falloff2_type", 0, eParamType::INTEGER, 0, 2));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_RMax, prefix + "falloff2_rmax"));//Precalc.
|
|
}
|
|
|
|
private:
|
|
T m_Scatter;
|
|
T m_MinDist;
|
|
T m_MulX;
|
|
T m_MulY;
|
|
T m_MulZ;
|
|
T m_MulC;
|
|
T m_X0;
|
|
T m_Y0;
|
|
T m_Z0;
|
|
T m_Invert;
|
|
T m_Type;
|
|
T m_RMax;//Precalc.
|
|
};
|
|
|
|
/// <summary>
|
|
/// falloff3.
|
|
/// </summary>
|
|
template <typename T>
|
|
class Falloff3Variation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
Falloff3Variation(T weight = 1.0) : ParametricVariation<T>("falloff3", eVariationId::VAR_FALLOFF3, weight, true, false, false, false, true)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(Falloff3Variation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
const v4T random(rand.Frand<T>(T(-0.5), T(0.5)), rand.Frand<T>(T(-0.5), T(0.5)), rand.Frand<T>(T(-0.5), T(0.5)), rand.Frand<T>(T(-0.5), T(0.5)));
|
|
T radius;
|
|
|
|
if (m_BlurShape == 0)//Circle.
|
|
radius = std::sqrt(Sqr(helper.In.x - m_CenterX) + Sqr(helper.In.y - m_CenterY) + Sqr(helper.In.z - m_CenterZ));
|
|
else//Square.
|
|
radius = std::max(std::abs(helper.In.x - m_CenterX), std::max(std::abs(helper.In.y - m_CenterY), (std::abs(helper.In.z - m_CenterZ))));//Original called a macro named min, which internally performed max.
|
|
|
|
const T dist = std::max<T>(((m_InvertDistance != 0 ? std::max<T>(1 - radius, 0) : std::max<T>(radius, 0)) - m_MinDistance) * m_RMax, 0);
|
|
|
|
switch (int(m_BlurType))
|
|
{
|
|
case 0://Gaussian.
|
|
{
|
|
const T sigma = dist * random.y * M_2PI;
|
|
const T phi = dist * random.z * T(M_PI);
|
|
const T rad = dist * random.x;
|
|
const T sigmas = std::sin(sigma);
|
|
const T sigmac = std::cos(sigma);
|
|
const T phis = std::sin(phi);
|
|
const T phic = std::cos(phi);
|
|
helper.Out.x = (helper.In.x + m_MulX * rad * sigmac * phic) * m_Weight;
|
|
helper.Out.y = (helper.In.y + m_MulY * rad * sigmac * phis) * m_Weight;
|
|
helper.Out.z = (helper.In.z + m_MulZ * rad * sigmas) * m_Weight;
|
|
outPoint.m_ColorX = std::abs(fmod(outPoint.m_ColorX + m_MulC * random.w * dist, T(1)));
|
|
}
|
|
break;
|
|
|
|
case 1://Radial.
|
|
if (helper.In.x == 0 && helper.In.y == 0 && helper.In.z == 0)
|
|
{
|
|
helper.Out.x = helper.In.x * m_Weight;
|
|
helper.Out.y = helper.In.y * m_Weight;
|
|
helper.Out.z = helper.In.z * m_Weight;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
const T rIn = std::sqrt(helper.m_PrecalcSumSquares + SQR(helper.In.z));
|
|
const T r = rIn + m_MulX * random.x * dist;
|
|
const T phi = helper.m_PrecalcAtanyx + m_MulY * random.y * dist;
|
|
const T sigma = std::asin(helper.In.z / rIn) + m_MulZ * random.z * dist;
|
|
const T sigmas = std::sin(sigma) * m_Weight;
|
|
const T sigmac = std::cos(sigma) * m_Weight;
|
|
const T phis = std::sin(phi);
|
|
const T phic = std::cos(phi);
|
|
helper.Out.x = r * sigmac * phic;
|
|
helper.Out.y = r * sigmac * phis;
|
|
helper.Out.z = r * sigmas;
|
|
outPoint.m_ColorX = std::abs(fmod(outPoint.m_ColorX + m_MulC * random.w * dist, T(1)));
|
|
}
|
|
|
|
break;
|
|
|
|
case 2://Log.
|
|
default:
|
|
{
|
|
const T coeff = m_RMax <= EPS ? dist : dist + m_Alpha * (VarFuncs<T>::LogMap(dist) - dist);
|
|
helper.Out.x = (helper.In.x + VarFuncs<T>::LogMap(m_MulX) * VarFuncs<T>::LogScale(random.x) * coeff) * m_Weight;
|
|
helper.Out.y = (helper.In.y + VarFuncs<T>::LogMap(m_MulY) * VarFuncs<T>::LogScale(random.y) * coeff) * m_Weight;
|
|
helper.Out.z = (helper.In.z + VarFuncs<T>::LogMap(m_MulZ) * VarFuncs<T>::LogScale(random.z) * coeff) * m_Weight;
|
|
outPoint.m_ColorX = std::abs(fmod(outPoint.m_ColorX + VarFuncs<T>::LogMap(m_MulC) * VarFuncs<T>::LogScale(random.w) * coeff, T(1)));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
int i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string index = ss2.str();
|
|
string weight = WeightDefineString();
|
|
string blurType = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string blurShape = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string blurStrength = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string minDist = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string invertDist = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string mulX = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string mulY = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string mulZ = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string mulC = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string centerX = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string centerY = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string centerZ = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string alpha = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string rMax = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\tconst real_t randx = MwcNext0505(mwc);\n"
|
|
<< "\t\tconst real_t randy = MwcNext0505(mwc);\n"
|
|
<< "\t\tconst real_t randz = MwcNext0505(mwc);\n"
|
|
<< "\t\tconst real_t randc = MwcNext0505(mwc);\n"
|
|
<< "\t\tconst real_t xmx = vIn.x - " << centerX << ";\n"
|
|
<< "\t\tconst real_t ymy = vIn.y - " << centerY << ";\n"
|
|
<< "\t\tconst real_t zmz = vIn.z - " << centerZ << ";\n"
|
|
<< "\t\treal_t radius;\n"
|
|
<< "\n"
|
|
<< "\t\tif (" << blurShape << " == 0)\n"
|
|
<< "\t\t radius = sqrt(fma(xmx, xmx, fma(ymy, ymy, SQR(zmz))));\n"
|
|
<< "\t\telse\n"
|
|
<< "\t\t radius = max(fabs(xmx), max(fabs(ymy), (fabs(zmz))));\n"
|
|
<< "\n"
|
|
<< "\t\tconst real_t dist = max(((" << invertDist << " != 0 ? max(1 - radius, (real_t)(0.0)) : max(radius, (real_t)(0.0))) - " << minDist << ") * " << rMax << ", (real_t)(0.0));\n"
|
|
<< "\n"
|
|
<< "\t\tswitch ((int)" << blurType << ")\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\tcase 0:\n"
|
|
<< "\t\t {\n"
|
|
<< "\t\t real_t sigma = dist * randy * M_2PI;\n"
|
|
<< "\t\t real_t phi = dist * randz * MPI;\n"
|
|
<< "\t\t real_t rad = dist * randx;\n"
|
|
<< "\t\t real_t sigmas = sin(sigma);\n"
|
|
<< "\t\t real_t sigmac = cos(sigma);\n"
|
|
<< "\t\t real_t phis = sin(phi);\n"
|
|
<< "\t\t real_t phic = cos(phi);\n"
|
|
<< "\n"
|
|
<< "\t\t vOut.x = fma(" << mulX << " * rad, sigmac * phic, vIn.x) * " << weight << ";\n"
|
|
<< "\t\t vOut.y = fma(" << mulY << " * rad, sigmac * phis, vIn.y) * " << weight << ";\n"
|
|
<< "\t\t vOut.z = fma(" << mulZ << " * rad, sigmas, vIn.z) * " << weight << ";\n"
|
|
<< "\t\t outPoint->m_ColorX = fabs(fmod(fma(" << mulC << ", randc * dist, outPoint->m_ColorX), (real_t)(1.0)));\n"
|
|
<< "\t\t }\n"
|
|
<< "\t\t break;\n"
|
|
<< "\t\tcase 1:\n"
|
|
<< "\t\t if (vIn.x == 0 && vIn.y == 0 && vIn.z == 0)\n"
|
|
<< "\t\t {\n"
|
|
<< "\t\t vOut.x = vIn.x * " << weight << ";\n"
|
|
<< "\t\t vOut.y = vIn.y * " << weight << ";\n"
|
|
<< "\t\t vOut.z = vIn.z * " << weight << ";\n"
|
|
<< "\t\t }\n"
|
|
<< "\t\t else\n"
|
|
<< "\t\t {\n"
|
|
<< "\t\t real_t rIn = Zeps(sqrt(fma(vIn.z, vIn.z, precalcSumSquares)));\n"
|
|
<< "\t\t real_t r = fma(" << mulX << ", randx * dist, rIn);\n"
|
|
<< "\t\t real_t phi = fma(" << mulY << ", randy * dist, precalcAtanyx);\n"
|
|
<< "\t\t real_t sigma = fma(" << mulZ << ", randz * dist, asin(vIn.z / rIn));\n"
|
|
<< "\t\t real_t sigmas = sin(sigma) * " << weight << ";\n"
|
|
<< "\t\t real_t sigmac = cos(sigma) * " << weight << ";\n"
|
|
<< "\t\t real_t phis = sin(phi);\n"
|
|
<< "\t\t real_t phic = cos(phi);\n"
|
|
<< "\n"
|
|
<< "\t\t vOut.x = r * sigmac * phic;\n"
|
|
<< "\t\t vOut.y = r * sigmac * phis;\n"
|
|
<< "\t\t vOut.z = r * sigmas;\n"
|
|
<< "\t\t outPoint->m_ColorX = fabs(fmod(fma(" << mulC << ", randc * dist, outPoint->m_ColorX), (real_t)(1.0)));\n"
|
|
<< "\t\t }\n"
|
|
<< "\t\t break;\n"
|
|
<< "\t\tcase 2:\n"
|
|
<< "\t\tdefault:\n"
|
|
<< "\t\t {\n"
|
|
<< "\t\t real_t coeff = " << rMax << " <= EPS ? dist : fma(" << alpha << ", (LogMap(dist) - dist), dist);\n"
|
|
<< "\n"
|
|
<< "\t\t vOut.x = fma(LogMap(" << mulX << "), LogScale(randx) * coeff, vIn.x) * " << weight << ";\n"
|
|
<< "\t\t vOut.y = fma(LogMap(" << mulY << "), LogScale(randy) * coeff, vIn.y) * " << weight << ";\n"
|
|
<< "\t\t vOut.z = fma(LogMap(" << mulZ << "), LogScale(randz) * coeff, vIn.z) * " << weight << ";\n"
|
|
<< "\t\t outPoint->m_ColorX = fabs(fmod(fma(LogMap(" << mulC << "), LogScale(randc) * coeff, outPoint->m_ColorX), (real_t)(1.0)));\n"
|
|
<< "\t\t }\n"
|
|
<< "\t\t break;\n"
|
|
<< "\t\t}\n"
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual vector<string> OpenCLGlobalFuncNames() const override
|
|
{
|
|
return vector<string> { "SignNz", "LogMap", "LogScale", "Zeps" };
|
|
}
|
|
|
|
virtual void Precalc() override
|
|
{
|
|
m_RMax = T(0.04) * m_BlurStrength;
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(&m_BlurType, prefix + "falloff3_blur_type", 0, eParamType::INTEGER, 0, 3));
|
|
m_Params.push_back(ParamWithName<T>(&m_BlurShape, prefix + "falloff3_blur_shape", 0, eParamType::INTEGER, 0, 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_BlurStrength, prefix + "falloff3_blur_strength", 1, eParamType::REAL, EPS, TMAX));
|
|
m_Params.push_back(ParamWithName<T>(&m_MinDistance, prefix + "falloff3_min_distance", T(0.5), eParamType::REAL, 0, TMAX));
|
|
m_Params.push_back(ParamWithName<T>(&m_InvertDistance, prefix + "falloff3_invert_distance", 0, eParamType::INTEGER, 0, 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_MulX, prefix + "falloff3_mul_x", 1, eParamType::REAL, 0, 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_MulY, prefix + "falloff3_mul_y", 1, eParamType::REAL, 0, 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_MulZ, prefix + "falloff3_mul_z", 0, eParamType::REAL, 0, 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_MulC, prefix + "falloff3_mul_c", 0, eParamType::REAL, 0, 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_CenterX, prefix + "falloff3_center_x"));
|
|
m_Params.push_back(ParamWithName<T>(&m_CenterY, prefix + "falloff3_center_y"));
|
|
m_Params.push_back(ParamWithName<T>(&m_CenterZ, prefix + "falloff3_center_z"));
|
|
m_Params.push_back(ParamWithName<T>(&m_Alpha, prefix + "falloff3_alpha"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_RMax, prefix + "falloff3_rmax"));//Precalc.
|
|
}
|
|
|
|
private:
|
|
T m_BlurType;
|
|
T m_BlurShape;
|
|
T m_BlurStrength;
|
|
T m_MinDistance;
|
|
T m_InvertDistance;
|
|
T m_MulX;
|
|
T m_MulY;
|
|
T m_MulZ;
|
|
T m_MulC;
|
|
T m_CenterX;
|
|
T m_CenterY;
|
|
T m_CenterZ;
|
|
T m_Alpha;
|
|
T m_RMax;//Precalc.
|
|
};
|
|
|
|
/// <summary>
|
|
/// xtrb.
|
|
/// </summary>
|
|
template <typename T>
|
|
class XtrbVariation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
XtrbVariation(T weight = 1.0) : ParametricVariation<T>("xtrb", eVariationId::VAR_XTRB, weight)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(XtrbVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
intmax_t m, n;
|
|
T alpha, beta, offsetAl, offsetBe, offsetGa, x, y;
|
|
//Transfer to trilinear coordinates, normalized to real distances from triangle sides.
|
|
DirectTrilinear(helper.In.x, helper.In.y, alpha, beta);
|
|
m = Floor<T>(alpha / m_S2a);
|
|
offsetAl = alpha - m * m_S2a;
|
|
n = Floor<T>(beta / m_S2b);
|
|
offsetBe = beta - n * m_S2b;
|
|
offsetGa = m_S2c - m_Ac * offsetAl - m_Bc * offsetBe;
|
|
|
|
if (offsetGa > 0)
|
|
{
|
|
Hex(offsetAl, offsetBe, offsetGa, alpha, beta, rand);
|
|
}
|
|
else
|
|
{
|
|
offsetAl = m_S2a - offsetAl;
|
|
offsetBe = m_S2b - offsetBe;
|
|
offsetGa = -offsetGa;
|
|
Hex(offsetAl, offsetBe, offsetGa, alpha, beta, rand);
|
|
alpha = m_S2a - alpha;
|
|
beta = m_S2b - beta;
|
|
}
|
|
|
|
alpha += m * m_S2a;
|
|
beta += n * m_S2b;
|
|
InverseTrilinear(alpha, beta, x, y, rand);
|
|
helper.Out.x = m_Weight * x;
|
|
helper.Out.y = m_Weight * y;
|
|
helper.Out.z = DefaultZ(helper);
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
intmax_t i = 0;
|
|
ss2 << "_" << XformIndexInEmber() << "]";
|
|
string index = ss2.str();
|
|
string weight = WeightDefineString();
|
|
string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string radius = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string width = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string dist = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string a = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string b = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string sinC = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string cosC = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string ha = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string hb = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string hc = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string ab = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string ac = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string ba = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string bc = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string ca = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string cb = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string s2a = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string s2b = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string s2c = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string s2ab = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string s2ac = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string s2bc = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string width1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string width2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string width3 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string absN = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string cn = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
ss << "\t{\n"
|
|
<< "\t\tint m, n;\n"
|
|
<< "\t\treal_t alpha, beta, offsetAl, offsetBe, offsetGa, x, y;\n"
|
|
<< "\n"
|
|
<< "\t\t{\n"//DirectTrilinear function extracted out here.
|
|
<< "\t\t alpha = vIn.y + " << radius << ";\n"
|
|
<< "\t\t beta = fma(vIn.x, " << sinC << ", fma(-vIn.y, " << cosC << ", " << radius << "));\n"
|
|
<< "\t\t}\n"
|
|
<< "\n"
|
|
<< "\t\tm = floor(alpha / " << s2a << ");\n"
|
|
<< "\t\toffsetAl = alpha - m * " << s2a << ";\n"
|
|
<< "\t\tn = floor(beta / " << s2b << ");\n"
|
|
<< "\t\toffsetBe = beta - n * " << s2b << ";\n"
|
|
<< "\t\toffsetGa = " << s2c << " + fma(-" << ac << ", offsetAl, -" << bc << " * offsetBe);\n"
|
|
<< "\n"
|
|
<< "\t\tif (offsetGa > 0)\n"
|
|
<< "\t\t{\n"
|
|
<< "\n"
|
|
<< "\t\t Hex(offsetAl, offsetBe, offsetGa,\n"
|
|
<< "\t\t " << width << ",\n"
|
|
<< "\t\t " << ha << ",\n"
|
|
<< "\t\t " << hb << ",\n"
|
|
<< "\t\t " << hc << ",\n"
|
|
<< "\t\t " << ab << ",\n"
|
|
<< "\t\t " << ba << ",\n"
|
|
<< "\t\t " << bc << ",\n"
|
|
<< "\t\t " << ca << ",\n"
|
|
<< "\t\t " << cb << ",\n"
|
|
<< "\t\t " << s2a << ",\n"
|
|
<< "\t\t " << s2b << ",\n"
|
|
<< "\t\t " << s2ab << ",\n"
|
|
<< "\t\t " << s2ac << ",\n"
|
|
<< "\t\t " << s2bc << ",\n"
|
|
<< "\t\t " << width1 << ",\n"
|
|
<< "\t\t " << width2 << ",\n"
|
|
<< "\t\t " << width3 << ",\n"
|
|
<< "\t\t &alpha, &beta, mwc);\n"
|
|
<< "\n"
|
|
<< "\t\t}\n"
|
|
<< "\t\telse\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t offsetAl = " << s2a << " - offsetAl;\n"
|
|
<< "\t\t offsetBe = " << s2b << " - offsetBe;\n"
|
|
<< "\t\t offsetGa = -offsetGa;\n"
|
|
<< "\n"
|
|
<< "\t\t Hex(offsetAl, offsetBe, offsetGa,\n"
|
|
<< "\t\t " << width << ",\n"
|
|
<< "\t\t " << ha << ",\n"
|
|
<< "\t\t " << hb << ",\n"
|
|
<< "\t\t " << hc << ",\n"
|
|
<< "\t\t " << ab << ",\n"
|
|
<< "\t\t " << ba << ",\n"
|
|
<< "\t\t " << bc << ",\n"
|
|
<< "\t\t " << ca << ",\n"
|
|
<< "\t\t " << cb << ",\n"
|
|
<< "\t\t " << s2a << ",\n"
|
|
<< "\t\t " << s2b << ",\n"
|
|
<< "\t\t " << s2ab << ",\n"
|
|
<< "\t\t " << s2ac << ",\n"
|
|
<< "\t\t " << s2bc << ",\n"
|
|
<< "\t\t " << width1 << ",\n"
|
|
<< "\t\t " << width2 << ",\n"
|
|
<< "\t\t " << width3 << ",\n"
|
|
<< "\t\t &alpha, &beta, mwc);\n"
|
|
<< "\n"
|
|
<< "\t\t alpha = " << s2a << " - alpha;\n"
|
|
<< "\t\t beta = " << s2b << " - beta;\n"
|
|
<< "\t\t}\n"
|
|
<< "\n"
|
|
<< "\t\talpha += m * " << s2a << ";\n"
|
|
<< "\t\tbeta += n * " << s2b << ";\n"
|
|
<< "\n"
|
|
<< "\t\t{\n"//InverseTrilinear function extracted out here.
|
|
<< "\t\t real_t inx = fma(alpha - " << radius << ", " << cosC << ", beta - " << radius << ") / " << sinC << ";\n"
|
|
<< "\t\t real_t iny = alpha - " << radius << ";\n"
|
|
<< "\t\t real_t angle = fma(M_2PI, (real_t)MwcNextRange(mwc, (uint)" << absN << "), atan2(iny, inx)) / " << power << ";\n"
|
|
<< "\t\t real_t r = " << weight << " * pow(fma(inx, inx, SQR(iny)), " << cn << ");\n"
|
|
<< "\n"
|
|
<< "\t\t x = r * cos(angle);\n"
|
|
<< "\t\t y = r * sin(angle);\n"
|
|
<< "\t\t}\n"
|
|
<< "\n"
|
|
<< "\t\tvOut.x = " << weight << " * x;\n"
|
|
<< "\t\tvOut.y = " << weight << " * y;\n"
|
|
<< "\t\tvOut.z = " << DefaultZCl()
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual string OpenCLFuncsString() const override
|
|
{
|
|
return
|
|
"\n"
|
|
"void Hex(real_t al, real_t be, real_t ga,\n"
|
|
" real_t width,\n"
|
|
" real_t ha,\n"
|
|
" real_t hb,\n"
|
|
" real_t hc,\n"
|
|
" real_t ab,\n"
|
|
" real_t ba,\n"
|
|
" real_t bc,\n"
|
|
" real_t ca,\n"
|
|
" real_t cb,\n"
|
|
" real_t s2a,\n"
|
|
" real_t s2b,\n"
|
|
" real_t s2ab,\n"
|
|
" real_t s2ac,\n"
|
|
" real_t s2bc,\n"
|
|
" real_t width1,\n"
|
|
" real_t width2,\n"
|
|
" real_t width3,\n"
|
|
" real_t* al1, real_t* be1, uint2* mwc)\n"
|
|
"{\n"
|
|
" real_t ga1, de1, r = MwcNext01(mwc);\n"
|
|
"\n"
|
|
" if (be < al)\n"
|
|
" {\n"
|
|
" if (ga < be)\n"
|
|
" {\n"
|
|
" if (r >= width3)\n"
|
|
" {\n"
|
|
" de1 = width * be;\n"
|
|
" ga1 = width * ga;\n"
|
|
" }\n"
|
|
" else\n"
|
|
" {\n"
|
|
" ga1 = fma(width1, ga, width2 * hc * ga / be);\n"
|
|
" de1 = fma(width1, be, width2 * s2ab * ((real_t)(3.0) - ga / be));\n"
|
|
" }\n"
|
|
"\n"
|
|
" *al1 = s2a + fma(-ba, de1, - ca * ga1);\n"
|
|
" *be1 = de1;\n"
|
|
" }\n"
|
|
" else\n"
|
|
" {\n"
|
|
" if (ga < al)\n"
|
|
" {\n"
|
|
" if (r >= width3)\n"
|
|
" {\n"
|
|
" ga1 = width * ga;\n"
|
|
" de1 = width * be;\n"
|
|
" }\n"
|
|
" else\n"
|
|
" {\n"
|
|
" de1 = fma(width1, be, width2 * hb * be / ga);\n"
|
|
" ga1 = fma(width1, ga, width2 * s2ac * ((real_t)(3.0) - be / ga));\n"
|
|
" }\n"
|
|
"\n"
|
|
" *al1 = s2a + fma(-ba, de1, -ca * ga1);\n"
|
|
" *be1 = de1;\n"
|
|
" }\n"
|
|
" else\n"
|
|
" {\n"
|
|
" if (r >= width3)\n"
|
|
" {\n"
|
|
" *al1 = width * al;\n"
|
|
" *be1 = width * be;\n"
|
|
" }\n"
|
|
" else\n"
|
|
" {\n"
|
|
" *be1 = fma(width1, be, width2 * hb * be / al);\n"
|
|
" *al1 = fma(width1, al, width2 * s2ac * ((real_t)(3.0) - be / al));\n"
|
|
" }\n"
|
|
" }\n"
|
|
" }\n"
|
|
" }\n"
|
|
" else\n"
|
|
" {\n"
|
|
" if (ga < al)\n"
|
|
" {\n"
|
|
" if (r >= width3)\n"
|
|
" {\n"
|
|
" de1 = width * al;\n"
|
|
" ga1 = width * ga;\n"
|
|
" }\n"
|
|
" else\n"
|
|
" {\n"
|
|
" ga1 = fma(width1, ga, width2 * hc * ga / al);\n"
|
|
" de1 = fma(width1, al, width2 * s2ab * ((real_t)(3.0) - ga / al));\n"
|
|
" }\n"
|
|
"\n"
|
|
" *be1 = s2b + fma(-ab, de1, -cb * ga1);\n"
|
|
" *al1 = de1;\n"
|
|
" }\n"
|
|
" else\n"
|
|
" {\n"
|
|
" if (ga < be)\n"
|
|
" {\n"
|
|
" if (r >= width3)\n"
|
|
" {\n"
|
|
" ga1 = width * ga;\n"
|
|
" de1 = width * al;\n"
|
|
" }\n"
|
|
" else\n"
|
|
" {\n"
|
|
" de1 = fma(width1, al, width2 * ha * al / ga);\n"
|
|
" ga1 = fma(width1, ga, width2 * s2bc * ((real_t)(3.0) - al / ga));\n"
|
|
" }\n"
|
|
"\n"
|
|
" *be1 = s2b + fma(-ab, de1, -cb * ga1);\n"
|
|
" *al1 = de1;\n"
|
|
" }\n"
|
|
" else\n"
|
|
" {\n"
|
|
" if (r >= width3)\n"
|
|
" {\n"
|
|
" *be1 = width * be;\n"
|
|
" *al1 = width * al;\n"
|
|
" }\n"
|
|
" else\n"
|
|
" {\n"
|
|
" *al1 = fma(width1, al, width2 * ha * al / be);\n"
|
|
" *be1 = fma(width1, be, width2 * s2bc * ((real_t)(3.0) - al / be));\n"
|
|
" }\n"
|
|
" }\n"
|
|
" }\n"
|
|
" }\n"
|
|
"}\n"
|
|
"\n"
|
|
;
|
|
}
|
|
|
|
virtual void Precalc() override
|
|
{
|
|
T s2, sinA2, cosA2, sinB2, cosB2, sinC2, cosC2;
|
|
T br = T(0.047) + m_A;
|
|
T cr = T(0.047) + m_B;
|
|
T ar = T(M_PI) - br - cr;
|
|
T temp = ar / 2;
|
|
sincos(temp, &sinA2, &cosA2);
|
|
temp = br / 2;
|
|
sincos(temp, &sinB2, &cosB2);
|
|
temp = cr / 2;
|
|
sincos(temp, &sinC2, &cosC2);
|
|
sincos(cr, &m_SinC, &m_CosC);
|
|
T a = m_Radius * (sinC2 / cosC2 + sinB2 / cosB2);
|
|
T b = m_Radius * (sinC2 / cosC2 + sinA2 / cosA2);
|
|
T c = m_Radius * (sinB2 / cosB2 + sinA2 / cosA2);
|
|
m_Width1 = 1 - m_Width;
|
|
m_Width2 = 2 * m_Width;
|
|
m_Width3 = 1 - m_Width * m_Width;
|
|
s2 = m_Radius * (a + b + c);
|
|
m_Ha = s2 / a / 6;
|
|
m_Hb = s2 / b / 6;
|
|
m_Hc = s2 / c / 6;
|
|
m_Ab = a / b;// a div on b
|
|
m_Ac = a / c;
|
|
m_Ba = b / a;
|
|
m_Bc = b / c;
|
|
m_Ca = c / a;
|
|
m_Cb = c / b;
|
|
m_S2a = 6 * m_Ha;
|
|
m_S2b = 6 * m_Hb;
|
|
m_S2c = 6 * m_Hc;
|
|
m_S2bc = s2 / (b + c) / 6;
|
|
m_S2ab = s2 / (a + b) / 6;
|
|
m_S2ac = s2 / (a + c) / 6;
|
|
|
|
if (m_Power == 0)
|
|
m_Power = 2;
|
|
|
|
m_AbsN = T(int(std::abs(m_Power)));
|
|
m_Cn = m_Dist / m_Power / 2;
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.push_back(ParamWithName<T>(&m_Power, prefix + "xtrb_power", 2, eParamType::INTEGER_NONZERO));
|
|
m_Params.push_back(ParamWithName<T>(&m_Radius, prefix + "xtrb_radius", 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_Width, prefix + "xtrb_width", T(0.5)));
|
|
m_Params.push_back(ParamWithName<T>(&m_Dist, prefix + "xtrb_dist", 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_A, prefix + "xtrb_a", 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_B, prefix + "xtrb_b", 1));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_SinC, prefix + "xtrb_sinc"));//Precalcs.
|
|
m_Params.push_back(ParamWithName<T>(true, &m_CosC, prefix + "xtrb_cosc"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Ha, prefix + "xtrb_ha"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Hb, prefix + "xtrb_hb"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Hc, prefix + "xtrb_hc"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Ab, prefix + "xtrb_ab"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Ac, prefix + "xtrb_ac"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Ba, prefix + "xtrb_ba"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Bc, prefix + "xtrb_bc"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Ca, prefix + "xtrb_ca"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Cb, prefix + "xtrb_cb"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_S2a, prefix + "xtrb_s2a"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_S2b, prefix + "xtrb_s2b"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_S2c, prefix + "xtrb_s2c"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_S2ab, prefix + "xtrb_s2ab"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_S2ac, prefix + "xtrb_s2ac"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_S2bc, prefix + "xtrb_s2bc"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Width1, prefix + "xtrb_width1"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Width2, prefix + "xtrb_width2"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Width3, prefix + "xtrb_width3"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_AbsN, prefix + "xtrb_absn"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Cn, prefix + "xtrb_cn"));
|
|
}
|
|
|
|
private:
|
|
inline void DirectTrilinear(T x, T y, T& al, T& be)
|
|
{
|
|
al = y + m_Radius;
|
|
be = x * m_SinC - y * m_CosC + m_Radius;
|
|
}
|
|
|
|
inline void InverseTrilinear(T al, T be, T& x, T& y, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand)
|
|
{
|
|
T inx = (be - m_Radius + (al - m_Radius) * m_CosC) / m_SinC;
|
|
T iny = al - m_Radius;
|
|
T angle = (std::atan2(iny, inx) + M_2PI * (rand.Rand(size_t(m_AbsN)))) / m_Power;
|
|
T r = m_Weight * std::pow(SQR(inx) + SQR(iny), m_Cn);
|
|
x = r * std::cos(angle);
|
|
y = r * std::sin(angle);
|
|
}
|
|
|
|
void Hex(T al, T be, T ga, T& al1, T& be1, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand)
|
|
{
|
|
T ga1, de1, r = rand.Frand01<T>();
|
|
|
|
if (be < al)
|
|
{
|
|
if (ga < be)
|
|
{
|
|
if (r >= m_Width3)
|
|
{
|
|
de1 = m_Width * be;
|
|
ga1 = m_Width * ga;
|
|
}
|
|
else
|
|
{
|
|
ga1 = m_Width1 * ga + m_Width2 * m_Hc * ga / be;
|
|
de1 = m_Width1 * be + m_Width2 * m_S2ab * (3 - ga / be);
|
|
}
|
|
|
|
al1 = m_S2a - m_Ba * de1 - m_Ca * ga1;
|
|
be1 = de1;
|
|
}
|
|
else
|
|
{
|
|
if (ga < al)
|
|
{
|
|
if (r >= m_Width3)
|
|
{
|
|
ga1 = m_Width * ga;
|
|
de1 = m_Width * be;
|
|
}
|
|
else
|
|
{
|
|
de1 = m_Width1 * be + m_Width2 * m_Hb * be / ga;
|
|
ga1 = m_Width1 * ga + m_Width2 * m_S2ac * (3 - be / ga);
|
|
}
|
|
|
|
al1 = m_S2a - m_Ba * de1 - m_Ca * ga1;
|
|
be1 = de1;
|
|
}
|
|
else
|
|
{
|
|
if (r >= m_Width3)
|
|
{
|
|
al1 = m_Width * al;
|
|
be1 = m_Width * be;
|
|
}
|
|
else
|
|
{
|
|
be1 = m_Width1 * be + m_Width2 * m_Hb * be / al;
|
|
al1 = m_Width1 * al + m_Width2 * m_S2ac * (3 - be / al);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ga < al)
|
|
{
|
|
if (r >= m_Width3)
|
|
{
|
|
de1 = m_Width * al;
|
|
ga1 = m_Width * ga;
|
|
}
|
|
else
|
|
{
|
|
ga1 = m_Width1 * ga + m_Width2 * m_Hc * ga / al;
|
|
de1 = m_Width1 * al + m_Width2 * m_S2ab * (3 - ga / al);
|
|
}
|
|
|
|
be1 = m_S2b - m_Ab * de1 - m_Cb * ga1;
|
|
al1 = de1;
|
|
}
|
|
else
|
|
{
|
|
if (ga < be)
|
|
{
|
|
if (r >= m_Width3)
|
|
{
|
|
ga1 = m_Width * ga;
|
|
de1 = m_Width * al;
|
|
}
|
|
else
|
|
{
|
|
de1 = m_Width1 * al + m_Width2 * m_Ha * al / ga;
|
|
ga1 = m_Width1 * ga + m_Width2 * m_S2bc * (3 - al / ga);
|
|
}
|
|
|
|
be1 = m_S2b - m_Ab * de1 - m_Cb * ga1;
|
|
al1 = de1;
|
|
}
|
|
else
|
|
{
|
|
if (r >= m_Width3)
|
|
{
|
|
be1 = m_Width * be;
|
|
al1 = m_Width * al;
|
|
}
|
|
else
|
|
{
|
|
al1 = m_Width1 * al + m_Width2 * m_Ha * al / be;
|
|
be1 = m_Width1 * be + m_Width2 * m_S2bc * (3 - al / be);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
T m_Power;
|
|
T m_Radius;
|
|
T m_Width;
|
|
T m_Dist;
|
|
T m_A;
|
|
T m_B;
|
|
T m_SinC;//Precalcs.
|
|
T m_CosC;
|
|
T m_Ha;
|
|
T m_Hb;
|
|
T m_Hc;
|
|
T m_Ab;
|
|
T m_Ac;
|
|
T m_Ba;
|
|
T m_Bc;
|
|
T m_Ca;
|
|
T m_Cb;
|
|
T m_S2a;
|
|
T m_S2b;
|
|
T m_S2c;
|
|
T m_S2ab;
|
|
T m_S2ac;
|
|
T m_S2bc;
|
|
T m_Width1;
|
|
T m_Width2;
|
|
T m_Width3;
|
|
T m_AbsN;
|
|
T m_Cn;
|
|
};
|
|
|
|
/// <summary>
|
|
/// hexaplay3D.
|
|
/// This uses state and the OpenCL version looks different and better than the CPU.
|
|
/// </summary>
|
|
template <typename T>
|
|
class Hexaplay3DVariation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
Hexaplay3DVariation(T weight = 1.0) : ParametricVariation<T>("hexaplay3D", eVariationId::VAR_HEXAPLAY3D, weight)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(Hexaplay3DVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
if (m_FCycle > 5)
|
|
{
|
|
m_FCycle = 0;
|
|
m_RSwtch = T(rand.RandBit());//Chooses 6 or 3 nodes.
|
|
}
|
|
|
|
if (m_BCycle > 2)
|
|
{
|
|
m_BCycle = 0;
|
|
m_RSwtch = T(rand.RandBit());//Chooses 6 or 3 nodes.
|
|
}
|
|
|
|
T tempx, tempy;
|
|
T sumX, sumY;
|
|
|
|
if (m_VarType == eVariationType::VARTYPE_REG)
|
|
{
|
|
sumX = outPoint.m_X;
|
|
sumY = outPoint.m_Y;
|
|
outPoint.m_X = 0;//Only need to clear regular, pre and post will overwrite by default.
|
|
outPoint.m_Y = 0;
|
|
}
|
|
else
|
|
{
|
|
sumX = helper.In.x;
|
|
sumY = helper.In.y;
|
|
}
|
|
|
|
int posNeg = rand.RandBit() ? -1 : 1;
|
|
|
|
//Creating Z factors relative to the planes. These will be added, whereas x and y will be assigned.
|
|
//Original does += z *, so using z on the right side of = is intentional.
|
|
if (m_MajPlane == 2)
|
|
//Boost is the separation distance between the two planes.
|
|
helper.Out.z = helper.In.z * T(0.5) * m_ZLift + (posNeg * m_Boost);
|
|
else
|
|
helper.Out.z = helper.In.z * T(0.5) * m_ZLift;
|
|
|
|
//Work out the segments and hexagonal nodes.
|
|
if (m_RSwtch)//Occasion to build using 60 degree segments.
|
|
{
|
|
int loc = int(m_FCycle);//Sequential nodes selection.
|
|
tempx = m_Seg60[loc].x;
|
|
tempy = m_Seg60[loc].y;
|
|
m_FCycle++;
|
|
}
|
|
else//Occasion to build on 120 degree segments.
|
|
{
|
|
int loc = int(m_BCycle);//Sequential nodes selection.
|
|
tempx = m_Seg120[loc].x;
|
|
tempy = m_Seg120[loc].y;
|
|
m_BCycle++;
|
|
}
|
|
|
|
helper.Out.x = ((sumX + helper.In.x) * m_HalfScale) + (m_Weight * tempx);
|
|
helper.Out.y = ((sumY + helper.In.y) * m_HalfScale) + (m_Weight * tempy);
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
intmax_t i = 0;
|
|
ss2 << "_" << XformIndexInEmber();
|
|
string weight = WeightDefineString();
|
|
string index = ss2.str() + "]";
|
|
string stateIndex = ss2.str();
|
|
string majp = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string zlift = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string majplane = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string boost = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string seg60xStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 6;//Precalc.
|
|
string seg60yStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 6;
|
|
string seg120xStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 3;
|
|
string seg120yStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 3;
|
|
string halfScale = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string rswtch = "varState->" + m_Params[i++].Name() + stateIndex;//State.
|
|
string fcycle = "varState->" + m_Params[i++].Name() + stateIndex;
|
|
string bcycle = "varState->" + m_Params[i++].Name() + stateIndex;
|
|
ss << "\t{\n"
|
|
<< "\t\tif (" << fcycle << " > 5)\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t " << fcycle << " = 0;\n"
|
|
<< "\t\t " << rswtch << " = (real_t)(MwcNext(mwc) & 1);\n"
|
|
<< "\t\t}\n"
|
|
<< "\n"
|
|
<< "\t\tif (" << bcycle << " > 2)\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t " << bcycle << " = 0;\n"
|
|
<< "\t\t " << rswtch << " = (real_t)(MwcNext(mwc) & 1);\n"
|
|
<< "\t\t}\n"
|
|
<< "\t\t\n"
|
|
<< "\t\treal_t tempx, tempy;\n"
|
|
<< "\t\treal_t sumX, sumY;\n\n";
|
|
|
|
if (m_VarType == eVariationType::VARTYPE_REG)
|
|
{
|
|
ss
|
|
<< "\t\tsumX = outPoint->m_X;\n"
|
|
<< "\t\tsumY = outPoint->m_Y;\n"
|
|
<< "\t\toutPoint->m_X = 0;\n"
|
|
<< "\t\toutPoint->m_Y = 0;\n";
|
|
}
|
|
else
|
|
{
|
|
ss
|
|
<< "\t\tsumX = vIn.x;\n"
|
|
<< "\t\tsumY = vIn.y;\n";
|
|
}
|
|
|
|
ss
|
|
<< "\n"
|
|
<< "\t\tint posNeg = (MwcNext(mwc) & 1) ? -1 : 1;\n"
|
|
<< "\n"
|
|
<< "\t\tif (" << majplane << " == 2)\n"
|
|
<< "\t\t vOut.z = fma(vIn.z * (real_t)(0.5), " << zlift << ", (posNeg * " << boost << "));\n"
|
|
<< "\t\telse\n"
|
|
<< "\t\t vOut.z = vIn.z * 0.5 * " << zlift << ";\n"
|
|
<< "\n"
|
|
<< "\t\tif (" << rswtch << ")\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t int loc = (int)" << fcycle << ";\n"
|
|
<< "\t\t tempx = parVars[" << seg60xStartIndex << " + loc];\n"
|
|
<< "\t\t tempy = parVars[" << seg60yStartIndex << " + loc];\n"
|
|
<< "\t\t " << fcycle << " = " << fcycle << " + 1;\n"
|
|
<< "\t\t}\n"
|
|
<< "\t\telse\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t int loc = (int)" << bcycle << ";\n"
|
|
<< "\t\t tempx = parVars[" << seg120xStartIndex << " + loc];\n"
|
|
<< "\t\t tempy = parVars[" << seg120yStartIndex << " + loc];\n"
|
|
<< "\t\t " << bcycle << " = " << bcycle << " + 1;\n"
|
|
<< "\t\t}\n"
|
|
<< "\n"
|
|
<< "\t\tvOut.x = fma(sumX + vIn.x, " << halfScale << ", " << weight << " * tempx);\n"
|
|
<< "\t\tvOut.y = fma(sumY + vIn.y, " << halfScale << ", " << weight << " * tempy);\n"
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual void InitStateVars(T* t, size_t& index) override
|
|
{
|
|
t[index++] = T(QTIsaac<ISAAC_SIZE, ISAAC_INT>::LockedRandBit());
|
|
t[index++] = 0;
|
|
t[index++] = 0;
|
|
}
|
|
|
|
virtual void Precalc() override
|
|
{
|
|
T hlift = std::sin(T(M_PI) / 3);
|
|
m_RSwtch = std::trunc(QTIsaac<ISAAC_SIZE, ISAAC_INT>::LockedFrand01<T>() * 3);//Chooses 6 or 3 nodes.
|
|
m_FCycle = 0;
|
|
m_BCycle = 0;
|
|
T absmajp = std::abs(m_MajP);
|
|
|
|
if (absmajp <= 1)
|
|
{
|
|
m_MajPlane = 1;//Want either 1 or 2.
|
|
}
|
|
else
|
|
{
|
|
m_MajPlane = 2;
|
|
m_Boost = (absmajp - 1) * T(0.5);//Distance above and below XY plane.
|
|
}
|
|
|
|
m_Seg60[0].x = 1;
|
|
m_Seg60[1].x = T(0.5);
|
|
m_Seg60[2].x = T(-0.5);
|
|
m_Seg60[3].x = -1;
|
|
m_Seg60[4].x = T(-0.5);
|
|
m_Seg60[5].x = T(0.5);
|
|
m_Seg60[0].y = 0;
|
|
m_Seg60[1].y = hlift;
|
|
m_Seg60[2].y = hlift;
|
|
m_Seg60[3].y = 0;
|
|
m_Seg60[4].y = -hlift;
|
|
m_Seg60[5].y = -hlift;
|
|
m_Seg120[0].x = 1;
|
|
m_Seg120[1].x = T(-0.5);
|
|
m_Seg120[2].x = T(-0.5);
|
|
m_Seg120[0].y = 0;
|
|
m_Seg120[1].y = hlift;
|
|
m_Seg120[2].y = -hlift;
|
|
m_HalfScale = m_Scale * T(0.5);
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.reserve(25);
|
|
m_Params.push_back(ParamWithName<T>(&m_MajP, prefix + "hexaplay3D_majp", 1, eParamType::REAL));
|
|
m_Params.push_back(ParamWithName<T>(&m_Scale, prefix + "hexaplay3D_scale", T(0.25), eParamType::REAL));
|
|
m_Params.push_back(ParamWithName<T>(&m_ZLift, prefix + "hexaplay3D_zlift", T(0.25), eParamType::REAL));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_MajPlane, prefix + "hexaplay3D_majplane"));//Precalc.
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Boost, prefix + "hexaplay3D_boost"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[0].x, prefix + "hexaplay3D_seg60x0"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[1].x, prefix + "hexaplay3D_seg60x1"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[2].x, prefix + "hexaplay3D_seg60x2"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[3].x, prefix + "hexaplay3D_seg60x3"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[4].x, prefix + "hexaplay3D_seg60x4"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[5].x, prefix + "hexaplay3D_seg60x5"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[0].y, prefix + "hexaplay3D_seg60y0"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[1].y, prefix + "hexaplay3D_seg60y1"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[2].y, prefix + "hexaplay3D_seg60y2"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[3].y, prefix + "hexaplay3D_seg60y3"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[4].y, prefix + "hexaplay3D_seg60y4"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[5].y, prefix + "hexaplay3D_seg60y5"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg120[0].x, prefix + "hexaplay3D_seg120x0"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg120[1].x, prefix + "hexaplay3D_seg120x1"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg120[2].x, prefix + "hexaplay3D_seg120x2"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg120[0].y, prefix + "hexaplay3D_seg120y0"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg120[1].y, prefix + "hexaplay3D_seg120y1"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg120[2].y, prefix + "hexaplay3D_seg120y2"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_HalfScale, prefix + "hexaplay3D_halfscale"));
|
|
m_Params.push_back(ParamWithName<T>(true, true, &m_RSwtch, prefix + "hexaplay3D_rswtch"));//State.
|
|
m_Params.push_back(ParamWithName<T>(true, true, &m_FCycle, prefix + "hexaplay3D_fcycle"));
|
|
m_Params.push_back(ParamWithName<T>(true, true, &m_BCycle, prefix + "hexaplay3D_bcycle"));
|
|
}
|
|
|
|
private:
|
|
T m_MajP;
|
|
T m_Scale;
|
|
T m_ZLift;
|
|
T m_MajPlane;//Precalc.
|
|
T m_Boost;
|
|
v2T m_Seg60[6];
|
|
v2T m_Seg120[3];
|
|
T m_HalfScale;
|
|
T m_RSwtch;//State.
|
|
T m_FCycle;
|
|
T m_BCycle;
|
|
};
|
|
|
|
/// <summary>
|
|
/// hexnix3D.
|
|
/// This uses state and the OpenCL version looks different and better than the CPU.
|
|
/// It takes care of doing either a sum or product of the output variables internally,
|
|
/// rather than relying on the calling code of Xform::Apply() to do it.
|
|
/// This is because different paths do different things to helper.Out.z
|
|
/// </summary>
|
|
template <typename T>
|
|
class Hexnix3DVariation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
Hexnix3DVariation(T weight = 1.0) : ParametricVariation<T>("hexnix3D", eVariationId::VAR_HEXNIX3D, weight)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(Hexnix3DVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
if (m_FCycle > 5)
|
|
{
|
|
m_FCycle = 0;
|
|
m_RSwtch = T(rand.RandBit());//Chooses 6 or 3 nodes.
|
|
}
|
|
|
|
if (m_BCycle > 2)
|
|
{
|
|
m_BCycle = 0;
|
|
m_RSwtch = T(rand.RandBit());//Chooses 6 or 3 nodes.
|
|
}
|
|
|
|
T smRotxFP = 0;
|
|
T smRotyFP = 0;
|
|
T smRotxFT = 0;
|
|
T smRotyFT = 0;
|
|
T sumX, sumY, sumZ;
|
|
|
|
if (m_VarType == eVariationType::VARTYPE_REG)
|
|
{
|
|
sumX = outPoint.m_X;
|
|
sumY = outPoint.m_Y;
|
|
sumZ = outPoint.m_Z;
|
|
outPoint.m_X = 0;
|
|
outPoint.m_Y = 0;//Z is optionally cleared and assigned to below.
|
|
}
|
|
else
|
|
{
|
|
sumX = helper.In.x;
|
|
sumY = helper.In.y;
|
|
sumZ = helper.In.z;
|
|
}
|
|
|
|
int posNeg = rand.RandBit() ? -1 : 1;
|
|
T scale3;
|
|
T tempx, tempy;
|
|
|
|
if (m_MajPlane == 0)
|
|
{
|
|
helper.Out.z = m_Smooth * helper.In.z * m_Scale * m_ZLift;
|
|
}
|
|
else if (m_MajPlane == 1 && m_MajP < 0)
|
|
{
|
|
if (posNeg < 0)
|
|
helper.Out.z = -2 * (sumZ * m_GentleZ);
|
|
}
|
|
else if (m_MajPlane == 2 && m_MajP < 0)
|
|
{
|
|
if (posNeg > 0)
|
|
{
|
|
helper.Out.z = (m_Smooth * (helper.In.z * m_Scale * m_ZLift + m_Boost));
|
|
}
|
|
else//For this case when reg, assign and zero out. For all others, sum as usual.
|
|
{
|
|
helper.Out.z = (sumZ - (2 * m_Smooth * sumZ)) + (m_Smooth * posNeg * (helper.In.z * m_Scale * m_ZLift + m_Boost));
|
|
|
|
if (m_VarType == eVariationType::VARTYPE_REG)
|
|
outPoint.m_Z = 0;
|
|
}
|
|
}
|
|
else
|
|
helper.Out.z = m_Smooth * (helper.In.z * m_Scale * m_ZLift + (posNeg * m_Boost));
|
|
|
|
if (m_RSwtch)
|
|
{
|
|
auto loc = rand.Rand(6);
|
|
tempx = m_Seg60[loc].x;
|
|
tempy = m_Seg60[loc].y;
|
|
scale3 = 1;
|
|
m_FCycle++;
|
|
}
|
|
else
|
|
{
|
|
auto loc = rand.Rand(3);
|
|
tempx = m_Seg120[loc].x;
|
|
tempy = m_Seg120[loc].y;
|
|
scale3 = m_3side;
|
|
m_BCycle++;
|
|
}
|
|
|
|
smRotxFP = (m_Smooth * m_Scale * sumX * tempx) - (m_Smooth * m_Scale * sumY * tempy);
|
|
smRotyFP = (m_Smooth * m_Scale * sumY * tempx) + (m_Smooth * m_Scale * sumX * tempy);
|
|
smRotxFT = (helper.In.x * m_Smooth * m_Scale * tempx) - (helper.In.y * m_Smooth * m_Scale * tempy);
|
|
smRotyFT = (helper.In.y * m_Smooth * m_Scale * tempx) + (helper.In.x * m_Smooth * m_Scale * tempy);
|
|
helper.Out.x = sumX * (1 - m_Smooth) + smRotxFP + smRotxFT + m_Smooth * m_Weight * scale3 * tempx;
|
|
helper.Out.y = sumY * (1 - m_Smooth) + smRotyFP + smRotyFT + m_Smooth * m_Weight * scale3 * tempy;
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
intmax_t i = 0;
|
|
ss2 << "_" << XformIndexInEmber();
|
|
string weight = WeightDefineString();
|
|
string index = ss2.str() + "]";
|
|
string stateIndex = ss2.str();
|
|
string majp = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string zlift = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string side3 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string smooth = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc.
|
|
string majplane = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string boost = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string gentlez = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string seg60xStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 6;
|
|
string seg60yStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 6;
|
|
string seg120xStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 3;
|
|
string seg120yStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 3;
|
|
string rswtch = "varState->" + m_Params[i++].Name() + stateIndex;//State.
|
|
string fcycle = "varState->" + m_Params[i++].Name() + stateIndex;
|
|
string bcycle = "varState->" + m_Params[i++].Name() + stateIndex;
|
|
ss << "\t{\n"
|
|
<< "\t\tif (" << fcycle << " > 5)\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t " << fcycle << " = 0;\n"
|
|
<< "\t\t " << rswtch << " = (real_t)(MwcNext(mwc) & 1);\n"
|
|
<< "\t\t}\n"
|
|
<< "\n"
|
|
<< "\t\tif (" << bcycle << " > 2)\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t " << bcycle << " = 0;\n"
|
|
<< "\t\t " << rswtch << " = (real_t)(MwcNext(mwc) & 1);\n"
|
|
<< "\t\t}\n"
|
|
<< "\n"
|
|
<< "\t\treal_t scale = " << scale << ";\n"//This is an optimal blend of memory accesses vs. caching to local variables which seems to work best.
|
|
<< "\t\treal_t smooth = " << smooth << ";\n"
|
|
<< "\t\treal_t smRotxFP = 0;\n"
|
|
<< "\t\treal_t smRotyFP = 0;\n"
|
|
<< "\t\treal_t smRotxFT = 0;\n"
|
|
<< "\t\treal_t smRotyFT = 0;\n"
|
|
<< "\t\treal_t sumX, sumY, sumZ;\n\n";
|
|
|
|
if (m_VarType == eVariationType::VARTYPE_REG)
|
|
{
|
|
ss
|
|
<< "\t\tsumX = outPoint->m_X;\n"
|
|
<< "\t\tsumY = outPoint->m_Y;\n"
|
|
<< "\t\tsumZ = outPoint->m_Z;\n"
|
|
<< "\t\toutPoint->m_X = 0;\n"
|
|
<< "\t\toutPoint->m_Y = 0;\n";
|
|
}
|
|
else
|
|
{
|
|
ss
|
|
<< "\t\tsumX = vIn.x;\n"
|
|
<< "\t\tsumY = vIn.y;\n"
|
|
<< "\t\tsumZ = vIn.z;\n";
|
|
}
|
|
|
|
ss
|
|
<< "\n"
|
|
<< "\t\tint posNeg = (MwcNext(mwc) & 1) ? -1 : 1;\n"
|
|
<< "\t\treal_t scale3;\n"
|
|
<< "\t\treal_t tempx, tempy;\n"
|
|
<< "\n"
|
|
<< "\t\tif (" << majplane << " == 0)\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t vOut.z = smooth * vIn.z * scale * " << zlift << ";\n"
|
|
<< "\t\t}\n"
|
|
<< "\t\telse if (" << majplane << " == 1 && " << majp << " < 0)\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t if (posNeg < 0)\n"
|
|
<< "\t\t vOut.z = -2 * (sumZ * " << gentlez << ");\n"
|
|
<< "\t\t}\n"
|
|
<< "\t\telse if (" << majplane << " == 2 && " << majp << " < 0)\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t if (posNeg > 0)\n"
|
|
<< "\t\t {\n"
|
|
<< "\t\t vOut.z = (smooth * fma(vIn.z * scale, " << zlift << ", " << boost << "));\n"
|
|
<< "\t\t }\n"
|
|
<< "\t\t else\n"
|
|
<< "\t\t {\n"
|
|
<< "\t\t vOut.z = fma(smooth * posNeg, fma(vIn.z * scale, " << zlift << ", " << boost << "), sumZ - ((real_t)(2.0) * smooth * sumZ));\n";
|
|
|
|
if (m_VarType == eVariationType::VARTYPE_REG)
|
|
ss << "\t\t outPoint->m_Z = 0;\n";
|
|
|
|
ss
|
|
<< "\t\t }\n"
|
|
<< "\t\t}\n"
|
|
<< "\t\telse\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t vOut.z = smooth * fma(vIn.z * scale, " << zlift << ", (posNeg * " << boost << "));\n"
|
|
<< "\t\t}\n"
|
|
<< "\n"
|
|
<< "\t\tif (" << rswtch << ")\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t uint loc = MwcNextRange(mwc, 6u);\n"
|
|
<< "\t\t tempx = parVars[" << seg60xStartIndex << " + loc];\n"
|
|
<< "\t\t tempy = parVars[" << seg60yStartIndex << " + loc];\n"
|
|
<< "\t\t scale3 = 1;\n"
|
|
<< "\t\t " << fcycle << " = " << fcycle << " + 1;\n"
|
|
<< "\t\t}\n"
|
|
<< "\t\telse\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t uint loc = MwcNextRange(mwc, 3u);\n"
|
|
<< "\t\t tempx = parVars[" << seg120xStartIndex << " + loc];\n"
|
|
<< "\t\t tempy = parVars[" << seg120yStartIndex << " + loc];\n"
|
|
<< "\t\t scale3 = " << side3 << ";\n"
|
|
<< "\t\t " << bcycle << " = " << bcycle << " + 1;\n"
|
|
<< "\t\t}\n"
|
|
<< "\n"
|
|
<< "\t\tsmRotxFP = fma(smooth * scale, sumX * tempx, -(smooth * scale * sumY * tempy));\n"
|
|
<< "\t\tsmRotyFP = fma(smooth * scale, sumY * tempx, (smooth * scale * sumX * tempy));\n"
|
|
<< "\t\tsmRotxFT = fma(vIn.x * smooth, scale * tempx, -(vIn.y * smooth * scale * tempy));\n"
|
|
<< "\t\tsmRotyFT = fma(vIn.y * smooth, scale * tempx, (vIn.x * smooth * scale * tempy));\n"
|
|
<< "\t\tvOut.x = fma(sumX, (1 - smooth), fma(smooth * " << weight << ", scale3 * tempx, smRotxFP + smRotxFT));\n"
|
|
<< "\t\tvOut.y = fma(sumY, (1 - smooth), fma(smooth * " << weight << ", scale3 * tempy, smRotyFP + smRotyFT));\n"
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual void InitStateVars(T* t, size_t& index) override
|
|
{
|
|
t[index++] = T(QTIsaac<ISAAC_SIZE, ISAAC_INT>::LockedRandBit());
|
|
t[index++] = 0;
|
|
t[index++] = 0;
|
|
}
|
|
|
|
virtual void Precalc() override
|
|
{
|
|
T hlift = std::sin(T(M_PI) / 3);
|
|
m_RSwtch = T(QTIsaac<ISAAC_SIZE, ISAAC_INT>::LockedRandBit());// QTIsaac<ISAAC_SIZE, ISAAC_INT>::LockedRand(4);// //std::trunc(QTIsaac<ISAAC_SIZE, ISAAC_INT>::LockedFrand01<T>() * 3);//Chooses 6 or 3 nodes.
|
|
m_FCycle = 0;
|
|
m_BCycle = 0;
|
|
auto absmajp = std::abs(m_MajP);
|
|
|
|
if (absmajp <= 1)
|
|
{
|
|
m_MajPlane = 0;
|
|
m_Boost = 0;
|
|
}
|
|
else if (absmajp > 1 && absmajp < 2)
|
|
{
|
|
m_MajPlane = 1;
|
|
m_Boost = 0;
|
|
}
|
|
else
|
|
{
|
|
m_MajPlane = 2;
|
|
m_Boost = (absmajp - 2) * T(0.5);
|
|
}
|
|
|
|
if (m_MajPlane == 1 && m_MajP < 0)
|
|
{
|
|
if (m_MajP < -1 && m_MajP >= -2)
|
|
m_GentleZ = absmajp - 1;
|
|
else
|
|
m_GentleZ = 1;
|
|
}
|
|
else
|
|
m_GentleZ = 0;
|
|
|
|
if (std::abs(m_Weight) <= T(0.5))
|
|
m_Smooth = m_Weight * 2;
|
|
else
|
|
m_Smooth = 1;
|
|
|
|
m_Seg60[0].x = 1;
|
|
m_Seg60[1].x = T(0.5);
|
|
m_Seg60[2].x = T(-0.5);
|
|
m_Seg60[3].x = -1;
|
|
m_Seg60[4].x = T(-0.5);
|
|
m_Seg60[5].x = T(0.5);
|
|
m_Seg60[0].y = 0;
|
|
m_Seg60[1].y = -hlift;
|
|
m_Seg60[2].y = -hlift;
|
|
m_Seg60[3].y = 0;
|
|
m_Seg60[4].y = hlift;
|
|
m_Seg60[5].y = hlift;
|
|
m_Seg120[0].x = 0;
|
|
m_Seg120[1].x = std::cos(7 * T(M_PI) / 6);
|
|
m_Seg120[2].x = std::cos(11 * T(M_PI) / 6);
|
|
m_Seg120[0].y = -1;
|
|
m_Seg120[1].y = T(0.5);
|
|
m_Seg120[2].y = T(0.5);
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.reserve(25);
|
|
m_Params.push_back(ParamWithName<T>(&m_MajP, prefix + "hexnix3D_majp", 1, eParamType::REAL));
|
|
m_Params.push_back(ParamWithName<T>(&m_Scale, prefix + "hexnix3D_scale", T(0.25), eParamType::REAL));
|
|
m_Params.push_back(ParamWithName<T>(&m_ZLift, prefix + "hexnix3D_zlift"));
|
|
m_Params.push_back(ParamWithName<T>(&m_3side, prefix + "hexnix3D_3side", T(0.667), eParamType::REAL));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Smooth, prefix + "hexnix3D_smooth"));//Precalc.
|
|
m_Params.push_back(ParamWithName<T>(true, &m_MajPlane, prefix + "hexnix3D_majplane"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Boost, prefix + "hexnix3D_boost"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_GentleZ, prefix + "hexnix3D_gentlez"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[0].x, prefix + "hexnix3D_seg60x0"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[1].x, prefix + "hexnix3D_seg60x1"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[2].x, prefix + "hexnix3D_seg60x2"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[3].x, prefix + "hexnix3D_seg60x3"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[4].x, prefix + "hexnix3D_seg60x4"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[5].x, prefix + "hexnix3D_seg60x5"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[0].y, prefix + "hexnix3D_seg60y0"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[1].y, prefix + "hexnix3D_seg60y1"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[2].y, prefix + "hexnix3D_seg60y2"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[3].y, prefix + "hexnix3D_seg60y3"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[4].y, prefix + "hexnix3D_seg60y4"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg60[5].y, prefix + "hexnix3D_seg60y5"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg120[0].x, prefix + "hexnix3D_seg120x0"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg120[1].x, prefix + "hexnix3D_seg120x1"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg120[2].x, prefix + "hexnix3D_seg120x2"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg120[0].y, prefix + "hexnix3D_seg120y0"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg120[1].y, prefix + "hexnix3D_seg120y1"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_Seg120[2].y, prefix + "hexnix3D_seg120y2"));
|
|
m_Params.push_back(ParamWithName<T>(true, true, &m_RSwtch, prefix + "hexnix3D_rswtch"));//State.
|
|
m_Params.push_back(ParamWithName<T>(true, true, &m_FCycle, prefix + "hexnix3D_fcycle"));
|
|
m_Params.push_back(ParamWithName<T>(true, true, &m_BCycle, prefix + "hexnix3D_bcycle"));
|
|
}
|
|
|
|
private:
|
|
T m_MajP;
|
|
T m_Scale;
|
|
T m_ZLift;
|
|
T m_3side;
|
|
T m_Smooth;//Precalc.
|
|
T m_MajPlane;
|
|
T m_Boost;
|
|
T m_GentleZ;
|
|
v2T m_Seg60[6];
|
|
v2T m_Seg120[3];
|
|
T m_RSwtch;//State.
|
|
T m_FCycle;
|
|
T m_BCycle;
|
|
};
|
|
|
|
/// <summary>
|
|
/// hexcrop.
|
|
/// </summary>
|
|
template <typename T>
|
|
class HexcropVariation : public ParametricVariation<T>
|
|
{
|
|
public:
|
|
HexcropVariation(T weight = 1.0) : ParametricVariation<T>("hexcrop", eVariationId::VAR_HEXCROP, weight)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
PARVARCOPY(HexcropVariation)
|
|
|
|
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
|
|
{
|
|
v2T i;
|
|
int c = 0, n = -1, j = 5;
|
|
i.x = helper.In.x + m_CenterX;
|
|
i.y = helper.In.y + m_CenterY;
|
|
|
|
while (++n < 6)
|
|
{
|
|
if ((m_P[n].y <= i.y && i.y < m_P[j].y) || (m_P[j].y <= i.y && i.y < m_P[n].y))
|
|
if (i.x < (m_P[j].x - m_P[n].x) * (i.y - m_P[n].y) / Zeps(m_P[j].y - m_P[n].y) + m_P[n].x)
|
|
c ^= 1;
|
|
|
|
j = n;
|
|
}
|
|
|
|
if (m_VarType == eVariationType::VARTYPE_REG)
|
|
{
|
|
helper.Out.x = c != 0 ? outPoint.m_X + i.x * m_Weight : m_Dropoff;
|
|
helper.Out.y = c != 0 ? outPoint.m_Y + i.y * m_Weight : m_Dropoff;
|
|
outPoint.m_X = 0;
|
|
outPoint.m_Y = 0;
|
|
}
|
|
else
|
|
{
|
|
helper.Out.x = c != 0 ? i.x * m_Weight : m_Dropoff;
|
|
helper.Out.y = c != 0 ? i.y * m_Weight : m_Dropoff;
|
|
}
|
|
|
|
helper.Out.z = m_Weight * helper.In.z;
|
|
}
|
|
|
|
virtual string OpenCLString() const override
|
|
{
|
|
ostringstream ss, ss2;
|
|
intmax_t i = 0;
|
|
ss2 << "_" << XformIndexInEmber();
|
|
string weight = WeightDefineString();
|
|
string index = ss2.str() + "]";
|
|
string stateIndex = ss2.str();
|
|
string scalex = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string scaley = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string centerx = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string centery = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string dropoff = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
|
string pxStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 6;//Precalc.
|
|
string pyStartIndex = ToUpper(m_Params[i].Name()) + stateIndex;
|
|
ss << "\t{\n"
|
|
<< "\t\treal2 i;\n"
|
|
<< "\t\tint c = 0, n = -1, j = 5;\n"
|
|
<< "\n"
|
|
<< "\t\ti.x = vIn.x + " << centerx << ";\n"
|
|
<< "\t\ti.y = vIn.y + " << centery << ";\n"
|
|
<< "\n"
|
|
<< "\t\twhile (++n < 6)\n"
|
|
<< "\t\t{\n"
|
|
<< "\t\t int xjoff = " << pxStartIndex << " + j;\n"
|
|
<< "\t\t int xnoff = " << pxStartIndex << " + n;\n"
|
|
<< "\t\t int yjoff = " << pyStartIndex << " + j;\n"
|
|
<< "\t\t int ynoff = " << pyStartIndex << " + n;\n"
|
|
<< "\n"
|
|
<< "\t\t if ((parVars[ynoff] <= i.y && i.y < parVars[yjoff]) || (parVars[yjoff] <= i.y && i.y < parVars[ynoff]))\n"
|
|
<< "\t\t if (i.x < (parVars[xjoff] - parVars[xnoff]) * (i.y - parVars[ynoff]) / Zeps(parVars[yjoff] - parVars[ynoff]) + parVars[xnoff])\n"
|
|
<< "\t\t c ^= 1;\n"
|
|
<< "\n"
|
|
<< "\t\t j = n;\n"
|
|
<< "\t\t}\n"
|
|
<< "\n";
|
|
|
|
if (m_VarType == eVariationType::VARTYPE_REG)
|
|
{
|
|
ss
|
|
<< "\t\tvOut.x = c != 0 ? fma(i.x, " << weight << ", outPoint->m_X) : " << dropoff << ";\n"
|
|
<< "\t\tvOut.y = c != 0 ? fma(i.y, " << weight << ", outPoint->m_Y) : " << dropoff << ";\n"
|
|
<< "\t\toutPoint->m_X = 0;\n"
|
|
<< "\t\toutPoint->m_Y = 0;\n";
|
|
}
|
|
else
|
|
{
|
|
ss
|
|
<< "\t\tvOut.x = c != 0 ? i.x * " << weight << " : " << dropoff << ";\n"
|
|
<< "\t\tvOut.y = c != 0 ? i.y * " << weight << " : " << dropoff << ";\n";
|
|
}
|
|
|
|
ss
|
|
<< "\t\tvOut.z = " << weight << " * vIn.z;\n"
|
|
<< "\t}\n";
|
|
return ss.str();
|
|
}
|
|
|
|
virtual void Precalc() override
|
|
{
|
|
m_P[0].x = T(-0.5000000000000000000000000000000) * m_ScaleX;
|
|
m_P[0].y = T(1.0606601717798212866012665431573) * m_ScaleY;
|
|
m_P[1].x = T(0.5000000000000000000000000000000) * m_ScaleX;
|
|
m_P[1].y = T(1.0606601717798212866012665431573) * m_ScaleY;
|
|
m_P[2].x = T(1.4142135623730950488016887242097) * m_ScaleX;
|
|
m_P[2].y = T(0.0000000000000000000000000000000) * m_ScaleY;
|
|
m_P[3].x = T(0.5000000000000000000000000000000) * m_ScaleX;
|
|
m_P[3].y = T(-1.0606601717798212866012665431573) * m_ScaleY;
|
|
m_P[4].x = T(-0.5000000000000000000000000000000) * m_ScaleX;
|
|
m_P[4].y = T(-1.0606601717798212866012665431573) * m_ScaleY;
|
|
m_P[5].x = T(-1.4142135623730950488016887242097) * m_ScaleX;
|
|
m_P[5].y = T(0.0000000000000000000000000000000) * m_ScaleY;
|
|
}
|
|
|
|
virtual vector<string> OpenCLGlobalFuncNames() const override
|
|
{
|
|
return vector<string> { "Zeps" };
|
|
}
|
|
|
|
protected:
|
|
void Init()
|
|
{
|
|
string prefix = Prefix();
|
|
m_Params.clear();
|
|
m_Params.reserve(17);
|
|
m_Params.push_back(ParamWithName<T>(&m_ScaleX, prefix + "hexcrop_scale_x", 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_ScaleY, prefix + "hexcrop_scale_y", 1));
|
|
m_Params.push_back(ParamWithName<T>(&m_CenterX, prefix + "hexcrop_center_x"));
|
|
m_Params.push_back(ParamWithName<T>(&m_CenterY, prefix + "hexcrop_center_y"));
|
|
m_Params.push_back(ParamWithName<T>(&m_Dropoff, prefix + "hexcrop_dropoff", T(1E10)));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_P[0].x, prefix + "hexcrop_px0"));//Precalc.
|
|
m_Params.push_back(ParamWithName<T>(true, &m_P[1].x, prefix + "hexcrop_px1"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_P[2].x, prefix + "hexcrop_px2"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_P[3].x, prefix + "hexcrop_px3"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_P[4].x, prefix + "hexcrop_px4"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_P[5].x, prefix + "hexcrop_px5"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_P[0].y, prefix + "hexcrop_py0"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_P[1].y, prefix + "hexcrop_py1"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_P[2].y, prefix + "hexcrop_py2"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_P[3].y, prefix + "hexcrop_py3"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_P[4].y, prefix + "hexcrop_py4"));
|
|
m_Params.push_back(ParamWithName<T>(true, &m_P[5].y, prefix + "hexcrop_py5"));
|
|
}
|
|
|
|
private:
|
|
T m_ScaleX;
|
|
T m_ScaleY;
|
|
T m_CenterX;
|
|
T m_CenterY;
|
|
T m_Dropoff;
|
|
v2T m_P[6];//Precalc.
|
|
};
|
|
|
|
MAKEPREPOSTPARVAR(Bubble2, bubble2, BUBBLE2)
|
|
MAKEPREPOSTPARVAR(CircleLinear, CircleLinear, CIRCLELINEAR)
|
|
MAKEPREPOSTPARVARASSIGN(CircleRand, CircleRand, CIRCLERAND, eVariationAssignType::ASSIGNTYPE_SUM)
|
|
MAKEPREPOSTPARVAR(CircleTrans1, CircleTrans1, CIRCLETRANS1)
|
|
MAKEPREPOSTPARVAR(Cubic3D, cubic3D, CUBIC3D)
|
|
MAKEPREPOSTPARVAR(CubicLattice3D, cubicLattice_3D, CUBIC_LATTICE3D)
|
|
MAKEPREPOSTVAR(Foci3D, foci_3D, FOCI3D)
|
|
MAKEPREPOSTPARVAR(FociP, foci_p, FOCI_P)
|
|
MAKEPREPOSTPARVAR(Ho, ho, HO)
|
|
MAKEPREPOSTPARVAR(Julia3Dq, julia3Dq, JULIA3DQ)
|
|
MAKEPREPOSTPARVARASSIGN(Line, line, LINE, eVariationAssignType::ASSIGNTYPE_SUM)
|
|
MAKEPREPOSTPARVAR(Loonie2, loonie2, LOONIE2)
|
|
MAKEPREPOSTPARVAR(Loonie3, loonie3, LOONIE3)
|
|
MAKEPREPOSTPARVAR(Loonie3D, loonie_3D, LOONIE3D)
|
|
MAKEPREPOSTPARVAR(Mcarpet, mcarpet, MCARPET)
|
|
MAKEPREPOSTPARVAR(Waves23D, waves2_3D, WAVES23D)
|
|
MAKEPREPOSTPARVARASSIGN(Pie3D, pie3D, PIE3D, eVariationAssignType::ASSIGNTYPE_SUM)
|
|
MAKEPREPOSTPARVAR(Popcorn23D, popcorn2_3D, POPCORN23D)
|
|
MAKEPREPOSTVAR(Sinusoidal3D, sinusoidal3D, SINUSOIDAL3D)
|
|
MAKEPREPOSTPARVAR(Scry3D, scry_3D, SCRY3D)
|
|
MAKEPREPOSTPARVAR(Shredlin, shredlin, SHRED_LIN)
|
|
MAKEPREPOSTPARVAR(SplitBrdr, SplitBrdr, SPLIT_BRDR)
|
|
MAKEPREPOSTVAR(Wdisc, wdisc, WDISC)
|
|
MAKEPREPOSTPARVAR(Falloff, falloff, FALLOFF)
|
|
MAKEPREPOSTPARVAR(Falloff2, falloff2, FALLOFF2)
|
|
MAKEPREPOSTPARVAR(Falloff3, falloff3, FALLOFF3)
|
|
MAKEPREPOSTPARVAR(Xtrb, xtrb, XTRB)
|
|
MAKEPREPOSTPARVAR(Hexaplay3D, hexaplay3D, HEXAPLAY3D)
|
|
MAKEPREPOSTPARVAR(Hexnix3D, hexnix3D, HEXNIX3D)
|
|
MAKEPREPOSTPARVAR(Hexcrop, hexcrop, HEXCROP)
|
|
}
|