diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6683e69 --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ +*.user +*.opensdf +*.sdf +*.suo +*.obj +*.tlog +*.def +*.dll +*.manifest +*.exp +*.lastbuildstate +*.lib +*.log +*.map +*.pdb +*.cache +*.res +*.ipch +*.bsc +Builds/MSVC/VS2010/GeneratedFiles/Release/moc_AboutDialog.cpp +*.exe +*.xml +*.ilk +*.wixobj +*.pch +*.txt +*.msi +*.idb +*.flam3 \ No newline at end of file diff --git a/Builds/MSVC/VS2010/Fractorium.sln b/Builds/MSVC/VS2010/Fractorium.sln index 9ca557c..f126860 100644 --- a/Builds/MSVC/VS2010/Fractorium.sln +++ b/Builds/MSVC/VS2010/Fractorium.sln @@ -579,7 +579,6 @@ Global {C8096C47-E358-438C-A520-146D46B0637D}.Release|Mixed Platforms.Build.0 = Release|x86 {C8096C47-E358-438C-A520-146D46B0637D}.Release|Win32.ActiveCfg = Release|x86 {C8096C47-E358-438C-A520-146D46B0637D}.Release|x64.ActiveCfg = Release|x64 - {C8096C47-E358-438C-A520-146D46B0637D}.Release|x64.Build.0 = Release|x64 {C8096C47-E358-438C-A520-146D46B0637D}.Release|x86.ActiveCfg = Release|x86 {C8096C47-E358-438C-A520-146D46B0637D}.Release|x86.Build.0 = Release|x86 {C8096C47-E358-438C-A520-146D46B0637D}.Release-MT|Mixed Platforms.ActiveCfg = Release|x86 diff --git a/Builds/MSVC/VS2010/Fractorium.vcxproj b/Builds/MSVC/VS2010/Fractorium.vcxproj index 65951e9..60f8f23 100644 --- a/Builds/MSVC/VS2010/Fractorium.vcxproj +++ b/Builds/MSVC/VS2010/Fractorium.vcxproj @@ -952,6 +952,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)".\GeneratedFiles\qrc_%(Filename).cpp;%(Outputs) "$(QTDIR)\bin\rcc.exe" -name "%(Filename)" -no-compress "%(FullPath)" -o .\GeneratedFiles\qrc_%(Filename).cpp "$(QTDIR)\bin\rcc.exe" -name "%(Filename)" -no-compress "%(FullPath)" -o .\GeneratedFiles\qrc_%(Filename).cpp + Designer diff --git a/Builds/MSVC/VS2010/FractoriumInstaller/FractoriumInstaller.wixproj b/Builds/MSVC/VS2010/FractoriumInstaller/FractoriumInstaller.wixproj index c74b043..f5273d8 100644 --- a/Builds/MSVC/VS2010/FractoriumInstaller/FractoriumInstaller.wixproj +++ b/Builds/MSVC/VS2010/FractoriumInstaller/FractoriumInstaller.wixproj @@ -6,7 +6,7 @@ 3.7 {c8096c47-e358-438c-a520-146d46b0637d} 2.0 - Fractorium_Beta_0.4.0.4 + Fractorium_Beta_0.4.0.5 Package $(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets diff --git a/Builds/MSVC/VS2010/FractoriumInstaller/Product.wxs b/Builds/MSVC/VS2010/FractoriumInstaller/Product.wxs index 4a6c5b4..64321f9 100644 --- a/Builds/MSVC/VS2010/FractoriumInstaller/Product.wxs +++ b/Builds/MSVC/VS2010/FractoriumInstaller/Product.wxs @@ -1,6 +1,6 @@ - + @@ -13,7 +13,7 @@ - + 1. + Add flatten and unflatten menu items. + Automatically flatten like Apophysis does. + Add plugin and new_linear tags to Xml to be compatible with Apophysis. + +--Bug Fixes + Fix blur, blur3d, bubble, cropn, cross, curl, curl3d, epispiral, ho, julia3d, julia3dz, loonie, mirror_x, mirror_y, mirror_z, rotate_x, sinusoidal, spherical, spherical3d, stripes. + Unique filename on final render was completely broken. + Two severe OpenCL bugs. Random seeds were biased and fusing was being reset too often leading to results that differ from the CPU. + Subtle, but sometimes severe bug in the setup of the xaos weights. + Use properly defined epsilon by getting the value from std::numeric_limits, rather than hard coding 1e-6 or 1e-10. + Omit incorrect usage of epsilon everywhere. It should not be automatically added to denominators. Rather, it should only be used if the denominator is zero. + Force final render progress bars to 100 on completion. Sometimes they didn't seem to make it there. + Make variation name and params comparisons be case insensitive. + +--Code Changes + Make ForEach and FindIf wrappers around std::for_each and std::find_if. + 0.4.0.1 Beta 07/06/2014 --Bug Fixes Fix name collision of mobius and Mobius. The former is treated as mobius_strip. diff --git a/Source/Ember/Ember.cpp b/Source/Ember/Ember.cpp index 61f43af..08a1f8f 100644 --- a/Source/Ember/Ember.cpp +++ b/Source/Ember/Ember.cpp @@ -392,8 +392,9 @@ auto_ptr> QTIsaac::GlobalR bool PaletteList::m_Init = false; \ vector> PaletteList::m_Palettes = vector>(); \ bool XmlToEmber::m_Init = false; \ + vector XmlToEmber::m_FlattenNames = vector(); \ vector> XmlToEmber::m_BadParamNames = vector>(); \ - vector> XmlToEmber::m_BadVariationNames = vector>(); + vector, vector>> XmlToEmber::m_BadVariationNames = vector, vector>>(); EXPORT_SINGLE_TYPE_EMBER(float) diff --git a/Source/Ember/Ember.h b/Source/Ember/Ember.h index d0b2d7e..bb55066 100644 --- a/Source/Ember/Ember.h +++ b/Source/Ember/Ember.h @@ -493,7 +493,7 @@ public: } else if ((projBits & PROJBITS_PITCH) || (projBits & PROJBITS_YAW)) { - if (m_CamYaw != 0) + if (projBits & PROJBITS_YAW) m_ProjFunc = &EmberNs::Ember::ProjectPitchYaw; else m_ProjFunc = &EmberNs::Ember::ProjectPitch; @@ -515,7 +515,7 @@ public: { bool b = false; - std::for_each(m_Xforms.begin(), m_Xforms.end(), [&](Xform& xform) { b |= xform.XaosPresent(); });//If at least one entry is not equal to 1, then xaos is present. + ForEach(m_Xforms, [&](Xform& xform) { b |= xform.XaosPresent(); });//If at least one entry is not equal to 1, then xaos is present. return b; } @@ -525,7 +525,7 @@ public: /// void ClearXaos() { - std::for_each(m_Xforms.begin(), m_Xforms.end(), [&](Xform& xform) { xform.ClearXaos(); }); + ForEach(m_Xforms, [&](Xform& xform) { xform.ClearXaos(); }); } /// @@ -556,7 +556,7 @@ public: { T weight = T(1) / m_Xforms.size(); - std::for_each(m_Xforms.begin(), m_Xforms.end(), [&](Xform& xform) { xform.m_Weight = weight; }); + ForEach(m_Xforms, [&](Xform& xform) { xform.m_Weight = weight; }); } /// @@ -571,8 +571,8 @@ public: if (normalizedWeights.size() != m_Xforms.size()) normalizedWeights.resize(m_Xforms.size()); - std::for_each(m_Xforms.begin(), m_Xforms.end(), [&](Xform& xform) { norm += xform.m_Weight; }); - std::for_each(normalizedWeights.begin(), normalizedWeights.end(), [&](T& weight) { weight = m_Xforms[i].m_Weight / norm; i++; }); + ForEach(m_Xforms, [&](Xform& xform) { norm += xform.m_Weight; }); + ForEach(normalizedWeights, [&](T& weight) { weight = m_Xforms[i].m_Weight / norm; i++; }); } /// @@ -586,7 +586,7 @@ public: unsigned int i = 0, xformIndex = 0, totalVarCount = m_FinalXform.TotalVariationCount(); variations.clear(); - std::for_each(m_Xforms.begin(), m_Xforms.end(), [&](const Xform& xform) { totalVarCount += xform.TotalVariationCount(); }); + ForEach(m_Xforms, [&](const Xform& xform) { totalVarCount += xform.TotalVariationCount(); }); variations.reserve(totalVarCount); while (Xform* xform = GetTotalXform(xformIndex++)) @@ -600,19 +600,52 @@ public: { string tempVarBaseName = tempVar->BaseName(); - if ((std::find_if(variations.begin(), variations.end(), [&] (const Variation* var) -> bool { return tempVar->VariationId() == var->VariationId(); }) == variations.end()) && - (std::find_if(variations.begin(), variations.end(), [&] (const Variation* var) -> bool { return tempVarBaseName == var->BaseName(); }) == variations.end())) + if (!FindIf(variations, [&] (const Variation* var) -> bool { return tempVar->VariationId() == var->VariationId(); }) && + !FindIf(variations, [&] (const Variation* var) -> bool { return tempVarBaseName == var->BaseName(); })) variations.push_back(tempVar); } else { - if (std::find_if(variations.begin(), variations.end(), [&] (const Variation* var) -> bool { return tempVar->VariationId() == var->VariationId(); }) == variations.end()) + if (!FindIf(variations, [&] (const Variation* var) -> bool { return tempVar->VariationId() == var->VariationId(); })) variations.push_back(tempVar); } } } } + /// + /// Flatten all xforms by adding a flatten variation if none is present, and if any of the + /// variations or parameters in the vector are present. + /// + /// Vector of variation and parameter names + /// True if flatten was added to any of the xforms, false if it already was present or if none of the specified variations or parameters were present. + bool Flatten(vector& names) + { + bool flattened = false; + + ForEach(m_Xforms, [&](Xform& xform) { flattened |= xform.Flatten(names); }); + + return flattened; + } + + /// + /// Flatten all xforms by adding a flatten variation in each if not already present. + /// + /// True if flatten was removed, false if it wasn't present. + bool Unflatten() + { + bool unflattened = false; + + ForEach(m_Xforms, [&](Xform& xform) + { + unflattened |= xform.DeleteVariationById(VAR_PRE_FLATTEN); + unflattened |= xform.DeleteVariationById(VAR_FLATTEN); + unflattened |= xform.DeleteVariationById(VAR_POST_FLATTEN); + }); + + return unflattened; + } + /// /// Thin wrapper around Interpolate() which takes a vector of embers rather than a pointer and size. /// All embers are expected to be aligned, including the final xform. If not the behavior is undefined. @@ -1086,7 +1119,7 @@ public: void ProjectZPerspective(Point& point, QTIsaac& rand) { - T zr = 1 - m_CamPerspective * (point.m_Z - m_CamZPos); + T zr = Zeps(1 - m_CamPerspective * (point.m_Z - m_CamZPos)); point.m_X /= zr; point.m_Y /= zr; @@ -1097,7 +1130,7 @@ public: { T z = point.m_Z - m_CamZPos; T y = m_CamMat[1][1] * point.m_Y + m_CamMat[2][1] * z; - T zr = 1 - m_CamPerspective * (m_CamMat[1][2] * point.m_Y + m_CamMat[2][2] * z); + T zr = Zeps(1 - m_CamPerspective * (m_CamMat[1][2] * point.m_Y + m_CamMat[2][2] * z)); point.m_X /= zr; point.m_Y = y / zr; @@ -1113,7 +1146,7 @@ public: z = point.m_Z - m_CamZPos; y = m_CamMat[1][1] * point.m_Y + m_CamMat[2][1] * z; z = m_CamMat[1][2] * point.m_Y + m_CamMat[2][2] * z; - zr = 1 - m_CamPerspective * z; + zr = Zeps(1 - m_CamPerspective * z); sincos(t, &dsin, &dcos); @@ -1134,7 +1167,7 @@ public: z = m_CamMat[0][2] * point.m_X + m_CamMat[1][2] * point.m_Y + m_CamMat[2][2] * z; - T zr = 1 - m_CamPerspective * z; + T zr = Zeps(1 - m_CamPerspective * z); T dr = rand.Frand01() * m_BlurCoef * z; sincos(t, &dsin, &dcos); @@ -1149,7 +1182,7 @@ public: T z = point.m_Z - m_CamZPos; T x = m_CamMat[0][0] * point.m_X + m_CamMat[1][0] * point.m_Y; T y = m_CamMat[0][1] * point.m_X + m_CamMat[1][1] * point.m_Y + m_CamMat[2][1] * z; - T zr = 1 - m_CamPerspective * (m_CamMat[0][2] * point.m_X + m_CamMat[1][2] * point.m_Y + m_CamMat[2][2] * z); + T zr = Zeps(1 - m_CamPerspective * (m_CamMat[0][2] * point.m_X + m_CamMat[1][2] * point.m_Y + m_CamMat[2][2] * z)); point.m_X = x / zr; point.m_Y = y / zr; diff --git a/Source/Ember/EmberDefines.h b/Source/Ember/EmberDefines.h index 2416a9e..28cfbc0 100644 --- a/Source/Ember/EmberDefines.h +++ b/Source/Ember/EmberDefines.h @@ -25,9 +25,9 @@ namespace EmberNs extern void sincos(double x, double *s, double *c); #endif -#define EMBER_VERSION "0.4.0.4" +#define EMBER_VERSION "0.4.0.5" #define EPS6 T(1e-6) -#define EPS T(1e-10)//Apoplugin.h uses -20, but -10 seems to work fine. +#define EPS std::numeric_limits::epsilon()//Apoplugin.h uses -20, but it's more mathematically correct to do it this way. #define ISAAC_SIZE 4 #define MEMALIGN 32 #define DE_THRESH 100 @@ -61,6 +61,7 @@ namespace EmberNs #endif #define DO_DOUBLE 1//Comment this out for shorter build times during development. Always uncomment for release. +//#define ISAAC_FLAM3_DEBUG 1//This is almost never needed, but is very useful when troubleshooting difficult bugs. Enable it to do a side by side comparison with flam3. #define v2T glm::detail::tvec2 #define v3T glm::detail::tvec3 diff --git a/Source/Ember/EmberToXml.h b/Source/Ember/EmberToXml.h index 1365328..766f52f 100644 --- a/Source/Ember/EmberToXml.h +++ b/Source/Ember/EmberToXml.h @@ -128,6 +128,7 @@ public: { unsigned int i, j; ostringstream os; + vector*> variations; os << "* var) { os << var->Name() << (var != variations.back() ? " " : "\""); }); + else + os << "\""; + + os << " new_linear=\"1\""; os << ">\n"; //This is a grey area, what to do about symmetry to avoid duplicating the symmetry xforms when reading back?//TODO//BUG. @@ -455,7 +465,7 @@ private: //os << "color=\"" << xform.m_ColorX << " " << xform.m_ColorY << "\" "; os << "var_color=\"" << xform.m_DirectColor << "\" "; os << "color_speed=\"" << xform.m_ColorSpeed << "\" "; - os << "symmetry=\"" << xform.m_ColorSpeed << "\" ";//Legacy support. + //os << "symmetry=\"" << fabs(xform.m_ColorSpeed - 1) * 2 << "\" ";//Legacy support. string s = xform.m_Name; diff --git a/Source/Ember/Isaac.h b/Source/Ember/Isaac.h index a3c97f6..db3e810 100644 --- a/Source/Ember/Isaac.h +++ b/Source/Ember/Isaac.h @@ -92,7 +92,11 @@ public: /// The next random integer inline T Rand() { +#ifdef ISAAC_FLAM3_DEBUG + return (!m_Rc.randcnt-- ? (Isaac(&m_Rc), m_Rc.randcnt=N-1, m_Rc.randrsl[m_Rc.randcnt]) : m_Rc.randrsl[m_Rc.randcnt]); +#else return (m_Rc.randcnt++ == N ? (Isaac(&m_Rc), m_Rc.randcnt=0, m_Rc.randrsl[m_Rc.randcnt]) : m_Rc.randrsl[m_Rc.randcnt]); +#endif } /// @@ -126,7 +130,11 @@ public: template inline floatType Frand01() { +#ifdef ISAAC_FLAM3_DEBUG + return (Rand() & 0xfffffff) / (floatType)0xfffffff; +#else return Frand(floatType(0), floatType(1)); +#endif } /// @@ -137,7 +145,11 @@ public: template inline floatType Frand11() { +#ifdef ISAAC_FLAM3_DEBUG + return ((Rand() & 0xfffffff) - 0x7ffffff) / (floatType)0x7ffffff; +#else return Frand(floatType(-1), floatType(1)); +#endif } /// @@ -233,7 +245,7 @@ public: } Isaac(ctx); //Fill in the first set of results. - ctx->randcnt = 0;//Prepare to use the first set of results. + ctx->randcnt = N;//TODO//0;//Prepare to use the first set of results. } /// @@ -257,6 +269,7 @@ public: m_Rc.randrsl[i] = s[i]; } +#ifndef ISAAC_FLAM3_DEBUG if (a == 0 && b == 0 && c == 0) { m_Rc.randa = (T)time(0); @@ -264,6 +277,7 @@ public: m_Rc.randc = (T)time(0) * (T)time(0) * (T)time(0); } else +#endif { m_Rc.randa = a; m_Rc.randb = b; diff --git a/Source/Ember/Iterator.h b/Source/Ember/Iterator.h index 9df347b..4accb33 100644 --- a/Source/Ember/Iterator.h +++ b/Source/Ember/Iterator.h @@ -80,7 +80,7 @@ public: /// True if success, else false. bool InitDistributions(Ember& ember) { - unsigned int i, j = 0; + unsigned int i; unsigned int distribCount = ember.XaosPresent() ? (unsigned int)ember.XformCount() + 1 : 1; const Xform* xforms = ember.Xforms(); @@ -101,10 +101,6 @@ public: if (distrib > 0) d *= xforms[distrib - 1].Xaos(i); - - //Original returned false if any xform had 0 density, it's allowed here - //because it can be useful when experimenting to test the effects of removing an - //xform by setting its probability to 0. totalDensity += d; } @@ -114,29 +110,55 @@ public: //only the first xform will get used. //Calculate how much of a fraction of a the total density each element represents. - T densityPerElement = totalDensity / CHOOSE_XFORM_GRAIN; - j = 0; + unsigned int j = 0; + T tempDensity = 0, currentDensityLimit = 0, densityPerElement = totalDensity / CHOOSE_XFORM_GRAIN; //Assign xform indices in order to each element of m_XformDistributions. //The number of elements assigned a given index is proportional to that xform's //density relative to the sum of all densities. for (i = 0; i < ember.XformCount(); i++) { - T tempDensity = 0; - T currentDensityLimit = xforms[i].m_Weight; - + T temp = xforms[i].m_Weight; + if (distrib > 0) - currentDensityLimit *= xforms[distrib - 1].Xaos(i); - + temp *= xforms[distrib - 1].Xaos(i); + + currentDensityLimit += temp; + //Populate points corresponding to this xform's weight/density. //Also check that j is within the bounds of the distribution array just to be safe in the case of a rounding error. - while (tempDensity <= currentDensityLimit && j < CHOOSE_XFORM_GRAIN) + while (tempDensity < currentDensityLimit && j < CHOOSE_XFORM_GRAIN) { + //printf("offset = %d, xform = %d, running sum = %f\n", j, i, tempDensity); m_XformDistributions[(distrib * CHOOSE_XFORM_GRAIN) + j] = i; tempDensity += densityPerElement; j++; } } + + //Flam3 did this, which gives the same result. + //T t = xforms[0].m_Weight; + // + //if (distrib > 0) + // t *= xforms[distrib - 1].Xaos(0); + // + //T r = 0; + // + //for (i = 0; i < CHOOSE_XFORM_GRAIN; i++) + //{ + // while (r >= t) + // { + // j++; + // + // if (distrib > 0) + // t += xforms[j].m_Weight * xforms[distrib - 1].Xaos(j); + // else + // t += xforms[j].m_Weight; + // } + // + // m_XformDistributions[(distrib * CHOOSE_XFORM_GRAIN) + i] = j; + // r += densityPerElement; + //} } return true; @@ -205,6 +227,10 @@ protected: ember.NonConstFinalXform()->Apply(&tempPoint, sample, rand); sample->m_VizAdjusted = tempVizAdjusted; } + else + { + *sample = tempPoint; + } } /// @@ -462,8 +488,8 @@ public: lastXformUsed = xformIndex + 1;//Store the last used transform. } - ember.Proj(p1, rand); samples[0] = p1; + ember.Proj(samples[0], rand); for (i = 1; i < count; i++)//Real loop. { diff --git a/Source/Ember/Renderer.cpp b/Source/Ember/Renderer.cpp index 1fc8229..a92dc18 100644 --- a/Source/Ember/Renderer.cpp +++ b/Source/Ember/Renderer.cpp @@ -1001,10 +1001,13 @@ void Renderer::ThreadCount(unsigned int threads, const char* seedStr if (seedString) { - unsigned int newSize = size + 5; + unsigned int newSize = size + 5 + (unsigned int)(t.Toc() + t.EndTime()); +#ifdef ISAAC_FLAM3_DEBUG + QTIsaac isaac(0, 0, 0, seeds); +#else QTIsaac isaac(newSize, newSize * newSize, newSize * newSize * newSize, seeds); - +#endif m_Rand.push_back(isaac); for (i = 0; i < (isaacSize * sizeof(ISAAC_INT)); i++) @@ -1597,10 +1600,10 @@ EmberStats Renderer::Iterate(unsigned __int64 iterCount, unsigned in //Use first as random point, the rest are iterated points. //Note that this gets reset with a new random point for each subBatchSize iterations. //This helps correct if iteration happens to be on a bad trajectory. - m_Samples[threadIndex][0].m_X = (T)m_Rand[threadIndex].Frand11(); - m_Samples[threadIndex][0].m_Y = (T)m_Rand[threadIndex].Frand11(); + m_Samples[threadIndex][0].m_X = m_Rand[threadIndex].Frand11(); + m_Samples[threadIndex][0].m_Y = m_Rand[threadIndex].Frand11(); m_Samples[threadIndex][0].m_Z = 0;//m_Ember.m_CamZPos;//Apo set this to 0, then made the user use special variations to kick it. It seems easier to just set it to zpos. - m_Samples[threadIndex][0].m_ColorX = (T)m_Rand[threadIndex].Frand01(); + m_Samples[threadIndex][0].m_ColorX = m_Rand[threadIndex].Frand01(); //Finally, iterate. //t.Tic(); diff --git a/Source/Ember/Utils.h b/Source/Ember/Utils.h index fb29df7..8f4ccb5 100644 --- a/Source/Ember/Utils.h +++ b/Source/Ember/Utils.h @@ -8,6 +8,31 @@ /// namespace EmberNs { +/// +/// Thin wrapper around std::find_if() to relieve the caller of having to +/// pass the implicitly obvious .begin() and .end(), and then compare the results to .end(). +/// +/// The container to call find_if() on +/// The lambda to call on each element +/// True if pred returned true once, else false. +template +bool inline FindIf(c& container, pr pred) +{ + return std::find_if(container.begin(), container.end(), pred) != container.end(); +} + +/// +/// Thin wrapper around std::for_each() to relieve the caller of having to +/// pass the implicitly obvious .begin() and .end(). +/// +/// The container to call for_each() on +/// The lambda to call on each element +template +void inline ForEach(c& container, fn func) +{ + std::for_each(container.begin(), container.end(), func); +} + /// /// After a run completes, information about what was run can be saved as strings to the comments /// section of a jpg or png file. This class is just a container for those values. @@ -100,7 +125,7 @@ public: { stringstream ss; - std::for_each(errorReport.begin() , errorReport.end() , [&](string s) { ss << s << endl; }); + ForEach(errorReport, [&](string s) { ss << s << endl; }); return ss.str(); } @@ -515,15 +540,15 @@ static inline T Powq4c(T x, T y) } /// -/// Return EPS6 if the passed in value was zero, else return the value. +/// Return EPS if the passed in value was zero, else return the value. /// /// The value /// The y distance -/// EPS6 or the value if it was non-zero +/// EPS or the value if it was non-zero template static inline T Zeps(T x) { - return x == 0 ? EPS6 : x; + return x == 0 ? EPS : x; } /// diff --git a/Source/Ember/Variation.h b/Source/Ember/Variation.h index 8442f9d..1ea52c3 100644 --- a/Source/Ember/Variation.h +++ b/Source/Ember/Variation.h @@ -1527,7 +1527,7 @@ public: T vd = max(min(val, m_Max), m_Min); if (IsNearZero(vd)) - *m_Param = EPS6 * SignNz(vd); + *m_Param = EPS * SignNz(vd); else *m_Param = vd; @@ -1667,9 +1667,9 @@ public: { bool b = false; - std::for_each(m_Params.begin() , m_Params.end() , [&](ParamWithName& param) + ForEach(m_Params, [&](ParamWithName& param) { - if (!strcmp(param.Name().c_str(), name)) + if (!_stricmp(param.Name().c_str(), name)) b = true; }); @@ -1684,7 +1684,7 @@ public: T* GetParam(const char* name) { for (size_t i = 0; i < m_Params.size(); i++) - if (!strcmp(m_Params[i].Name().c_str(), name)) + if (!_stricmp(m_Params[i].Name().c_str(), name)) return m_Params[i].Param(); return NULL; @@ -1698,7 +1698,7 @@ public: T GetParamVal(const char* name) const { for (size_t i = 0; i < m_Params.size(); i++) - if (!strcmp(m_Params[i].Name().c_str(), name)) + if (!_stricmp(m_Params[i].Name().c_str(), name)) return m_Params[i].ParamVal(); return 0; @@ -1714,9 +1714,9 @@ public: { bool b = false; - std::for_each(m_Params.begin(), m_Params.end(), [&](ParamWithName& param) + ForEach(m_Params, [&](ParamWithName& param) { - if (!strcmp(param.Name().c_str(), name)) + if (!_stricmp(param.Name().c_str(), name)) { param.Set(val); b = true; @@ -1756,7 +1756,7 @@ public: virtual void Random(QTIsaac& rand) { Variation::Random(rand); - std::for_each(m_Params.begin(), m_Params.end(), [&](ParamWithName& param) { param.Set(rand.Frand11()); }); + ForEach(m_Params, [&](ParamWithName& param) { param.Set(rand.Frand11()); }); Precalc(); } @@ -1765,10 +1765,29 @@ public: /// void Clear() { - std::for_each(m_Params.begin(), m_Params.end(), [&](ParamWithName& param) { *(param.Param()) = 0; }); + ForEach(m_Params, [&](ParamWithName& param) { *(param.Param()) = 0; }); Precalc(); } + /// + /// Return a vector of all parameter names, optionally including precalcs. + /// + /// Whether to include the names of precalcs in the returned vector + /// A vector of all parameter names + vector ParamNames(bool includePrecalcs = false) + { + vector vec; + + vec.reserve(m_Params.size()); + ForEach(m_Params, [&](const ParamWithName& param) + { + if ((includePrecalcs && param.IsPrecalc()) || !param.IsPrecalc()) + vec.push_back(param.Name()); + }); + + return vec; + } + /// /// Return the name, weight and parameters of the variation as a string. /// @@ -1778,7 +1797,7 @@ public: ostringstream ss; ss << Variation::ToString() << endl; - std::for_each(m_Params.begin(), m_Params.end(), [&](const ParamWithName& param) { ss << param.ToString() << endl; }); + ForEach(m_Params, [&](const ParamWithName& param) { ss << param.ToString() << endl; }); return ss.str(); } diff --git a/Source/Ember/VariationList.h b/Source/Ember/VariationList.h index 36e408e..951e0c0 100644 --- a/Source/Ember/VariationList.h +++ b/Source/Ember/VariationList.h @@ -342,16 +342,16 @@ public: ADDPREPOSTREGVAR(DCTriangle) ADDPREPOSTREGVAR(DCZTransl) - std::for_each(m_Variations.begin(), m_Variations.end(), [&](Variation* var) { var->Precalc(); }); + ForEach(m_Variations, [&](Variation* var) { var->Precalc(); }); std::sort(m_Variations.begin(), m_Variations.end(), [&](const Variation* var1, const Variation* var2) { return var1->VariationId() < var2->VariationId(); }); m_RegVariations.reserve(m_Variations.size() / 3); m_PreVariations.reserve(m_Variations.size() / 3); m_PostVariations.reserve(m_Variations.size() / 3); - std::for_each(m_Variations.begin(), m_Variations.end(), [&](Variation* var) { if (var->VarType() == VARTYPE_REG) m_RegVariations.push_back(var); }); - std::for_each(m_Variations.begin(), m_Variations.end(), [&](Variation* var) { if (var->VarType() == VARTYPE_PRE) m_PreVariations.push_back(var); }); - std::for_each(m_Variations.begin(), m_Variations.end(), [&](Variation* var) { if (var->VarType() == VARTYPE_POST) m_PostVariations.push_back(var); }); + ForEach(m_Variations, [&](Variation* var) { if (var->VarType() == VARTYPE_REG) m_RegVariations.push_back(var); }); + ForEach(m_Variations, [&](Variation* var) { if (var->VarType() == VARTYPE_PRE) m_PreVariations.push_back(var); }); + ForEach(m_Variations, [&](Variation* var) { if (var->VarType() == VARTYPE_POST) m_PostVariations.push_back(var); }); //Keep a list of which variations derive from ParametricVariation. //Note that these are not new copies, rather just pointers to the original instances in m_Variations. @@ -436,7 +436,7 @@ public: Variation* GetVariation(string name) { for (unsigned int i = 0; i < m_Variations.size() && m_Variations[i] != NULL; i++) - if (name == m_Variations[i]->Name()) + if (!_stricmp(name.c_str(), m_Variations[i]->Name().c_str())) return m_Variations[i]; return NULL; @@ -467,7 +467,7 @@ public: ParametricVariation* GetParametricVariation(string name) { for (unsigned int i = 0; i < m_ParametricVariations.size() && m_ParametricVariations[i] != NULL; i++) - if (name == m_ParametricVariations[i]->Name()) + if (!_stricmp(name.c_str(), m_ParametricVariations[i]->Name().c_str())) return m_ParametricVariations[i]; return NULL; @@ -481,7 +481,7 @@ public: int GetVariationIndex(string name) { for (unsigned int i = 0; i < m_Variations.size() && m_Variations[i] != NULL; i++) - if (name == m_Variations[i]->Name()) + if (!_stricmp(name.c_str(), m_Variations[i]->Name().c_str())) return i; return -1; diff --git a/Source/Ember/Variations01.h b/Source/Ember/Variations01.h index 22da9d3..87c580d 100644 --- a/Source/Ember/Variations01.h +++ b/Source/Ember/Variations01.h @@ -29,7 +29,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x;\n" @@ -60,16 +60,18 @@ public: { helper.Out.x = m_Weight * sin(helper.In.x); helper.Out.y = m_Weight * sin(helper.In.y); + helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * sin(vIn.x);\n" << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * sin(vIn.y);\n" + << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n" << "\t}\n"; return ss.str(); @@ -94,22 +96,24 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T r2 = m_Weight / (helper.m_PrecalcSumSquares + EPS6); + T r2 = m_Weight / Zeps(helper.m_PrecalcSumSquares); helper.Out.x = r2 * helper.In.x; helper.Out.y = r2 * helper.In.y; + helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" - << "\t\treal_t r2 = xform->m_VariationWeights[" << varIndex << "] / (precalcSumSquares + EPS6);\n" + << "\t\treal_t r2 = xform->m_VariationWeights[" << varIndex << "] / Zeps(precalcSumSquares);\n" << "\n" << "\t\tvOut.x = r2 * vIn.x;\n" << "\t\tvOut.y = r2 * vIn.y;\n" + << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n" << "\t}\n"; return ss.str(); @@ -147,7 +151,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t c1 = sin(precalcSumSquares);\n" @@ -182,7 +186,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T r = m_Weight / (helper.m_PrecalcSqrtSumSquares + T(EPS)); + T r = m_Weight / Zeps(helper.m_PrecalcSqrtSumSquares); helper.Out.x = (helper.In.x - helper.In.y) * (helper.In.x + helper.In.y) * r; helper.Out.y = 2 * helper.In.x * helper.In.y * r; @@ -192,10 +196,10 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" - << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] / (precalcSqrtSumSquares + EPS);\n" + << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] / Zeps(precalcSqrtSumSquares);\n" << "\n" << "\t\tvOut.x = (vIn.x - vIn.y) * (vIn.x + vIn.y) * r;\n" << "\t\tvOut.y = 2.0 * vIn.x * vIn.y * r;\n" @@ -223,22 +227,19 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T nx = helper.m_PrecalcAtanxy * T(M_1_PI); - T ny = helper.m_PrecalcSqrtSumSquares - 1; - - helper.Out.x = m_Weight * nx; - helper.Out.y = m_Weight * ny; + helper.Out.x = m_Weight * (helper.m_PrecalcAtanxy * T(M_1_PI)); + helper.Out.y = m_Weight * (helper.m_PrecalcSqrtSumSquares - 1); helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" - << "\t\tvOut.x = (xform->m_VariationWeights[" << varIndex << "] * (precalcAtanxy * M_1_PI));\n" - << "\t\tvOut.y = (xform->m_VariationWeights[" << varIndex << "] * (precalcSqrtSumSquares - 1.0));\n" + << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (precalcAtanxy * M_1_PI);\n" + << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * (precalcSqrtSumSquares - 1.0);\n" << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n" << "\t}\n"; @@ -271,7 +272,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * precalcSqrtSumSquares * sin(precalcAtanxy + precalcSqrtSumSquares);\n" @@ -312,7 +313,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t a = precalcSqrtSumSquares * precalcAtanxy;\n" @@ -412,7 +413,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T r = helper.m_PrecalcSqrtSumSquares + T(EPS); + T r = Zeps(helper.m_PrecalcSqrtSumSquares); T r1 = m_Weight / r; helper.Out.x = r1 * (helper.m_PrecalcCosa + sin(r)); @@ -423,10 +424,10 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" - << "\t\treal_t r = precalcSqrtSumSquares + EPS;\n" + << "\t\treal_t r = Zeps(precalcSqrtSumSquares);\n" << "\t\treal_t r1 = xform->m_VariationWeights[" << varIndex << "] / r;\n" << "\n" << "\t\tvOut.x = r1 * (precalcCosa + sin(r));\n" @@ -455,7 +456,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T r = helper.m_PrecalcSqrtSumSquares + T(EPS); + T r = Zeps(helper.m_PrecalcSqrtSumSquares); helper.Out.x = m_Weight * helper.m_PrecalcSina / r; helper.Out.y = m_Weight * helper.m_PrecalcCosa * r; @@ -465,10 +466,10 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" - << "\t\treal_t r = precalcSqrtSumSquares + EPS;\n" + << "\t\treal_t r = Zeps(precalcSqrtSumSquares);\n" << "\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * precalcSina / r;\n" << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * precalcCosa * r;\n" @@ -504,7 +505,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * precalcSina * cos(precalcSqrtSumSquares);\n" @@ -552,7 +553,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t a = precalcAtanxy;\n" @@ -605,7 +606,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] * sqrt(precalcSqrtSumSquares);\n" @@ -653,7 +654,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t nx = vIn.x < 0.0 ? (vIn.x * 2.0) : vIn.x;\n" @@ -731,8 +732,8 @@ public: T dx = m_Xform->m_Affine.C(); T dy = m_Xform->m_Affine.F(); - m_Dx2 = 1 / (dx * dx + T(EPS)); - m_Dy2 = 1 / (dy * dy + T(EPS)); + m_Dx2 = 1 / Zeps(dx * dx); + m_Dy2 = 1 / Zeps(dy * dy); } } @@ -781,7 +782,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r = 2 * xform->m_VariationWeights[" << varIndex << "] / (precalcSqrtSumSquares + 1);\n" @@ -827,7 +828,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t dx = tan(3 * vIn.y);\n" @@ -874,7 +875,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t dx = xform->m_VariationWeights[" << varIndex << "] * exp(vIn.x - 1.0);\n" @@ -920,7 +921,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] * pow(precalcSqrtSumSquares, precalcSina);\n" @@ -963,7 +964,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t a = vIn.x * M_PI;\n" @@ -1001,7 +1002,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T dx = m_Xform->m_Affine.C() * m_Xform->m_Affine.C() + T(EPS); + T dx = Zeps(m_Xform->m_Affine.C() * m_Xform->m_Affine.C()); T r = helper.m_PrecalcSqrtSumSquares; r = m_Weight * (fmod(r + dx, 2 * dx) - dx + r * (1 - dx)); @@ -1013,10 +1014,10 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" - << "\t\treal_t dx = xform->m_C * xform->m_C + EPS;\n" + << "\t\treal_t dx = Zeps(xform->m_C * xform->m_C);\n" << "\t\treal_t r = precalcSqrtSumSquares;\n" << "\n" << "\t\tr = xform->m_VariationWeights[" << varIndex << "] * (fmod(r + dx, 2 * dx) - dx + r * (1 - dx));\n" @@ -1053,7 +1054,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T dx = T(M_PI) * (m_Xform->m_Affine.C() * m_Xform->m_Affine.C() + T(EPS)); + T dx = T(M_PI) * Zeps(m_Xform->m_Affine.C() * m_Xform->m_Affine.C()); T dy = m_Xform->m_Affine.F(); T dx2 = T(0.5) * dx; T a = helper.m_PrecalcAtanxy; @@ -1068,10 +1069,10 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" - << "\t\treal_t dx = M_PI * (xform->m_C * xform->m_C + EPS);\n" + << "\t\treal_t dx = M_PI * Zeps(xform->m_C * xform->m_C);\n" << "\t\treal_t dy = xform->m_F;\n" << "\t\treal_t dx2 = 0.5 * dx;\n" << "\t\treal_t a = precalcAtanxy + ((fmod(precalcAtanxy + dy, dx) > dx2) ? -dx2 : dx2);\n" @@ -1114,6 +1115,7 @@ public: helper.Out.x = m_Weight * helper.m_PrecalcSina * r; helper.Out.y = m_Weight * helper.m_PrecalcCosa * r; + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -1132,6 +1134,7 @@ public: << "\n" << "\t\tvOut.x = (xform->m_VariationWeights[" << varIndex << "] * precalcSina * r);\n" << "\t\tvOut.y = (xform->m_VariationWeights[" << varIndex << "] * precalcCosa * r);\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -1333,7 +1336,7 @@ public: virtual void Precalc() { - m_Fan2Dx = T(M_PI) * (SQR(m_Fan2X) + EPS); + m_Fan2Dx = T(M_PI) * Zeps(SQR(m_Fan2X)); m_Fan2Dx2 = T(0.5) * m_Fan2Dx; } @@ -1416,7 +1419,7 @@ public: virtual void Precalc() { - m_Rings2Val2 = SQR(m_Rings2Val) + EPS; + m_Rings2Val2 = Zeps(SQR(m_Rings2Val)); } virtual void Random(QTIsaac& rand) @@ -1465,7 +1468,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r = (xform->m_VariationWeights[" << varIndex << "] * 2.0) / (precalcSqrtSumSquares + 1.0);\n" @@ -1492,24 +1495,26 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T r = m_Weight / (T(0.25) * helper.m_PrecalcSumSquares + 1); + T denom = T(0.25) * helper.m_PrecalcSumSquares + 1; + T r = m_Weight / denom; helper.Out.x = r * helper.In.x; helper.Out.y = r * helper.In.y; - helper.Out.z = m_Weight * helper.In.z; + helper.Out.z = m_Weight * (2 / denom - 1); } virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" - << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] / (0.25 * precalcSumSquares + 1);\n" + << "\t\treal_t denom = 0.25 * precalcSumSquares + 1;\n" + << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] / denom;\n" << "\n" << "\t\tvOut.x = r * vIn.x;\n" << "\t\tvOut.y = r * vIn.y;\n" - << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n" + << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * (2 / denom - 1);\n" << "\t}\n"; return ss.str(); @@ -1537,7 +1542,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * sin(vIn.x);\n" @@ -1565,11 +1570,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T d = m_Dist - helper.In.y * m_Vsin; - - if (d == 0) - d = EPS6; - + T d = Zeps(m_Dist - helper.In.y * m_Vsin); T t = 1 / d; helper.Out.x = m_Weight * m_Dist * helper.In.x * t; @@ -1589,11 +1590,7 @@ public: string vfCos = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" - << "\t\treal_t d = " << dist << " - vIn.y * " << vSin << ";\n" - << "\n" - << "\t\tif (d == 0)\n" - << "\t\t d = EPS6;\n" - << "\n" + << "\t\treal_t d = Zeps(" << dist << " - vIn.y * " << vSin << ");\n" << "\t\treal_t t = 1.0 / d;\n" << "\n" << "\t\tvOut.x = (xform->m_VariationWeights[" << varIndex << "] * " << dist << " * vIn.x * t);\n" @@ -1661,7 +1658,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t tempr = MwcNext01(mwc) * M_2PI;\n" @@ -1726,6 +1723,7 @@ public: virtual void Precalc() { + m_Power = Zeps(m_Power); m_Rn = fabs(m_Power); m_Cn = m_Dist / m_Power / 2; } @@ -1877,6 +1875,9 @@ private: /// /// Blur. +/// This is somewhat different than the original functionality in that blur used +/// the code below, but pre_blur used gaussian_blur. +/// If the original pre_blur functionality is needed, use pre_gaussian_blur. /// template class EMBER_API BlurVariation : public Variation @@ -1889,8 +1890,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { T tempr = rand.Frand01() * M_2PI; - T r = m_Weight * (rand.Frand01() + rand.Frand01() - + rand.Frand01() + rand.Frand01() - 2); + T r = m_Weight * rand.Frand01(); helper.Out.x = r * cos(tempr); helper.Out.y = r * sin(tempr); @@ -1900,7 +1900,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t tmpr = MwcNext01(mwc) * M_2PI;\n" @@ -1939,7 +1939,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t angle = MwcNext01(mwc) * M_2PI;\n" @@ -2122,19 +2122,22 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T rFactor = pow(helper.m_PrecalcSumSquares, m_Power / 2); - T theta = helper.m_PrecalcAtanyx; - T b = M_2PI / m_Sides; - T amp, phi = theta - (b * Floor(theta / b)); + T rFactor; - if (phi > b / 2) - phi -= b; + if ((helper.In.x == 0) && (helper.In.y == 0)) + rFactor = 0; + else + rFactor = pow(helper.m_PrecalcSumSquares, m_CPower); - amp = m_Corners * (1 / (cos(phi) + EPS) - 1) + m_Circle; - amp /= (rFactor + T(EPS)); + T phi = helper.m_PrecalcAtanyx - m_CSides * Floor(helper.m_PrecalcAtanyx * m_CSidesInv); + + if (phi > T(0.5) * m_CSides) + phi -= m_CSides; - helper.Out.x = m_Weight * helper.In.x * amp; - helper.Out.y = m_Weight * helper.In.y * amp; + T amp = (m_Corners * (1 / cos(phi) - 1) + m_Circle) * m_Weight * rFactor; + + helper.Out.x = amp * helper.In.x; + helper.Out.y = amp * helper.In.y; helper.Out.z = m_Weight * helper.In.z; } @@ -2144,30 +2147,44 @@ public: int i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); - string sides = "parVars[" + ToUpper(m_Params[i++].Name()) + index; - string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; - string circle = "parVars[" + ToUpper(m_Params[i++].Name()) + index; - string corners = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string sides = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string circle = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string corners = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string csides = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string csidesinv = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string cpower = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" - << "\t\treal_t rFactor = pow(precalcSumSquares, " << power << " / 2.0);\n" - << "\t\treal_t theta = precalcAtanyx;\n" - << "\t\treal_t b = M_2PI / " << sides << ";\n" - << "\t\treal_t amp, phi = theta - (b * floor(theta / b));\n" + << "\t\treal_t rFactor;\n" << "\n" - << "\t\tif (phi > b / 2)\n" - << "\t\t phi -= b;\n" + << "\t\tif ((vIn.x == 0.0) && (vIn.y == 0.0))\n" + << "\t\t rFactor = 0.0;\n" + << "\t\telse\n" + << "\t\t rFactor = pow(precalcSumSquares, " << cpower << ");\n" << "\n" - << "\t\tamp = " << corners << " * (1.0 / (cos(phi) + EPS) - 1.0) + " << circle << ";\n" - << "\t\tamp /= (rFactor + EPS);\n" - << "\t\tvOut.x = (xform->m_VariationWeights[" << varIndex << "] * vIn.x * amp);\n" - << "\t\tvOut.y = (xform->m_VariationWeights[" << varIndex << "] * vIn.y * amp);\n" + << "\t\treal_t phi = precalcAtanyx - " << csides << " * floor(precalcAtanyx * " << csidesinv << ");\n" + << "\n" + << "\t\tif (phi > 0.5 * " << csides << ")\n" + << "\t\t phi -= " << csides << ";\n" + << "\n" + << "\t\treal_t amp = (" << corners << " * (1 / cos(phi) - 1) + " << circle << ") * xform->m_VariationWeights[" << varIndex << "] * rFactor;\n" + << "\n" + << "\t\tvOut.x = amp * vIn.x;\n" + << "\t\tvOut.y = amp * vIn.y;\n" << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n" << "\t}\n"; return ss.str(); } + virtual void Precalc() + { + m_CPower = -T(0.5) * m_Power; + m_CSides = 2 * T(M_PI) / m_Sides; + m_CSidesInv = 1 / m_CSides; + } + virtual void Random(QTIsaac& rand) { m_Sides = (T)(int)(rand.Frand01() * 10 + 3); @@ -2186,6 +2203,9 @@ protected: m_Params.push_back(ParamWithName(&m_Power, prefix + "ngon_power", 3)); m_Params.push_back(ParamWithName(&m_Circle, prefix + "ngon_circle", 1)); m_Params.push_back(ParamWithName(&m_Corners, prefix + "ngon_corners", 2)); + m_Params.push_back(ParamWithName(true, &m_CSides, prefix + "ngon_csides")); + m_Params.push_back(ParamWithName(true, &m_CSidesInv, prefix + "ngon_csides_inv")); + m_Params.push_back(ParamWithName(true, &m_CPower, prefix + "ngon_cpower")); } private: @@ -2193,10 +2213,16 @@ private: T m_Power; T m_Circle; T m_Corners; + T m_CSides; + T m_CSidesInv; + T m_CPower; }; /// /// Curl. +/// Note that in Apophysis, curl and post_curl differed slightly. +/// Using what post_curl did here gave bad results, so sticking with the original +/// curl code. /// template class EMBER_API CurlVariation : public ParametricVariation @@ -2211,15 +2237,12 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T re = 1 + m_C1w * helper.In.x + m_C2w * (SQR(helper.In.x) - SQR(helper.In.y));//Optimized from PostCurl. - T im = m_C1w * helper.In.y + m_C22 * helper.In.x * helper.In.y; - T r = SQR(re) + SQR(im); + T re = 1 + m_C1 * helper.In.x + m_C2 * (SQR(helper.In.x) - SQR(helper.In.y)); + T im = m_C1 * helper.In.y + m_C22 * helper.In.x * helper.In.y; + T r = m_Weight / Zeps(SQR(re) + SQR(im)); - if (r == 0) - r = EPS6; - - helper.Out.x = (helper.In.x * re + helper.In.y * im) / r; - helper.Out.y = (helper.In.y * re - helper.In.x * im) / r; + helper.Out.x = (helper.In.x * re + helper.In.y * im) * r; + helper.Out.y = (helper.In.y * re - helper.In.x * im) * r; helper.Out.z = m_Weight * helper.In.z; } @@ -2231,22 +2254,15 @@ public: string index = ss2.str(); string c1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string c2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; - string c1w = "parVars[" + ToUpper(m_Params[i++].Name()) + index; - string c2w = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string c22 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" - << "\t\treal_t x = vIn.x;\n" - << "\t\treal_t y = vIn.y;\n" - << "\t\treal_t re = 1 + " << c1w << " * x + " << c2w << " * (SQR(x) - SQR(y));\n" - << "\t\treal_t im = " << c1w << " * y + " << c22 << " * x * y;\n" - << "\t\treal_t r = SQR(re) + SQR(im);\n" + << "\t\treal_t re = 1.0 + " << c1 << " * vIn.x + " << c2 << " * (SQR(vIn.x) - SQR(vIn.y));\n" + << "\t\treal_t im = " << c1 << " * vIn.y + " << c22 << " * vIn.x * vIn.y;\n" + << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] / Zeps(SQR(re) + SQR(im));\n" << "\n" - << "\t\tif (r == 0)\n" - << "\t\t r = EPS6;\n" - << "\n" - << "\t\tvOut.x = (x * re + y * im) / r;\n" - << "\t\tvOut.y = (y * re - x * im) / r;\n" + << "\t\tvOut.x = (vIn.x * re + vIn.y * im) * r;\n" + << "\t\tvOut.y = (vIn.y * re - vIn.x * im) * r;\n" << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n" << "\t}\n"; @@ -2255,9 +2271,7 @@ public: virtual void Precalc() { - m_C1w = m_C1 * m_Weight; - m_C2w = m_C2 * m_Weight; - m_C22 = 2 * m_C2w; + m_C22 = 2 * m_C2; } virtual void Random(QTIsaac& rand) @@ -2274,17 +2288,13 @@ protected: m_Params.clear(); m_Params.push_back(ParamWithName(&m_C1, prefix + "curl_c1", 1)); m_Params.push_back(ParamWithName(&m_C2, prefix + "curl_c2")); - m_Params.push_back(ParamWithName(true, &m_C1w, prefix + "curl_c1w"));//Precalc. - m_Params.push_back(ParamWithName(true, &m_C2w, prefix + "curl_c2w")); - m_Params.push_back(ParamWithName(true, &m_C22, prefix + "curl_c22")); + m_Params.push_back(ParamWithName(true, &m_C22, prefix + "curl_c22"));//Precalc. } private: T m_C1; T m_C2; - T m_C1w;//Precalc. - T m_C2w; - T m_C22; + T m_C22;//Precalc. }; /// @@ -2388,7 +2398,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t angle = MwcNext01(mwc) * xform->m_VariationWeights[" << varIndex << "] * M_PI;\n" @@ -2425,7 +2435,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * sin(vIn.x) / cos(vIn.y);\n" @@ -2458,7 +2468,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (MwcNext01(mwc) - 0.5);\n" @@ -2484,7 +2494,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { T ang = m_Weight * rand.Frand01() * T(M_PI); - T r = m_Weight / (helper.m_PrecalcSumSquares + T(EPS)); + T r = m_Weight / Zeps(helper.m_PrecalcSumSquares); T tanr = m_Weight * tan(ang) * r; helper.Out.x = tanr * cos(helper.In.x); @@ -2495,11 +2505,11 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t ang = xform->m_VariationWeights[" << varIndex << "] * MwcNext01(mwc) * M_PI;\n" - << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] / (precalcSumSquares + EPS);\n" + << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] / Zeps(precalcSumSquares);\n" << "\t\treal_t tanr = xform->m_VariationWeights[" << varIndex << "] * tan(ang) * r;\n" << "\n" << "\t\tvOut.x = tanr * cos(vIn.x);\n" @@ -2530,12 +2540,13 @@ public: sincos(r, &sinr, &cosr); helper.Out.x = m_Weight * helper.In.x * (cosr + sinr); helper.Out.y = m_Weight * helper.In.x * (cosr - sinr); + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r = MwcNext01(mwc) * xform->m_VariationWeights[" << varIndex << "] * precalcSqrtSumSquares;\n" @@ -2544,6 +2555,7 @@ public: << "\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x * (cosr + sinr);\n" << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * vIn.x * (cosr - sinr);\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -2580,7 +2592,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] * precalcSqrtSumSquares;\n" @@ -2631,7 +2643,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r = MwcNext01(mwc) * xform->m_VariationWeights[" << varIndex << "] * precalcSqrtSumSquares;\n" @@ -2664,9 +2676,8 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T s = helper.In.x * helper.In.x - helper.In.y * helper.In.y; - T r = m_Weight * sqrt(1 / (s * s + EPS)); - + T r = m_Weight / Zeps(fabs((helper.In.x - helper.In.y) * (helper.In.x + helper.In.y))); + helper.Out.x = helper.In.x * r; helper.Out.y = helper.In.y * r; helper.Out.z = m_Weight * helper.In.z; @@ -2675,11 +2686,10 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" - << "\t\treal_t s = vIn.x * vIn.x - vIn.y * vIn.y;\n" - << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] * sqrt(1.0 / (s * s + EPS));\n" + << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] /Zeps(fabs((vIn.x - vIn.y) * (vIn.x + vIn.y)));\n" << "\n" << "\t\tvOut.x = vIn.x * r;\n" << "\t\tvOut.y = vIn.y * r;\n" @@ -3201,18 +3211,18 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T x2y2 = helper.m_PrecalcSumSquares; - T t = x2y2 + 1; - T x2 = 2 * helper.In.x; + const T x2y2 = helper.m_PrecalcSumSquares; + const T t = x2y2 + 1; + const T x2 = 2 * helper.In.x; T y = T(0.5) * atan2(2 * helper.In.y, x2y2 - 1) + m_S; if (y > T(M_PI_2)) - y = T(-M_PI_2) + fmod(y + T(M_PI_2), T(M_PI)); - else if (y < T(-M_PI_2)) + y = -T(M_PI_2) + fmod(y + T(M_PI_2), T(M_PI)); + else if (y < -T(M_PI_2)) y = T(M_PI_2) - fmod(T(M_PI_2) - y, T(M_PI)); - T f = t + x2; - T g = t - x2; + const T f = t + x2; + const T g = t - x2; if ((g == 0) || (f / g <= 0)) { @@ -3296,7 +3306,7 @@ public: virtual void Precalc() { - m_S = T(-M_PI_2) * m_Shift;; + m_S = -T(M_PI_2) * m_Shift;; m_V = m_Weight * T(M_2_PI); m_V4 = m_Weight * T(0.25) * T(M_2_PI); } @@ -3308,7 +3318,7 @@ public: virtual bool SetParamVal(const char* name, T val) { - if (!strcmp(name, "bipolar_shift")) + if (!_stricmp(name, "bipolar_shift")) { T temp = Fabsmod(T(0.5) * (val + 1)); @@ -3398,7 +3408,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t roundX = Rint(vIn.x);\n" @@ -3463,7 +3473,7 @@ public: { T wx = m_Weight * T(1.3029400317411197908970256609023);//This precision came from the original. T y2 = helper.In.y * 2; - T r = wx * sqrt(fabs(helper.In.y * helper.In.x) / (T(EPS) + helper.In.x * helper.In.x + y2 * y2)); + T r = wx * sqrt(fabs(helper.In.y * helper.In.x) / Zeps(helper.In.x * helper.In.x + y2 * y2)); helper.Out.x = r * helper.In.x; helper.Out.y = r * y2; @@ -3473,12 +3483,12 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t wx = xform->m_VariationWeights[" << varIndex << "] * 1.3029400317411197908970256609023;\n" << "\t\treal_t y2 = vIn.y * 2.0;\n" - << "\t\treal_t r = wx * sqrt(fabs(vIn.y * vIn.x) / (EPS + vIn.x * vIn.x + y2 * y2));\n" + << "\t\treal_t r = wx * sqrt(fabs(vIn.y * vIn.x) / Zeps(vIn.x * vIn.x + y2 * y2));\n" << "\n" << "\t\tvOut.x = r * vIn.x;\n" << "\t\tvOut.y = r * y2;\n" @@ -3841,7 +3851,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t tmp = precalcSumSquares + 1.0;\n" @@ -3873,12 +3883,15 @@ public: /// Elliptic. /// template -class EMBER_API EllipticVariation : public Variation +class EMBER_API EllipticVariation : public ParametricVariation { public: - EllipticVariation(T weight = 1.0) : Variation("elliptic", VAR_ELLIPTIC, weight, true) { } + EllipticVariation(T weight = 1.0) : ParametricVariation("elliptic", VAR_ELLIPTIC, weight, true) + { + Init(); + } - VARCOPY(EllipticVariation) + PARVARCOPY(EllipticVariation) void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { @@ -3888,7 +3901,7 @@ public: T a = helper.In.x / xmax; T b = 1 - a * a; T ssx = xmax - 1; - T w = m_Weight / T(M_PI_2); + const T w = m_WeightDivPiDiv2; if (b < 0) b = 0; @@ -3912,8 +3925,11 @@ public: virtual string OpenCLString() { - ostringstream ss; + ostringstream ss, ss2; int i = 0, varIndex = IndexInXform(); + ss2 << "_" << XformIndexInEmber() << "]"; + string index = ss2.str(); + string weightDivPiDiv2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t tmp = precalcSumSquares + 1.0;\n" @@ -3922,7 +3938,7 @@ public: << "\t\treal_t a = vIn.x / xmax;\n" << "\t\treal_t b = 1.0 - a * a;\n" << "\t\treal_t ssx = xmax - 1.0;\n" - << "\t\treal_t w = xform->m_VariationWeights[" << varIndex << "] / M_PI_2;\n" + << "\t\tconst real_t w = " << weightDivPiDiv2 << ";\n" << "\n" << "\t\tif (b < 0)\n" << "\t\t b = 0;\n" @@ -3946,6 +3962,23 @@ public: return ss.str(); } + + virtual void Precalc() + { + m_WeightDivPiDiv2 = m_Weight / T(M_PI_2); + } + +protected: + void Init() + { + string prefix = Prefix(); + + m_Params.clear(); + m_Params.push_back(ParamWithName(true, &m_WeightDivPiDiv2, prefix + "elliptic_weight_div_pi_div_2"));//Precalc. + } + +private: + T m_WeightDivPiDiv2;//Precalc. }; /// @@ -4012,7 +4045,7 @@ public: virtual bool SetParamVal(const char* name, T val) { - if (!strcmp(name, "escher_beta")) + if (!_stricmp(name, "escher_beta")) { m_Beta = Fabsmod((val + T(M_PI)) / (2 * T(M_PI))) * 2 * T(M_PI) - T(M_PI); Precalc(); @@ -4058,36 +4091,30 @@ public: sincos(helper.In.y, &sn, &cn); - tmp = expx + expnx - cn; - - if (tmp == 0) - tmp = EPS6; - - tmp = m_Weight / tmp; + tmp = m_Weight / Zeps(expx + expnx - cn); helper.Out.x = tmp * (expx - expnx); helper.Out.y = tmp * sn; + helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t expx = exp(vIn.x) * 0.5;\n" << "\t\treal_t expnx = 0.25 / expx;\n" << "\t\treal_t sn = sin(vIn.y);\n" << "\t\treal_t cn = cos(vIn.y);\n" - << "\t\treal_t tmp = expx + expnx - cn;\n" - << "\n" - << "\t\tif (tmp == 0)\n" - << "\t\t tmp = EPS6;\n" + << "\t\treal_t tmp = Zeps(expx + expnx - cn);\n" << "\n" << "\t\ttmp = xform->m_VariationWeights[" << varIndex << "] / tmp;\n" << "\n" << "\t\tvOut.x = tmp * (expx - expnx);\n" << "\t\tvOut.y = tmp * sn;\n" + << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n" << "\t}\n"; return ss.str(); @@ -4123,7 +4150,7 @@ public: } else { - r = 1 + m_Space / (r + EPS6); + r = 1 + m_Space / Zeps(r); helper.Out.x = m_Weight * (r * x + m_X);//Fix to make it colapse to 0 when weight is 0.//SMOULDER helper.Out.y = m_Weight * (r * y - m_Y); @@ -4158,7 +4185,7 @@ public: << "\t\t}\n" << "\t\telse\n" << "\t\t{\n" - << "\t\t r = 1.0 + " << space << " / (r + EPS6);\n" + << "\t\t r = 1.0 + " << space << " / Zeps(r);\n" << "\n" << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * (r * x + " << x << ");\n" << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * (r * y - " << y << ");\n" @@ -4172,7 +4199,7 @@ public: virtual bool SetParamVal(const char* name, T val) { - if (!strcmp(name, "lazysusan_spin")) + if (!_stricmp(name, "lazysusan_spin")) { m_Spin = Fabsmod(val / T(M_2PI)) * T(M_2PI); Precalc(); @@ -4228,9 +4255,9 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - if (helper.m_PrecalcSumSquares < m_W2) + if (helper.m_PrecalcSumSquares < m_W2 && helper.m_PrecalcSumSquares != 0) { - T r = m_Weight * sqrt(m_W2 / helper.m_PrecalcSumSquares - 1); + T r = m_Weight * sqrt((m_W2 / helper.m_PrecalcSumSquares) - 1); helper.Out.x = r * helper.In.x; helper.Out.y = r * helper.In.y; @@ -4253,9 +4280,9 @@ public: string w2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" - << "\t\tif (precalcSumSquares < " << w2 << ")\n" + << "\t\tif (precalcSumSquares < " << w2 << " && precalcSumSquares != 0)\n" << "\t\t{\n" - << "\t\t real_t r = xform->m_VariationWeights[" << varIndex << "] * sqrt(" << w2 << " / precalcSumSquares - 1.0);\n" + << "\t\t real_t r = xform->m_VariationWeights[" << varIndex << "] * sqrt((" << w2 << " / precalcSumSquares) - 1.0);\n" << "\t\t vOut.x = r * vIn.x;\n" << "\t\t vOut.y = r * vIn.y;\n" << "\t\t}\n" @@ -4637,10 +4664,11 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { T t = helper.m_PrecalcSumSquares; - T r = 1 / (helper.m_PrecalcSqrtSumSquares * (t + m_InvWeight)); + T r = 1 / Zeps(helper.m_PrecalcSqrtSumSquares * (t + m_InvWeight)); helper.Out.x = helper.In.x * r; helper.Out.y = helper.In.y * r; + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -4653,10 +4681,11 @@ public: ss << "\t{\n" << "\t\treal_t t = precalcSumSquares;\n" - << "\t\treal_t r = 1.0 / (precalcSqrtSumSquares * (t + " << invWeight << "));\n" + << "\t\treal_t r = 1.0 / Zeps(precalcSqrtSumSquares * (t + " << invWeight << "));\n" << "\n" << "\t\tvOut.x = vIn.x * r;\n" << "\t\tvOut.y = vIn.y * r;\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -4664,7 +4693,7 @@ public: virtual void Precalc() { - m_InvWeight = 1 / (m_Weight + EPS6); + m_InvWeight = 1 / Zeps(m_Weight); } protected: @@ -4956,7 +4985,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T roundx = (T)Floor(helper.In.x + T(0.5)); + T roundx = (T)(int)(helper.In.x >= 0 ? (helper.In.x + T(0.5)) : (helper.In.x - T(0.5))); T offsetx = helper.In.x - roundx; helper.Out.x = m_Weight * (offsetx * (1 - m_Space) + roundx); @@ -4974,7 +5003,7 @@ public: string warp = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" - << "\t\treal_t roundx = floor(vIn.x + 0.5);\n" + << "\t\treal_t roundx = (real_t)(int)(vIn.x >= 0 ? (vIn.x + 0.5) : (vIn.x - 0.5));\n" << "\t\treal_t offsetx = vIn.x - roundx;\n" << "\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (offsetx * (1.0 - " << space << ") + roundx);\n" @@ -5206,7 +5235,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T r = 1 / (helper.m_PrecalcSqrtSumSquares + T(EPS)); + T r = 1 / Zeps(helper.m_PrecalcSqrtSumSquares); T a = helper.m_PrecalcAtanyx + m_Swirl * r; T c = (T)Floor((m_Count * a + T(M_PI)) * T(M_1_PI) * T(0.5)); T compFac = 1 - m_Angle * m_Count * T(M_1_PI) * T(0.5); @@ -5230,7 +5259,7 @@ public: string swirl = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" - << "\t\treal_t r = 1.0 / (precalcSqrtSumSquares + EPS);\n" + << "\t\treal_t r = 1.0 / Zeps(precalcSqrtSumSquares);\n" << "\t\treal_t a = precalcAtanyx + " << swirl << " * r;\n" << "\t\treal_t c = floor((" << count << " * a + M_PI) * M_1_PI * 0.5);\n" << "\t\treal_t compFac = 1 - " << angle << " * " << count << " * M_1_PI * 0.5;\n" @@ -5446,7 +5475,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t expe = xform->m_VariationWeights[" << varIndex << "] * exp(vIn.x);\n" @@ -5510,7 +5539,7 @@ protected: string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_Base, prefix + "log_base", T(M_E), REAL, EPS6, TMAX)); + m_Params.push_back(ParamWithName(&m_Base, prefix + "log_base", T(M_E), REAL, EPS, TMAX)); m_Params.push_back(ParamWithName(true, &m_Denom, prefix + "log_denom"));//Precalc. } @@ -5540,7 +5569,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * sin(vIn.x) * cosh(vIn.y);\n" @@ -5574,7 +5603,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * cos(vIn.x) * cosh(vIn.y);\n" @@ -5613,7 +5642,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t tansin = sin(2.0 * vIn.x);\n" @@ -5658,7 +5687,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t secsin = sin(vIn.x);\n" @@ -5703,7 +5732,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t cscsin = sin(vIn.x);\n" @@ -5748,7 +5777,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t cotsin = sin(2.0 * vIn.x);\n" @@ -5792,7 +5821,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t sinhsin = sin(vIn.y);\n" @@ -5835,7 +5864,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t coshsin = sin(vIn.y);\n" @@ -5879,7 +5908,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t tanhsin = sin(2.0 * vIn.y);\n" @@ -5924,7 +5953,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t sechsin = sin(vIn.y);\n" @@ -5969,7 +5998,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t cschsin = sin(vIn.y);\n" @@ -6014,7 +6043,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t cothsin = sin(2.0 * vIn.y);\n" @@ -6139,7 +6168,8 @@ public: helper.Out.x = avgr * cos(avga); helper.Out.y = avgr * sin(avga); - helper.Out.z = m_Weight * helper.In.z; + helper.Out.z = helper.In.z; + //helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() @@ -6258,7 +6288,7 @@ MAKEPREPOSTPARVAR(Cell, cell, CELL) MAKEPREPOSTPARVAR(Cpow, cpow, CPOW) MAKEPREPOSTPARVAR(Curve, curve, CURVE) MAKEPREPOSTVAR(Edisc, edisc, EDISC) -MAKEPREPOSTVAR(Elliptic, elliptic, ELLIPTIC) +MAKEPREPOSTPARVAR(Elliptic, elliptic, ELLIPTIC) MAKEPREPOSTPARVAR(Escher, escher, ESCHER) MAKEPREPOSTVAR(Foci, foci, FOCI) MAKEPREPOSTPARVAR(LazySusan, lazysusan, LAZYSUSAN) diff --git a/Source/Ember/Variations02.h b/Source/Ember/Variations02.h index 29dcabc..619df4a 100644 --- a/Source/Ember/Variations02.h +++ b/Source/Ember/Variations02.h @@ -27,7 +27,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t t = xform->m_VariationWeights[" << varIndex << "] / sqrt(precalcSumSquares + 1.0);\n" @@ -64,7 +64,13 @@ public: { helper.Out.x = m_Weight * t * cos(theta); helper.Out.y = m_Weight * t * sin(theta); - helper.Out.z = m_Weight * helper.In.z; + helper.Out.z = 0; + } + else + { + helper.Out.x = 0; + helper.Out.y = 0; + helper.Out.z = 0; } } @@ -86,7 +92,13 @@ public: << "\t\t{\n" << "\t\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * t * cos(theta);\n" << "\t\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * t * sin(theta);\n" - << "\t\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n" + << "\t\t\tvOut.z = 0;\n" + << "\t\t}\n" + << "\t\telse\n" + << "\t\t{\n" + << "\t\t\tvOut.x = 0;\n" + << "\t\t\tvOut.y = 0;\n" + << "\t\t\tvOut.z = 0;\n" << "\t\t}\n" << "\t}\n"; @@ -239,7 +251,7 @@ public: virtual void Precalc() { T radius = T(0.5) * (m_BwrapsCellsize / (1 + SQR(m_BwrapsSpace))); - m_G2 = SQR(m_BwrapsGain) / (radius + EPS6) + EPS6; + m_G2 = Zeps(SQR(m_BwrapsGain) / Zeps(radius)); T maxBubble = m_G2 * radius; if (maxBubble > 2) @@ -505,7 +517,7 @@ protected: string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_BlurPixelizeSize, prefix + "blur_pixelize_size", T(0.1), REAL, EPS6)); + m_Params.push_back(ParamWithName(&m_BlurPixelizeSize, prefix + "blur_pixelize_size", T(0.1), REAL, EPS)); m_Params.push_back(ParamWithName(&m_BlurPixelizeScale, prefix + "blur_pixelize_scale", 1)); m_Params.push_back(ParamWithName(true, &m_V, prefix + "blur_pixelize_v"));//Precalc. m_Params.push_back(ParamWithName(true, &m_InvSize, prefix + "blur_pixelize_inv_size")); @@ -920,7 +932,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - if (m_VarType == VARTYPE_REG) + if (m_VarType == VARTYPE_REG)//Rare and different usage of in/out. { helper.Out.x = helper.Out.y = helper.Out.z = 0; outPoint.m_Z = 0; @@ -937,10 +949,12 @@ public: { ostringstream ss; - if (m_VarType == VARTYPE_REG)//Rare and different usage of in/out. + if (m_VarType == VARTYPE_REG) { ss << "\t{\n" - << "\t\tvOut.x = vOut.y = vOut.z = 0;\n" + << "\t\tvOut.x = 0;\n" + << "\t\tvOut.y = 0;\n" + << "\t\tvOut.z = 0;\n" << "\t\toutPoint->m_Z = 0;\n" << "\t}\n"; } @@ -978,12 +992,12 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" - << "\t\tvOut.x = vOut.y = 0;\n" - << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * (MwcNext01(mwc) + MwcNext01(mwc) + MwcNext01(mwc) + MwcNext01(mwc) - 2.0);\n" - << "\t}\n"; + << "\t\tvOut.x = vOut.y = 0;\n" + << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * (MwcNext01(mwc) + MwcNext01(mwc) + MwcNext01(mwc) + MwcNext01(mwc) - 2.0);\n" + << "\t}\n"; return ss.str(); } @@ -991,6 +1005,7 @@ public: /// /// ZScale. +/// This uses in/out in a rare and different way. /// template class EMBER_API ZScaleVariation : public Variation @@ -1009,12 +1024,12 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" - << "\t\tvOut.x = vOut.y = 0;\n" - << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n" - << "\t}\n"; + << "\t\tvOut.x = vOut.y = 0;\n" + << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n" + << "\t}\n"; return ss.str(); } @@ -1022,6 +1037,7 @@ public: /// /// ZTranslate. +/// This uses in/out in a rare and different way. /// template class EMBER_API ZTranslateVariation : public Variation @@ -1040,12 +1056,12 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" - << "\t\tvOut.x = vOut.y = 0;\n" - << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "];\n" - << "\t}\n"; + << "\t\tvOut.x = vOut.y = 0;\n" + << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "];\n" + << "\t}\n"; return ss.str(); } @@ -1053,6 +1069,7 @@ public: /// /// zcone. +/// This uses in/out in a rare and different way. /// template class EMBER_API ZConeVariation : public Variation @@ -1064,7 +1081,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - if (m_VarType == VARTYPE_REG) + if (m_VarType == VARTYPE_REG)//Rare and different usage of in/out. { helper.Out.x = helper.Out.y = 0; } @@ -1080,24 +1097,23 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); + + ss << "\t{\n"; if (m_VarType == VARTYPE_REG) { - ss << "\t{\n" - << "\t\tvOut.x = vOut.y = 0;\n" - << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * precalcSqrtSumSquares;\n" - << "\t}\n"; + ss << "\t\tvOut.x = vOut.y = 0;\n"; } else { - ss << "\t{\n" - << "\t\tvOut.x = vIn.x;\n" - << "\t\tvOut.y = vIn.y;\n" - << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * precalcSqrtSumSquares;\n" - << "\t}\n"; + ss << "\t\tvOut.x = vIn.x;\n" + << "\t\tvOut.y = vIn.y;\n"; } + ss << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * precalcSqrtSumSquares;\n" + << "\t}\n"; + return ss.str(); } }; @@ -1109,7 +1125,7 @@ template class EMBER_API Blur3DVariation : public Variation { public: - Blur3DVariation(T weight = 1.0) : Variation("blur_3d", VAR_BLUR3D, weight) { } + Blur3DVariation(T weight = 1.0) : Variation("blur3D", VAR_BLUR3D, weight) { } VARCOPY(Blur3DVariation) @@ -1131,7 +1147,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t angle = MwcNext01(mwc) * M_2PI;\n" @@ -1164,7 +1180,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T r2 = m_Weight / (helper.m_PrecalcSumSquares + helper.In.z + EPS6); + T r2 = m_Weight / Zeps(helper.m_PrecalcSumSquares + SQR(helper.In.z)); helper.Out.x = r2 * helper.In.x; helper.Out.y = r2 * helper.In.y; @@ -1174,10 +1190,10 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" - << "\t\treal_t r2 = xform->m_VariationWeights[" << varIndex << "] / (precalcSumSquares + vIn.z + EPS6);\n" + << "\t\treal_t r2 = xform->m_VariationWeights[" << varIndex << "] / Zeps(precalcSumSquares + SQR(vIn.z));\n" << "\n" << "\t\tvOut.x = r2 * vIn.x;\n" << "\t\tvOut.y = r2 * vIn.y;\n" @@ -1205,7 +1221,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { T r2 = helper.m_PrecalcSumSquares + SQR(helper.In.z); - T r = m_Weight / ((r2 * m_C2) + (m_C2x * helper.In.x) - (m_C2y * helper.In.y) + (m_C2z * helper.In.z) + 1); + T r = m_Weight / Zeps(r2 * m_C2 + m_C2x * helper.In.x - m_C2y * helper.In.y + m_C2z * helper.In.z + 1); helper.Out.x = r * (helper.In.x + m_Cx * r2); helper.Out.y = r * (helper.In.y - m_Cy * r2); @@ -1228,7 +1244,7 @@ public: ss << "\t{\n" << "\t\treal_t r2 = precalcSumSquares + SQR(vIn.z);\n" - << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] / ((r2 * " << c2 << ") + (" << c2x << " * vIn.x) - (" << c2y << " * vIn.y) + (" << c2z << " * vIn.z) + 1.0);\n" + << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] / Zeps(r2 * " << c2 << " + " << c2x << " * vIn.x - " << c2y << " * vIn.y + " << c2z << " * vIn.z + 1.0);\n" << "\n" << "\t\tvOut.x = r * (vIn.x + " << cx << " * r2);\n" << "\t\tvOut.y = r * (vIn.y - " << cy << " * r2);\n" @@ -1243,7 +1259,7 @@ public: m_C2x = 2 * m_Cx; m_C2y = 2 * m_Cy; m_C2z = 2 * m_Cz; - m_C2 = SQR(m_C2x) + SQR(m_C2y) + SQR(m_C2z); + m_C2 = SQR(m_Cx) + SQR(m_Cy) + SQR(m_Cz); } protected: @@ -1291,7 +1307,7 @@ public: T temp = r * m_Pi; T sr = sin(temp); T cr = cos(temp); - T vv = m_Weight * helper.m_PrecalcAtanxy / (m_Pi + EPS6); + T vv = m_Weight * helper.m_PrecalcAtanxy / Zeps(m_Pi); helper.Out.x = vv * sr; helper.Out.y = vv * cr; @@ -1311,7 +1327,7 @@ public: << "\t\treal_t temp = r * " << pi << ";\n" << "\t\treal_t sr = sin(temp);\n" << "\t\treal_t cr = cos(temp);\n" - << "\t\treal_t vv = xform->m_VariationWeights[" << varIndex << "] * precalcAtanxy / (" << pi << " + EPS6);\n" + << "\t\treal_t vv = xform->m_VariationWeights[" << varIndex << "] * precalcAtanxy / Zeps(" << pi << ");\n" << "\n" << "\t\tvOut.x = vv * sr;\n" << "\t\tvOut.y = vv * cr;\n" @@ -1350,8 +1366,8 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T roundX = Rint(helper.In.x); - T roundY = Rint(helper.In.y); + T roundX = (T)(int)(helper.In.x >= 0 ? (int)(helper.In.x + T(0.5)) : (int)(helper.In.x - T(0.5))); + T roundY = (T)(int)(helper.In.y >= 0 ? (int)(helper.In.y + T(0.5)) : (int)(helper.In.y - T(0.5))); T offsetX = helper.In.x - roundX; T offsetY = helper.In.y - roundY; @@ -1407,8 +1423,8 @@ public: string cr = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" - << "\t\treal_t roundX = Rint(vIn.x);\n" - << "\t\treal_t roundY = Rint(vIn.y);\n" + << "\t\treal_t roundX = (real_t)(int)(vIn.x >= 0 ? (int)(vIn.x + 0.5) : (int)(vIn.x - 0.5));\n" + << "\t\treal_t roundY = (real_t)(int)(vIn.y >= 0 ? (int)(vIn.y + 0.5) : (int)(vIn.y - 0.5));\n" << "\t\treal_t offsetX = vIn.x - roundX;\n" << "\t\treal_t offsetY = vIn.y - roundY;\n" << "\n" @@ -1455,13 +1471,9 @@ public: virtual void Precalc() { - T c = fabs(m_C); - T cl = fabs(m_Left); - T cr = fabs(m_Right); - - c = c == 0 ? EPS : c; - cl = cl == 0 ? EPS : cl; - cr = cr == 0 ? EPS : cr; + T c = Zeps(fabs(m_C)); + T cl = Zeps(fabs(m_Left)); + T cr = Zeps(fabs(m_Right)); m_AbsC = c; m_Cl = c * cl; @@ -1628,7 +1640,7 @@ public: virtual void Precalc() { - m_Cs = 1 / (m_Size + EPS); + m_Cs = 1 / Zeps(m_Size); m_Cx = m_X; m_Cy = m_Y; m_Ncx = -m_X; @@ -1907,6 +1919,7 @@ public: helper.Out.x = -1 + m_Vv2 * Lerp(Lerp(x, Fosc(x, T(4), m_Px), oscnapx), Fosc(bx, T(4), m_Px), oscnapx);//Original did a direct assignment to outPoint, which is incompatible with Ember's design. helper.Out.y = -1 + m_Vv2 * Lerp(Lerp(y, Fosc(y, T(4), m_Py), oscnapy), Fosc(by, T(4), m_Py), oscnapy); + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -1937,6 +1950,7 @@ public: << "\n" << "\t\tvOut.x = -1 + " << vv2 << " * Lerp(Lerp(x, Fosc(x, 4, " << px << "), oscnapx), Fosc(bx, 4, " << px << "), oscnapx);\n" << "\t\tvOut.y = -1 + " << vv2 << " * Lerp(Lerp(y, Fosc(y, 4, " << py << "), oscnapy), Fosc(by, 4, " << py << "), oscnapy);\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -2014,7 +2028,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t avgr = xform->m_VariationWeights[" << varIndex << "] * (sqrt(SQR(vIn.y) + SQR(vIn.x + 1)) / sqrt(SQR(vIn.y) + SQR(vIn.x - 1)));\n" @@ -2084,7 +2098,7 @@ public: virtual void Precalc() { - m_K = T(0.5) * log(SQR(m_Real) + SQR(m_Imag) + EPS);//Original used 1e-300, which isn't representable with a float. + m_K = T(0.5) * log(Zeps(SQR(m_Real) + SQR(m_Imag)));//Original used 1e-300, which isn't representable with a float. m_T = atan2(m_Imag, m_Real); } @@ -2218,7 +2232,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t a = M_2PI / (precalcSqrtSumSquares + 1);\n" @@ -2602,7 +2616,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t x = LRint(vIn.x);\n" @@ -2766,6 +2780,7 @@ public: helper.Out.x = vr * (a * c + b * d); helper.Out.y = vr * (b * c - a * d); + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -2789,6 +2804,7 @@ public: << "\n" << "\t\tvOut.x = vr * (a * c + b * d);\n" << "\t\tvOut.y = vr * (b * c - a * d);\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -2860,6 +2876,7 @@ public: helper.Out.x = vr * (a * c + b * d); helper.Out.y = vr * (b * c - a * d); + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -2887,6 +2904,7 @@ public: << "\n" << "\t\tvOut.x = vr * (a * c + b * d);\n" << "\t\tvOut.y = vr * (b * c - a * d);\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -2953,6 +2971,7 @@ public: helper.Out.x = vr * (x * cosa + y * sina); helper.Out.y = vr * (y * cosa - x * sina); + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -2980,6 +2999,7 @@ public: << "\n" << "\t\tvOut.x = vr * (x * cosa + y * sina);\n" << "\t\tvOut.y = vr * (y * cosa - x * sina);\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -3542,6 +3562,7 @@ public: helper.Out.x = r * cosa; helper.Out.y = r * sina; + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -3564,6 +3585,7 @@ public: << "\n" << "\t\tvOut.x = r * cosa;\n" << "\t\tvOut.y = r * sina;\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -4224,11 +4246,7 @@ public: T x2cx = m_C2x * helper.In.x; T y2cy = m_C2y * helper.In.y; T z2cz = m_C2z * helper.In.z; - T val = m_C2 * r2 - x2cx - y2cy - z2cz + 1; - - if (val == 0) - val += EPS6; - + T val = Zeps(m_C2 * r2 - x2cx - y2cy - z2cz + 1); T d = m_Weight / val; helper.Out.x = d * (helper.In.x * m_S2x + m_Cx * (y2cy + z2cz - r2 - 1)); @@ -4261,11 +4279,7 @@ public: << "\t\treal_t x2cx = " << c2x << " * vIn.x;\n" << "\t\treal_t y2cy = " << c2y << " * vIn.y;\n" << "\t\treal_t z2cz = " << c2z << " * vIn.z;\n" - << "\t\treal_t val = " << c2 << " * r2 - x2cx - y2cy - z2cz + 1.0;\n" - << "\n" - << "\t\tif (val == 0.0)\n" - << "\t\t val += EPS6;\n" - << "\n" + << "\t\treal_t val = Zeps(" << c2 << " * r2 - x2cx - y2cy - z2cz + 1.0);\n" << "\t\treal_t d = xform->m_VariationWeights[" << varIndex << "] / val;\n" << "\n" << "\t\tvOut.x = d * (vIn.x * " << s2x << " + " << cx << " * (y2cy + z2cz - r2 - 1.0));\n" @@ -4622,6 +4636,7 @@ public: //invert the multiplication with scale from before. helper.Out.x = m_Weight * Lerp(u1, u2, m_P) * m_Is;//Original did a direct assignment to outPoint, which is incompatible with Ember's design. helper.Out.y = m_Weight * Lerp(v1, v2, m_P) * m_Is; + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -4667,6 +4682,7 @@ public: << "\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * Lerp(u1, u2, " << p << ") * " << is << ";\n" << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * Lerp(v1, v2, " << p << ") * " << is << ";\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -4677,7 +4693,7 @@ public: m_F = m_Frequency * 5; m_A = m_Amplitude * T(0.01); m_P = m_Phase * M_2PI - T(M_PI); - m_S = m_Scale == 0 ? EPS6 : m_Scale;//Scale must not be zero. + m_S = Zeps(m_Scale);//Scale must not be zero. m_Is = 1 / m_S;//Need the inverse scale. //Pre-multiply velocity + phase, phase + amplitude and (PI - phase) + amplitude. @@ -4792,7 +4808,7 @@ public: { if (m_Sx == 0) { - m_Sx = EPS6; + m_Sx = EPS; m_Ax = 1; } else @@ -4911,11 +4927,8 @@ public: { m_Ax = m_AmpX; m_Ay = m_AmpY; - m_Fx = m_FreqX * M_2PI; - m_Fy = m_FreqY * M_2PI; - - if (m_Fx == 0) m_Fx = EPS6; - if (m_Fy == 0) m_Fy = EPS6; + m_Fx = Zeps(m_FreqX * M_2PI); + m_Fy = Zeps(m_FreqY * M_2PI); } protected: @@ -5053,7 +5066,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "];\n" @@ -5517,7 +5530,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * sin(vIn.x) * (cosh(vIn.y) + 1.0) * Sqr(sin(vIn.x));\n" @@ -5552,7 +5565,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t d = xform->m_VariationWeights[" << varIndex << "] / precalcSumSquares;\n" @@ -5700,7 +5713,7 @@ MAKEPREPOSTPARVAR(BlurLinear, blur_linear, BLUR_LINEAR) MAKEPREPOSTPARVARASSIGN(BlurSquare, blur_square, BLUR_SQUARE, ASSIGNTYPE_SUM) MAKEPREPOSTVAR(Flatten, flatten, FLATTEN) MAKEPREPOSTVARASSIGN(Zblur, zblur, ZBLUR, ASSIGNTYPE_SUM) -MAKEPREPOSTVARASSIGN(Blur3D, blur_3d, BLUR3D, ASSIGNTYPE_SUM) +MAKEPREPOSTVARASSIGN(Blur3D, blur3D, BLUR3D, ASSIGNTYPE_SUM) MAKEPREPOSTVARASSIGN(ZScale, zscale, ZSCALE, ASSIGNTYPE_SUM) MAKEPREPOSTVARASSIGN(ZTranslate, ztranslate, ZTRANSLATE, ASSIGNTYPE_SUM) MAKEPREPOSTVAR(ZCone, zcone, ZCONE) diff --git a/Source/Ember/Variations03.h b/Source/Ember/Variations03.h index 8d21653..ae0af14 100644 --- a/Source/Ember/Variations03.h +++ b/Source/Ember/Variations03.h @@ -80,7 +80,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x;\n" @@ -109,7 +109,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { T r2 = pow(helper.m_PrecalcSumSquares, m_Power * T(0.5)) * m_Weight; - T ran = (helper.m_PrecalcAtanyx / (m_Denominator + EPS6) + (m_Root * M_2PI * Floor(rand.Frand01() * m_Denominator) / (m_Denominator + EPS))) * m_Numerator; + T ran = (helper.m_PrecalcAtanyx / Zeps(m_Denominator) + (m_Root * M_2PI * Floor(rand.Frand01() * m_Denominator) / Zeps(m_Denominator))) * m_Numerator; helper.Out.x = r2 * cos(ran); helper.Out.y = r2 * sin(ran); @@ -131,7 +131,7 @@ public: ss << "\t{\n" << "\t\treal_t r2 = pow(precalcSumSquares, " << power << " * 0.5) * xform->m_VariationWeights[" << varIndex << "];\n" - << "\t\treal_t ran = (precalcAtanyx / (" << denominator << " + EPS6) + (" << root << " * M_2PI * floor(MwcNext01(mwc) * " << denominator << ") / (" << denominator << " + EPS))) * " << numerator << ";\n" + << "\t\treal_t ran = (precalcAtanyx / Zeps(" << denominator << ") + (" << root << " * M_2PI * floor(MwcNext01(mwc) * " << denominator << ") / Zeps(" << denominator << "))) * " << numerator << ";\n" << "\n" << "\t\tvOut.x = r2 * cos(ran);\n" << "\t\tvOut.y = r2 * sin(ran);\n" @@ -143,7 +143,7 @@ public: virtual void Precalc() { - m_Power = m_Numerator / (m_Denominator * m_Correctn * (1 / m_Correctd) + EPS6); + m_Power = m_Numerator / Zeps(m_Denominator * m_Correctn * (1 / m_Correctd)); } protected: @@ -185,7 +185,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T u = sqrt(ClampGte0((m_A + EPS6) * SQR(helper.In.x) + (m_B + EPS6) * SQR(helper.In.y)));//Original did not clamp. + T u = sqrt(ClampGte0(Zeps(m_A) * SQR(helper.In.x) + Zeps(m_B) * SQR(helper.In.y)));//Original did not clamp. helper.Out.x = cos(u) * tan(helper.In.x) * m_Weight; helper.Out.y = sin(u) * tan(helper.In.y) * m_Weight; @@ -202,7 +202,7 @@ public: string b = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" - << "\t\treal_t u = sqrt(ClampGte((" << a << " + EPS6) * SQR(vIn.x) + (" << b << " + EPS6) * SQR(vIn.y), 0.0));\n" + << "\t\treal_t u = sqrt(ClampGte(Zeps(" << a << ") * SQR(vIn.x) + Zeps(" << b << ") * SQR(vIn.y), 0.0));\n" << "\n" << "\t\tvOut.x = cos(u) * tan(vIn.x) * xform->m_VariationWeights[" << varIndex << "];\n" << "\t\tvOut.y = sin(u) * tan(vIn.y) * xform->m_VariationWeights[" << varIndex << "];\n" @@ -248,7 +248,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (vIn.x - ((SQR(vIn.x) * vIn.x) / 3)) + vIn.x * SQR(vIn.y);\n" @@ -1087,7 +1087,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t rad = sqrt(MwcNext01(mwc));\n" @@ -1261,7 +1261,7 @@ public: bool mode = m_Power > 0; m_WorkPower = mode ? m_Power : -m_Power; - ClampLteRef(m_WorkPower, 2); + ClampGteRef(m_WorkPower, 2); m_Alpha = M_2PI / m_WorkPower; } @@ -1490,7 +1490,7 @@ public: T z = helper.In.z / m_AbsN; T r = m_Weight * pow(helper.m_PrecalcSumSquares + SQR(z), m_Cn); T tmp = r * helper.m_PrecalcSqrtSumSquares; - T ang = helper.m_PrecalcAtanyx + M_2PI * rand.Rand((unsigned int)m_AbsN); + T ang = (helper.m_PrecalcAtanyx + M_2PI * rand.Rand((unsigned int)m_AbsN)) / m_N; helper.Out.x = tmp * cos(ang); helper.Out.y = tmp * sin(ang); @@ -1511,7 +1511,7 @@ public: << "\t\treal_t z = vIn.z / " << absn << ";\n" << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] * pow(precalcSumSquares + SQR(z), " << cn << ");\n" << "\t\treal_t tmp = r * precalcSqrtSumSquares;\n" - << "\t\treal_t ang = precalcAtanyx + M_2PI * MwcNextRange(mwc, (uint)" << absn << ");\n" + << "\t\treal_t ang = (precalcAtanyx + M_2PI * MwcNextRange(mwc, (uint)" << absn << ")) / " << n << ";\n" << "\n" << "\t\tvOut.x = tmp * cos(ang);\n" << "\t\tvOut.y = tmp * sin(ang);\n" @@ -1569,7 +1569,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { T r = m_Weight * pow(helper.m_PrecalcSumSquares, m_Cn); - T temp = helper.m_PrecalcAtanyx + M_2PI * rand.Rand((unsigned int)m_AbsN); + T temp = (helper.m_PrecalcAtanyx + M_2PI * rand.Rand((unsigned int)m_AbsN)) / m_N; helper.Out.x = r * cos(temp); helper.Out.y = r * sin(temp); @@ -1588,7 +1588,7 @@ public: ss << "\t{\n" << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] * pow(precalcSumSquares, " << cn << ");\n" - << "\t\treal_t temp = precalcAtanyx + M_2PI * MwcNextRange(mwc, (uint)" << absn << ");\n" + << "\t\treal_t temp = (precalcAtanyx + M_2PI * MwcNextRange(mwc, (uint)" << absn << ")) / " << n << ";\n" << "\n" << "\t\tvOut.x = r * cos(temp);\n" << "\t\tvOut.y = r * sin(temp);\n" @@ -1647,6 +1647,7 @@ public: { helper.Out.x = SignNz(helper.In.x) * pow(fabs(helper.In.x), m_PowX) * m_Weight; helper.Out.y = SignNz(helper.In.y) * pow(fabs(helper.In.y), m_PowY) * m_Weight; + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -1659,8 +1660,9 @@ public: string powy = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" - << "\t\tvOut.x = (real_t)(vIn.x < 0 ? -1 : 1) * pow(fabs(vIn.x), " << powx << ") * xform->m_VariationWeights[" << varIndex << "];\n" - << "\t\tvOut.y = (real_t)(vIn.y < 0 ? -1 : 1) * pow(fabs(vIn.y), " << powy << ") * xform->m_VariationWeights[" << varIndex << "];\n" + << "\t\tvOut.x = SignNz(vIn.x) * pow(fabs(vIn.x), " << powx << ") * xform->m_VariationWeights[" << varIndex << "];\n" + << "\t\tvOut.y = SignNz(vIn.y) * pow(fabs(vIn.y), " << powy << ") * xform->m_VariationWeights[" << varIndex << "];\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -1754,10 +1756,11 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T r = m_Weight / (helper.m_PrecalcSumSquares + EPS6); + T r = m_Weight / Zeps(helper.m_PrecalcSumSquares); helper.Out.x = helper.In.x * r * m_X; helper.Out.y = helper.In.y * r * m_Y; + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -1770,10 +1773,11 @@ public: string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" - << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] / (precalcSumSquares + EPS6);\n" + << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] / Zeps(precalcSumSquares);\n" << "\n" << "\t\tvOut.x = vIn.x * r * " << x << ";\n" << "\t\tvOut.y = vIn.y * r * " << y << ";\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -1810,7 +1814,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T r = m_Weight / (helper.m_PrecalcSumSquares + SQR(helper.In.z) + EPS6); + T r = m_Weight / Zeps(helper.m_PrecalcSumSquares + SQR(helper.In.z)); helper.Out.x = helper.In.x * r * m_X; helper.Out.y = helper.In.y * r * m_Y; @@ -1828,7 +1832,7 @@ public: string z = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" - << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] / (precalcSumSquares + SQR(vIn.z) + EPS6);\n" + << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] / Zeps(precalcSumSquares + SQR(vIn.z));\n" << "\n" << "\t\tvOut.x = vIn.x * r * " << x << ";\n" << "\t\tvOut.y = vIn.y * r * " << y << ";\n" @@ -1968,7 +1972,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t sinX = sin(vIn.x);\n" @@ -2010,7 +2014,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t e = 1 / precalcSumSquares + SQR(M_2_PI);\n" @@ -2084,7 +2088,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t inZ, otherZ, tempTz, tempPz;\n" @@ -2158,25 +2162,27 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T c1 = SQR(helper.In.x); - T c2 = SQR(helper.In.y); + T d = Zeps(helper.m_PrecalcSumSquares); + T c1 = Zeps(SQR(helper.In.x)); + T c2 = Zeps(SQR(helper.In.y)); - helper.Out.x = m_Weight * ((1 / helper.m_PrecalcSumSquares + EPS6) * cos(c1 + EPS6) * sin(c2 + EPS6)); - helper.Out.y = m_Weight * ((1 / helper.m_PrecalcSumSquares + EPS6) * sin(c1 + EPS6) * sin(c2 + EPS6)); + helper.Out.x = m_Weight * ((1 / d) * cos(c1) * sin(c2)); + helper.Out.y = m_Weight * ((1 / d) * sin(c1) * sin(c2)); helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" - << "\t\treal_t c1 = SQR(vIn.x);\n" - << "\t\treal_t c2 = SQR(vIn.y);\n" + << "\t\treal_t d = Zeps(precalcSumSquares);\n" + << "\t\treal_t c1 = Zeps(SQR(vIn.x));\n" + << "\t\treal_t c2 = Zeps(SQR(vIn.y));\n" << "\n" - << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * ((1.0 / precalcSumSquares + EPS6) * cos(c1 + EPS6) * sin(c2 + EPS6));\n" - << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * ((1.0 / precalcSumSquares + EPS6) * sin(c1 + EPS6) * sin(c2 + EPS6));\n" + << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * ((1.0 / d) * cos(c1) * sin(c2));\n" + << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * ((1.0 / d) * sin(c1) * sin(c2));\n" << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n" << "\t}\n"; @@ -2236,7 +2242,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t a = precalcAtanyx;\n" @@ -2295,7 +2301,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T dx, dy, r = m_Weight / (helper.m_PrecalcSumSquares + EPS6); + T dx, dy, r = m_Weight / (helper.m_PrecalcSumSquares + EPS); int isXY = int(LRint(helper.In.x * m_InvSize) + LRint(helper.In.y * m_InvSize)); if (isXY % 2) @@ -2327,7 +2333,7 @@ public: string invSize = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc. ss << "\t{\n" - << "\t\treal_t dx, dy, r = xform->m_VariationWeights[" << varIndex << "] / (precalcSumSquares + EPS6);\n" + << "\t\treal_t dx, dy, r = xform->m_VariationWeights[" << varIndex << "] / (precalcSumSquares + EPS);\n" << "\t\tint isXY = LRint(vIn.x * " << invSize << ") + LRint(vIn.y * " << invSize << ");\n" << "\n" << "\t\tif (isXY % 2)\n" @@ -2351,7 +2357,7 @@ public: virtual void Precalc() { - m_InvSize = 1 / (m_Size + EPS6); + m_InvSize = 1 / (m_Size + EPS); } protected: @@ -2481,7 +2487,7 @@ public: T uIm = m_Re_A * helper.In.y + m_Im_A * helper.In.x + m_Im_B; T vRe = m_Re_C * helper.In.x - m_Im_C * helper.In.y + m_Re_D; T vIm = m_Re_C * helper.In.y + m_Im_C * helper.In.x + m_Im_D; - T vDenom = vRe * vRe + vIm * vIm; + T vDenom = Zeps(SQR(vRe) + SQR(vIm)); helper.Out.x = m_Weight * (uRe * vRe + uIm * vIm) / vDenom; helper.Out.y = m_Weight * (uIm * vRe - uRe * vIm) / vDenom; @@ -2508,7 +2514,7 @@ public: << "\t\treal_t uIm = " << reA << " * vIn.y + " << imA << " * vIn.x + " << imB << ";\n" << "\t\treal_t vRe = " << reC << " * vIn.x - " << imC << " * vIn.y + " << reD << ";\n" << "\t\treal_t vIm = " << reC << " * vIn.y + " << imC << " * vIn.x + " << imD << ";\n" - << "\t\treal_t vDenom = vRe * vRe + vIm * vIm;\n" + << "\t\treal_t vDenom = Zeps(vRe * vRe + vIm * vIm);\n" << "\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (uRe * vRe + uIm * vIm) / vDenom;\n" << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * (uIm * vRe - uRe * vIm) / vDenom;\n" @@ -3069,7 +3075,7 @@ protected: m_Params.clear(); m_Params.push_back(ParamWithName(&m_Even, prefix + "target_even", 0, REAL_CYCLIC, 0, M_2PI)); m_Params.push_back(ParamWithName(&m_Odd, prefix + "target_odd", 0, REAL_CYCLIC, 0, M_2PI)); - m_Params.push_back(ParamWithName(&m_Size, prefix + "target_size", 1, REAL, EPS6, TMAX)); + m_Params.push_back(ParamWithName(&m_Size, prefix + "target_size", 1, REAL, EPS, TMAX)); m_Params.push_back(ParamWithName(true, &m_SizeDiv2, prefix + "target_size_2"));//Precalc. } @@ -3259,9 +3265,7 @@ public: virtual void Precalc() { - if (m_Num == 0) - m_Num = EPS6; - + m_Num = Zeps(m_Num); m_KnPi = m_Num * T(M_1_PI); m_PiKn = T(M_PI) / m_Num; m_Ka = T(M_PI) * m_A; @@ -3380,7 +3384,7 @@ public: T tau = T(0.5) * (log(Sqr(helper.In.x + 1) + SQR(helper.In.y)) - log(Sqr(helper.In.x - 1) + SQR(helper.In.y))); T sigma = T(M_PI) - atan2(helper.In.y, helper.In.x + 1) - atan2(helper.In.y, 1 - helper.In.x); - sigma += tau * m_Out + m_In / tau; + sigma = sigma + tau * m_Out + m_In / tau; T temp = cosh(tau) - cos(sigma); @@ -3402,7 +3406,7 @@ public: << "\t\treal_t tau = 0.5 * (log(Sqr(vIn.x + 1.0) + SQR(vIn.y)) - log(Sqr(vIn.x - 1.0) + SQR(vIn.y)));\n" << "\t\treal_t sigma = M_PI - atan2(vIn.y, vIn.x + 1.0) - atan2(vIn.y, 1.0 - vIn.x);\n" << "\n" - << "\t\tsigma += tau * " << out << " + " << in << " / tau;\n" + << "\t\tsigma = sigma + tau * " << out << " + " << in << " / tau;\n" << "\n" << "\t\treal_t temp = cosh(tau) - cos(sigma);\n" << "\n" @@ -3448,7 +3452,7 @@ public: T tau = T(0.5) * (log(Sqr(helper.In.x + 1) + SQR(helper.In.y)) - log(Sqr(helper.In.x - 1) + SQR(helper.In.y))) / m_Power + m_Move; T sigma = T(M_PI) - atan2(helper.In.y, helper.In.x + 1) - atan2(helper.In.y, 1 - helper.In.x) + m_Rotate; - sigma /= m_Power + M_2PI / m_Power * Floor(rand.Frand01() * m_Power); + sigma = sigma / m_Power + M_2PI / m_Power * Floor(rand.Frand01() * m_Power); if (helper.In.x >= 0) tau += m_Split; @@ -3477,7 +3481,7 @@ public: << "\t\treal_t tau = 0.5 * (log(Sqr(vIn.x + 1.0) + SQR(vIn.y)) - log(Sqr(vIn.x - 1.0) + SQR(vIn.y))) / " << power << " + " << move << ";\n" << "\t\treal_t sigma = M_PI - atan2(vIn.y, vIn.x + 1.0) - atan2(vIn.y, 1.0 - vIn.x) + " << rotate << ";\n" << "\n" - << "\t\tsigma /= " << power << " + M_2PI / " << power << " * floor(MwcNext01(mwc) * " << power << ");\n" + << "\t\tsigma = sigma / " << power << " + M_2PI / " << power << " * floor(MwcNext01(mwc) * " << power << ");\n" << "\n" << "\t\tif (vIn.x >= 0)\n" << "\t\t tau += " << split << ";\n" @@ -3804,7 +3808,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x;\n" diff --git a/Source/Ember/Variations04.h b/Source/Ember/Variations04.h index 56a3560..e8086d5 100644 --- a/Source/Ember/Variations04.h +++ b/Source/Ember/Variations04.h @@ -601,7 +601,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T d = helper.m_PrecalcSumSquares + EPS6; + T d = Zeps(helper.m_PrecalcSumSquares); helper.Out.x = (m_Weight / d) * (tanh(d) * (2 * helper.In.x)); helper.Out.y = (m_Weight / d) * (cos(d) * (2 * helper.In.y)); @@ -611,10 +611,10 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" - << "\t\treal_t d = precalcSumSquares + EPS6;\n" + << "\t\treal_t d = Zeps(precalcSumSquares);\n" << "\n" << "\t\tvOut.x = (xform->m_VariationWeights[" << varIndex << "] / d) * (tanh(d) * (2.0 * vIn.x));\n" << "\t\tvOut.y = (xform->m_VariationWeights[" << varIndex << "] / d) * (cos(d) * (2.0 * vIn.y));\n" @@ -638,7 +638,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T d = helper.m_PrecalcSumSquares + EPS6; + T d = Zeps(helper.m_PrecalcSumSquares); helper.Out.x = (m_Weight / 2) * (tanh(d) * (2 * helper.In.x)); helper.Out.y = (m_Weight / 2) * (cos(d) * (2 * helper.In.y)); @@ -648,10 +648,10 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" - << "\t\treal_t d = precalcSumSquares + EPS6;\n" + << "\t\treal_t d = Zeps(precalcSumSquares);\n" << "\n" << "\t\tvOut.x = (xform->m_VariationWeights[" << varIndex << "] / 2.0) * (tanh(d) * (2.0 * vIn.x));\n" << "\t\tvOut.y = (xform->m_VariationWeights[" << varIndex << "] / 2.0) * (cos(d) * (2.0 * vIn.y));\n" @@ -664,6 +664,7 @@ public: /// /// RotateX. +/// This uses in/out in a rare and different way. /// template class EMBER_API RotateXVariation : public ParametricVariation @@ -678,7 +679,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T z = m_RxCos * helper.In.x - m_RxSin * helper.In.y; + T z = m_RxCos * helper.In.z - m_RxSin * helper.In.y; if (m_VarType == VARTYPE_REG) { @@ -704,7 +705,7 @@ public: string rxCos = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" - << "\t\treal_t z = " << rxCos << " * vIn.x - " << rxSin << " * vIn.y;\n" + << "\t\treal_t z = " << rxCos << " * vIn.z - " << rxSin << " * vIn.y;\n" << "\n"; if (m_VarType == VARTYPE_REG) @@ -749,6 +750,7 @@ private: /// /// RotateY. +/// This uses in/out in a rare and different way. /// template class EMBER_API RotateYVariation : public ParametricVariation @@ -913,6 +915,7 @@ private: /// /// MirrorX. +/// This uses in/out in a rare and different way. /// template class EMBER_API MirrorXVariation : public Variation @@ -924,20 +927,24 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - helper.Out.x = fabs(helper.In.x); - - if (rand.Rand() & 1) - helper.Out.x = -helper.Out.x; - if (m_VarType == VARTYPE_REG) { + helper.Out.x = fabs(outPoint.m_X); + + if (rand.RandBit()) + helper.Out.x = -helper.Out.x; + helper.Out.y = 0; helper.Out.z = 0; - outPoint.m_Y = helper.In.y; - outPoint.m_Z = helper.In.z; + outPoint.m_X = 0;//Flipped x will be added. } else { + helper.Out.x = fabs(helper.In.x); + + if (rand.RandBit()) + helper.Out.x = -helper.Out.x; + helper.Out.y = helper.In.y; helper.Out.z = helper.In.z; } @@ -947,23 +954,28 @@ public: { ostringstream ss; - ss << "\t{\n" - << "\t\tvOut.x = fabs(vIn.x);\n" - << "\n" - << "\t\tif (MwcNext(mwc) & 1)\n" - << "\t\t vOut.x = -vOut.x;\n"; + ss << "\t{\n"; if (m_VarType == VARTYPE_REG) { ss << + "\t\tvOut.x = fabs(outPoint->m_X);\n" + "\n" + "\t\tif (MwcNext(mwc) & 1)\n" + "\t\t vOut.x = -vOut.x;\n" + "\n" "\t\tvOut.y = 0;\n" "\t\tvOut.z = 0;\n" - "\t\toutPoint->m_Y = vIn.y;\n" - "\t\toutPoint->m_Z = vIn.z;\n"; + "\t\toutPoint->m_X = 0;\n"; } else { ss << + "\t\tvOut.x = fabs(vIn.x);\n" + "\n" + "\t\tif (MwcNext(mwc) & 1)\n" + "\t\t vOut.x = -vOut.x;\n" + "\n" "\t\tvOut.y = vIn.y;\n" "\t\tvOut.z = vIn.z;\n"; } @@ -976,6 +988,7 @@ public: /// /// MirrorY. +/// This uses in/out in a rare and different way. /// template class EMBER_API MirrorYVariation : public Variation @@ -987,20 +1000,24 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - helper.Out.y = fabs(helper.In.y); - - if (rand.Rand() & 1) - helper.Out.y = -helper.Out.y; - if (m_VarType == VARTYPE_REG) { + helper.Out.y = fabs(outPoint.m_Y); + + if (rand.RandBit()) + helper.Out.y = -helper.Out.y; + helper.Out.x = 0; helper.Out.z = 0; - outPoint.m_X = helper.In.x; - outPoint.m_Z = helper.In.z; + outPoint.m_Y = 0;//Flipped y will be added. } else { + helper.Out.y = fabs(helper.In.y); + + if (rand.RandBit()) + helper.Out.y = -helper.Out.y; + helper.Out.x = helper.In.x; helper.Out.z = helper.In.z; } @@ -1010,23 +1027,28 @@ public: { ostringstream ss; - ss << "\t{\n" - << "\t\tvOut.y = fabs(vIn.y);\n" - << "\n" - << "\t\tif (MwcNext(mwc) & 1)\n" - << "\t\t vOut.y = -vOut.y;\n"; + ss << "\t{\n"; if (m_VarType == VARTYPE_REG) { ss << + "\t\tvOut.y = fabs(outPoint->m_Y);\n" + "\n" + "\t\tif (MwcNext(mwc) & 1)\n" + "\t\t vOut.y = -vOut.y;\n" + "\n" "\t\tvOut.x = 0;\n" "\t\tvOut.z = 0;\n" - "\t\toutPoint->m_X = vIn.x;\n" - "\t\toutPoint->m_Z = vIn.z;\n"; + "\t\toutPoint->m_Y = 0;\n"; } else { ss << + "\t\tvOut.y = fabs(vIn.y);\n" + "\n" + "\t\tif (MwcNext(mwc) & 1)\n" + "\t\t vOut.y = -vOut.y;\n" + "\n" "\t\tvOut.x = vIn.x;\n" "\t\tvOut.z = vIn.z;\n"; } @@ -1039,6 +1061,7 @@ public: /// /// MirrorZ. +/// This uses in/out in a rare and different way. /// template class EMBER_API MirrorZVariation : public Variation @@ -1052,21 +1075,25 @@ public: { if (m_VarType == VARTYPE_REG) { + helper.Out.z = fabs(outPoint.m_Z); + + if (rand.RandBit()) + helper.Out.z = -helper.Out.z; + helper.Out.x = 0; helper.Out.y = 0; - outPoint.m_X = helper.In.x; - outPoint.m_Y = helper.In.y; + outPoint.m_Z = 0;//Flipped z will be added. } else { + helper.Out.z = fabs(helper.In.z); + + if (rand.RandBit()) + helper.Out.z = -helper.Out.z; + helper.Out.x = helper.In.x; helper.Out.y = helper.In.y; } - - helper.Out.z = fabs(helper.In.z); - - if (rand.Rand() & 1) - helper.Out.z = -helper.Out.z; } virtual string OpenCLString() @@ -1078,23 +1105,28 @@ public: if (m_VarType == VARTYPE_REG) { ss << + "\t\tvOut.z = fabs(outPoint->m_Z);\n" + "\n" + "\t\tif (MwcNext(mwc) & 1)\n" + "\t\t vOut.z = -vOut.z;\n" + "\n" "\t\tvOut.x = 0;\n" "\t\tvOut.y = 0;\n" - "\t\toutPoint->m_X = vIn.x;\n" - "\t\toutPoint->m_Y = vIn.y;\n"; + "\t\toutPoint->m_Z = 0;\n"; } else { ss << + "\t\tvOut.z = fabs(vIn.z);\n" + "\n" + "\t\tif (MwcNext(mwc) & 1)\n" + "\t\t vOut.z = -vOut.z;\n" + "\n" "\t\tvOut.x = vIn.x;\n" "\t\tvOut.y = vIn.y;\n"; } - ss << "\t\tvOut.z = fabs(vIn.z);\n" - << "\n" - << "\t\tif (MwcNext(mwc) & 1)\n" - << "\t\t vOut.z = -vOut.z;\n" - << "\t}\n"; + ss << "\t}\n"; return ss.str(); } @@ -1197,10 +1229,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T jun = EPS6; - - if (fabs(m_N) > EPS6) - jun = m_N; + T jun = Zeps(fabs(m_N)); T a = (atan2(helper.In.y, pow(helper.In.x, m_Sep)) + M_2PI * Floor(rand.Frand01() * m_AbsN)) / jun; T r = m_Weight * pow(helper.m_PrecalcSumSquares, m_Cn * m_A); @@ -1224,10 +1253,7 @@ public: string cn = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" - << "\t\treal_t jun = EPS6;\n" - << "\n" - << "\t\tif (fabs(" << n << ") > EPS6)\n" - << "\t\t jun = " << n << ";\n" + << "\t\treal_t jun = Zeps(fabs(" << n << "));\n" << "\n" << "\t\treal_t a = (atan2(vIn.y, pow(vIn.x, " << sep << ")) + M_2PI * floor(MwcNext01(mwc) * " << absN << ")) / jun;\n" << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] * pow(precalcSumSquares, " << cn << " * " << a << ");\n" @@ -1242,10 +1268,7 @@ public: virtual void Precalc() { - T jun = EPS6; - - if (abs(m_N) > EPS) - jun = m_N; + T jun = Zeps(fabs(m_N)); m_AbsN = abs(m_N); m_Cn = 1 / jun / 2; @@ -1296,6 +1319,7 @@ public: helper.Out.x = m_Weight * sin(helper.In.x) * (sqX + m_W - v); helper.Out.y = m_Weight * sin(helper.In.y) * (sqY + m_W - v); + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -1313,6 +1337,7 @@ public: << "\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * sin(vIn.x) * (sqX + " << w << " - v);\n" << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * sin(vIn.y) * (sqY + " << w << " - v);\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -1383,6 +1408,7 @@ public: helper.Out.x = m_Weight * (m_K * (helper.In.x - x0) + x0); helper.Out.y = m_Weight * (m_K * (helper.In.y - y0) + y0); + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -1434,6 +1460,7 @@ public: << "\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (" << m_k << " * (vIn.x - x0) + x0);\n" << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * (" << m_k << " * (vIn.y - y0) + y0);\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -1461,7 +1488,7 @@ protected: m_Params.clear(); m_Params.push_back(ParamWithName(&m_K, prefix + "Voron_K", T(0.99))); - m_Params.push_back(ParamWithName(&m_Step, prefix + "Voron_Step", T(0.25))); + m_Params.push_back(ParamWithName(&m_Step, prefix + "Voron_Step", T(0.25), REAL_NONZERO)); m_Params.push_back(ParamWithName(&m_Num, prefix + "Voron_Num", 1, INTEGER, 1, 25)); m_Params.push_back(ParamWithName(&m_XSeed, prefix + "Voron_XSeed", 3, INTEGER)); m_Params.push_back(ParamWithName(&m_YSeed, prefix + "Voron_YSeed", 7, INTEGER)); @@ -1511,10 +1538,10 @@ public: break; case 1: a = (rand.Rand((ISAAC_INT)m_Slices) + rand.Frand01()) / m_Slices; - r = (rand.Rand((ISAAC_INT)m_Slices) + m_YThickness) / m_Slices; + r = (rand.Rand((ISAAC_INT)m_Slices) + m_YThickness) / m_Slices; break; case 2: - a = (rand.Rand((ISAAC_INT)m_Slices) + m_XThickness) / m_Slices; + a = (rand.Rand((ISAAC_INT)m_Slices) + m_XThickness) / m_Slices; r = (rand.Rand((ISAAC_INT)m_Slices) + rand.Frand01()) / m_Slices; break; case 3: @@ -1529,6 +1556,7 @@ public: helper.Out.x = m_CosR * a + m_SinR * r; helper.Out.y = -m_SinR * a + m_CosR * r; + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -1573,6 +1601,7 @@ public: << "\n" << "\t\tvOut.x = " << cosr << " * a + " << sinr << " * r;\n" << "\t\tvOut.y = -" << sinr << " * a + " << cosr << " * r;\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -1590,7 +1619,7 @@ protected: string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_Slices, prefix + "waffle_slices", 6, INTEGER)); + m_Params.push_back(ParamWithName(&m_Slices, prefix + "waffle_slices", 6, INTEGER_NONZERO)); m_Params.push_back(ParamWithName(&m_XThickness, prefix + "waffle_xthickness", T(0.5))); m_Params.push_back(ParamWithName(&m_YThickness, prefix + "waffle_ythickness", T(0.5))); m_Params.push_back(ParamWithName(&m_Rotation, prefix + "waffle_rotation")); @@ -1628,7 +1657,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (MwcNext01(mwc) - 0.5);\n" @@ -1870,7 +1899,7 @@ public: { T t, rX, rY, rZ; - t = helper.m_PrecalcSumSquares + SQR(helper.In.z) + EPS6; + t = Zeps(helper.m_PrecalcSumSquares + SQR(helper.In.z)); rX = m_Weight / pow(t, m_StretchX); rY = m_Weight / pow(t, m_StretchY); @@ -1899,7 +1928,7 @@ public: ss << "\t{\n" << "\t\treal_t t, rX, rY, rZ;\n" << "\n" - << "\t\tt = precalcSumSquares + SQR(vIn.z) + EPS6;\n" + << "\t\tt = Zeps(precalcSumSquares + SQR(vIn.z));\n" << "\t\trX = xform->m_VariationWeights[" << varIndex << "] / pow(t, " << stretchX << ");\n" << "\t\trY = xform->m_VariationWeights[" << varIndex << "] / pow(t, " << stretchY << ");\n" << "\n" @@ -2239,7 +2268,7 @@ public: } else { - r = m_Weight * (1 + m_Space / r); + r = m_Weight * (1 + m_Space / Zeps(r)); helper.Out.x = r * x + m_X; helper.Out.y = r * y - m_Y; } @@ -2249,6 +2278,8 @@ public: helper.Out.x = m_Weight * helper.In.x; helper.Out.y = m_Weight * helper.In.y; } + + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -2305,7 +2336,7 @@ public: << "\t\t }\n" << "\t\t else\n" << "\t\t {\n" - << "\t\t r = xform->m_VariationWeights[" << varIndex << "] * (1 + " << space << " / r);\n" + << "\t\t r = xform->m_VariationWeights[" << varIndex << "] * (1 + " << space << " / Zeps(r));\n" << "\t\t vOut.x = r * x + " << x << ";\n" << "\t\t vOut.y = r * y - " << y << ";\n" << "\t\t }\n" @@ -2315,6 +2346,8 @@ public: << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x;\n" << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * vIn.y;\n" << "\t\t}\n" + << "\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -2592,9 +2625,9 @@ public: T sv = sin(v); T cv = cos(v); - helper.Out.x += m_X * r * sv * cu; - helper.Out.y += m_Y * r * sv * su; - helper.Out.z += m_Z * r * cv; + helper.Out.x = m_X * r * sv * cu; + helper.Out.y = m_Y * r * sv * su; + helper.Out.z = m_Z * r * cv; } virtual string OpenCLString() @@ -2675,11 +2708,7 @@ public: const T d = SQR(x) - SQR(y); const T re = Spread(m_C1 * x + m_C2 * d, m_Sx) + 1; const T im = Spread(m_C1 * y + m_C2x2 * x * y, m_Sy); - T c = Powq4c(SQR(re) + SQR(im), m_PowerInv); - - if (c == 0) - c = EPS6; - + T c = Zeps(Powq4c(SQR(re) + SQR(im), m_PowerInv)); const T r = m_Weight / c; helper.Out.x = (x * re + y * im) * r; @@ -2711,10 +2740,7 @@ public: << "\t\tconst real_t d = SQR(x) - SQR(y);\n" << "\t\tconst real_t re = Spread(" << c1 << " * x + " << c2 << " * d, " << sx << ") + 1.0;\n" << "\t\tconst real_t im = Spread(" << c1 << " * y + " << c2x2 << " * x * y, " << sy << ");\n" - << "\t\treal_t c = Powq4c(SQR(re) + SQR(im), " << powerInv << ");\n" - << "\n" - << "\t\tif (c == 0.0)\n" - << "\t\t c = EPS6;\n" + << "\t\treal_t c = Zeps(Powq4c(SQR(re) + SQR(im), " << powerInv << "));\n" << "\n" << "\t\tconst real_t r = xform->m_VariationWeights[" << varIndex << "] / c;\n" << "\n" @@ -2785,7 +2811,7 @@ public: r += m_Ar * sin(fma(m_Br, r, m_Cr)); if (r == 0) - r = EPS6; + r = EPS; T temp = fma(m_At, sin(fma(m_Bt, r, m_Ct)), helper.m_PrecalcAtanyx); T st = sin(temp); @@ -2832,7 +2858,7 @@ public: << "\t\tr += " << ar << " * sin(fma(" << br << ", r, " << cr << "));\n" << "\n" << "\t\tif (r == 0)\n" - << "\t\t r = EPS6;\n" + << "\t\t r = EPS;\n" << "\n" << "\t\treal_t temp = fma(" << at << ", sin(fma(" << bt << ", r, " << ct << ")), precalcAtanyx);\n" << "\t\treal_t st = sin(temp);\n" @@ -2978,6 +3004,7 @@ public: helper.Out.x = m_Weight * (fp1x + fp2x); helper.Out.y = m_Weight * (fp1y + fp2y); + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -3045,6 +3072,7 @@ public: << "\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (fp1x + fp2x);\n" << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * (fp1y + fp2y);\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -3055,17 +3083,17 @@ public: return "real_t Interference2Sine(real_t a, real_t b, real_t c, real_t p, real_t x)\n" "{\n" - " return a * pow(ClampGte(sin(b * x + c), EPS6), p);\n" + " return a * pow(ClampGte(sin(b * x + c), EPS), p);\n" "}\n" "\n" "real_t Interference2Tri(real_t a, real_t b, real_t c, real_t p, real_t x)\n" "{\n" - " return a * 2 * pow(ClampGte(asin(cos(b * x + c - M_PI_2)), EPS6) * M_1_PI, p);\n" + " return a * 2 * pow(ClampGte(asin(cos(b * x + c - M_PI_2)), EPS) * M_1_PI, p);\n" "}\n" "\n" "real_t Interference2Squ(real_t a, real_t b, real_t c, real_t p, real_t x)\n" "{\n" - " return a * pow(sin(b * x + c) < 0 ? EPS6 : 1, p);\n" + " return a * pow(sin(b * x + c) < 0 ? EPS : 1, p);\n" "}\n" "\n"; } @@ -3091,17 +3119,17 @@ protected: private: inline static T Sine(T a, T b, T c, T p, T x) { - return a * pow(ClampGte(sin(b * x + c), EPS6), p);//Original did not clamp. + return a * pow(ClampGte(sin(b * x + c), EPS), p);//Original did not clamp. } inline static T Tri(T a, T b, T c, T p, T x) { - return a * 2 * pow(ClampGte(asin(cos(b * x + c - T(M_PI_2))), EPS6) * T(M_1_PI), p);//Original did not clamp. + return a * 2 * pow(ClampGte(asin(cos(b * x + c - T(M_PI_2))), EPS) * T(M_1_PI), p);//Original did not clamp. } inline static T Squ(T a, T b, T c, T p, T x) { - return a * pow(sin(b * x + c) < 0 ? EPS6 : T(1), p);//Original passed -1 to pow if sin() was < 0. Doing so will return NaN, so EPS6 is passed instead. + return a * pow(sin(b * x + c) < 0 ? EPS : T(1), p);//Original passed -1 to pow if sin() was < 0. Doing so will return NaN, so EPS is passed instead. } T m_A1; @@ -3144,7 +3172,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t absV = Hypot(vIn.y, vIn.z);\n" @@ -3191,7 +3219,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t absV = Hypot(vIn.y, vIn.z);\n" @@ -3239,7 +3267,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t absV = Hypot(vIn.y, vIn.z);\n" @@ -3288,7 +3316,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t absV = Hypot(vIn.y, vIn.z);\n" @@ -3342,7 +3370,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t sysz = SQR(vIn.y) + SQR(vIn.z);\n" @@ -3401,7 +3429,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t sysz = SQR(vIn.y) + SQR(vIn.z);\n" @@ -3454,7 +3482,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t absV = Hypot(vIn.y, vIn.z);\n" @@ -3501,7 +3529,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t absV = Hypot(vIn.y, vIn.z);\n" @@ -3554,7 +3582,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t sysz = SQR(vIn.y) + SQR(vIn.z);\n" @@ -3613,7 +3641,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t sysz = SQR(vIn.y) + SQR(vIn.z);\n" @@ -3667,7 +3695,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t absV = Hypot(vIn.y, vIn.z);\n" @@ -3716,7 +3744,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t absV = Hypot(vIn.y, vIn.z);\n" @@ -3763,7 +3791,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t absV = Hypot(vIn.y, vIn.z);\n" @@ -3837,7 +3865,7 @@ protected: string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_Base, prefix + "loq_base", T(M_E), REAL, EPS6, TMAX)); + m_Params.push_back(ParamWithName(&m_Base, prefix + "loq_base", T(M_E), REAL, EPS, TMAX)); m_Params.push_back(ParamWithName(true, &m_Denom, prefix + "loq_denom"));//Precalc. } @@ -3859,18 +3887,20 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - helper.Out.x = m_Weight / helper.m_PrecalcSqrtSumSquares; + helper.Out.x = m_Weight / Zeps(helper.m_PrecalcSqrtSumSquares); helper.Out.y = helper.m_PrecalcAtanyx; + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" - << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] / precalcSqrtSumSquares;\n" + << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] / Zeps(precalcSqrtSumSquares);\n" << "\t\tvOut.y = precalcAtanyx;\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -3901,6 +3931,7 @@ public: (m_Q04 * xy + m_Q05 * helper.In.y + m_Q06 * sqy); helper.Out.y = (m_Q07 + m_Q08 * helper.In.x + m_Q09 * sqx) + (m_Q10 * xy + m_Weight * m_Q11 * helper.In.y + m_Q12 * sqy); + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -3931,6 +3962,7 @@ public: << "\t\t (" << q04 << " * xy + " << q05 << " * vIn.y + " << q06 << " * sqy);\n" << "\t\tvOut.y = (" << q07 << " + " << q08 << " * vIn.x + " << q09 << " * sqx) + \n" << "\t\t (" << q10 << " * xy + xform->m_VariationWeights[" << varIndex << "] * " << q11 << " * vIn.y + " << q12 << " * sqy);\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -3989,11 +4021,11 @@ public: { T xx = (rand.Frand01() - T(0.5)) * 2; T yy = (rand.Frand01() - T(0.5)) * 2; - T k = yy < 0 ? T(-1) : T(1); + T k = SignNz(yy); T yymax = ((m_A * pow(fabs(xx), m_P) + k * m_B * sqrt(fabs(1 - SQR(xx)))) - m_A); //The function must be in a range 0-1 to work properly. - yymax /= (fabs(m_A) + fabs(m_B)); + yymax /= Zeps(fabs(m_A) + fabs(m_B)); //Quick and dirty way to force y to be in range without altering the density. if (k > 0) @@ -4009,6 +4041,7 @@ public: helper.Out.x = xx * m_Weight; helper.Out.y = yy * m_Weight; + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -4024,10 +4057,10 @@ public: ss << "\t{\n" << "\t\treal_t xx = (MwcNext01(mwc) - 0.5) * 2;\n" << "\t\treal_t yy = (MwcNext01(mwc) - 0.5) * 2;\n" - << "\t\treal_t k = yy < 0 ? -1 : 1;\n" + << "\t\treal_t k = SignNz(yy);\n" << "\t\treal_t yymax = ((" << a << " * pow(fabs(xx), " << p << ") + k * " << b << " * sqrt(fabs(1 - SQR(xx)))) - " << a << ");\n" << "\n" - << "\t\tyymax /= (fabs(" << a << ") + fabs(" << b << "));\n" + << "\t\tyymax /= Zeps(fabs(" << a << ") + fabs(" << b << "));\n" << "\n" << "\t\tif (k > 0)\n" << "\t\t{\n" @@ -4042,6 +4075,7 @@ public: << "\n" << "\t\tvOut.x = xx * xform->m_VariationWeights[" << varIndex << "];\n" << "\t\tvOut.y = yy * xform->m_VariationWeights[" << varIndex << "];\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -4139,9 +4173,9 @@ public: randInt = seed + niter; randiter = 0; - while (randiter < niter) + while (randiter < niter && randiter < 20)//Allow it to escape. { - randiter += 1; + randiter++; randInt = fmod((randInt * multiplier + offset), modBase); } } @@ -4194,6 +4228,8 @@ public: helper.Out.x += m_Size * (x + Floor(helper.In.x));//The += is intended here. helper.Out.y += m_Size * (y + Floor(helper.In.y)); } + + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -4273,9 +4309,9 @@ public: << "\t\t randInt = seed + niter;\n" << "\t\t randiter = 0;\n" << "\n" - << "\t\t while (randiter < niter)\n" + << "\t\t while (randiter < niter && randiter < 20)\n" << "\t\t {\n" - << "\t\t randiter += 1;\n" + << "\t\t randiter++;\n" << "\t\t randInt = fmod((randInt * multiplier + offset), modBase);\n" << "\t\t }\n" << "\t\t }\n" @@ -4327,6 +4363,8 @@ public: << "\t\t vOut.x += " << size << " * (x + floor(vIn.x));\n" << "\t\t vOut.y += " << size << " * (y + floor(vIn.y));\n" << "\t\t}\n" + << "\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -4336,7 +4374,7 @@ public: { m_OneOverEx = 1 / m_Exponent; m_AbsSeed = fabs(m_Seed); - m_Seed2 = sqrt(m_AbsSeed + (m_AbsSeed / 2) + EPS6) / ((m_AbsSeed * T(0.5)) + EPS6) * T(0.25); + m_Seed2 = sqrt(Zeps(m_AbsSeed + (m_AbsSeed / 2))) / Zeps((m_AbsSeed * T(0.5))) * T(0.25); m_OneOverRmax = 1 / (T(0.5) * (pow(T(2), 1 / m_Exponent) - 1) * m_ArcWidth); m_Scale = (cos(-m_Rotation) - sin(-m_Rotation)) / m_Weight; } @@ -4551,7 +4589,7 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T r = m_Weight / ((SQR(SQR(helper.In.x)) + SQR(helper.In.z) + SQR(SQR(helper.In.y)) + SQR(helper.In.z)) + EPS6); + T r = m_Weight / Zeps((SQR(SQR(helper.In.x)) + SQR(helper.In.z) + SQR(SQR(helper.In.y)) + SQR(helper.In.z))); if (r < 2) { @@ -4565,7 +4603,7 @@ public: helper.Out.y = m_Weight * helper.In.y; helper.Out.z = m_Weight * helper.In.z; - T t = m_Weight / ((sqrt(SQR(helper.In.x)) + sqrt(helper.In.z) + sqrt(SQR(helper.In.y)) + sqrt(helper.In.z)) + EPS6); + T t = m_Weight / Zeps((sqrt(SQR(helper.In.x)) + sqrt(helper.In.z) + sqrt(SQR(helper.In.y)) + sqrt(helper.In.z))); if (r >= 0) { @@ -4608,7 +4646,7 @@ public: string z = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" - << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] / ((SQR(SQR(vIn.x)) + SQR(vIn.z) + SQR(SQR(vIn.y)) + SQR(vIn.z)) + EPS6);\n" + << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] / Zeps((SQR(SQR(vIn.x)) + SQR(vIn.z) + SQR(SQR(vIn.y)) + SQR(vIn.z)));\n" << "\n" << "\t\tif (r < 2)\n" << "\t\t{\n" @@ -4622,7 +4660,7 @@ public: << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * vIn.y;\n" << "\t\t vOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n" << "\n" - << "\t\t real_t t = xform->m_VariationWeights[" << varIndex << "] / ((sqrt(SQR(vIn.x)) + sqrt(vIn.z) + sqrt(SQR(vIn.y)) + sqrt(vIn.z)) + EPS6);\n" + << "\t\t real_t t = xform->m_VariationWeights[" << varIndex << "] / Zeps((sqrt(SQR(vIn.x)) + sqrt(vIn.z) + sqrt(SQR(vIn.y)) + sqrt(vIn.z)));\n" << "\n" << "\t\t if (r >= 0)\n" << "\t\t {\n" @@ -4730,6 +4768,8 @@ public: helper.Out.y = m_Weight * helper.In.y; } } + + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -4786,6 +4826,8 @@ public: << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * vIn.y;\n" << "\t\t }\n" << "\t\t}\n" + << "\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -4803,9 +4845,9 @@ protected: string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_R1, prefix + "trade_r1", 1, REAL, EPS6, TMAX)); + m_Params.push_back(ParamWithName(&m_R1, prefix + "trade_r1", 1, REAL, EPS, TMAX)); m_Params.push_back(ParamWithName(&m_D1, prefix + "trade_d1", 1, REAL, 0, TMAX)); - m_Params.push_back(ParamWithName(&m_R2, prefix + "trade_r2", 1, REAL, EPS6, TMAX)); + m_Params.push_back(ParamWithName(&m_R2, prefix + "trade_r2", 1, REAL, EPS, TMAX)); m_Params.push_back(ParamWithName(&m_D2, prefix + "trade_d2", 1, REAL, 0, TMAX)); m_Params.push_back(ParamWithName(true, &m_C1, prefix + "trade_c1")); m_Params.push_back(ParamWithName(true, &m_C2, prefix + "trade_c2")); @@ -4843,6 +4885,7 @@ public: helper.Out.x = m_Weight * mod2 * cos(temp); helper.Out.y = m_Weight * mod2 * sin(temp); + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -4865,6 +4908,7 @@ public: << "\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * mod2 * cos(temp);\n" << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * mod2 * sin(temp);\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -4872,7 +4916,7 @@ public: virtual void Precalc() { - m_ReInv = 1 / (m_Re + EPS6); + m_ReInv = 1 / Zeps(m_Re); m_Im100 = m_Im * T(0.01); } @@ -4922,7 +4966,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r = MwcNext01(mwc) * xform->m_VariationWeights[" << varIndex << "] * precalcSqrtSumSquares;\n" @@ -5030,22 +5074,23 @@ public: void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) { - T t = ((cos(helper.In.x) + cos(helper.In.y)) / m_Mp + 1); + T t = Zeps((cos(helper.In.x) + cos(helper.In.y)) / m_Mp + 1); T r = m_Weight / t; T tmp = helper.m_PrecalcSumSquares + 1; T x2 = 2 * helper.In.x; T y2 = 2 * helper.In.y; T xmax = T(0.5) * (sqrt(tmp + x2) + sqrt(tmp - x2)); T ymax = T(0.5) * (sqrt(tmp + y2) + sqrt(tmp - y2)); - T a = helper.In.x / xmax; + T a = helper.In.x / Zeps(xmax); T b = SafeSqrt(1 - SQR(a)); helper.Out.x = m_Vx * atan2(a, b) * r; - a = helper.In.y / ymax; + a = helper.In.y / Zeps(ymax); b = SafeSqrt(1 - SQR(a)); helper.Out.y = m_Vy * atan2(a, b) * r; + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -5062,22 +5107,23 @@ public: string vy = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" - << "\t\treal_t t = ((cos(vIn.x) + cos(vIn.y)) / " << mp << " + 1);\n" + << "\t\treal_t t = Zeps((cos(vIn.x) + cos(vIn.y)) / " << mp << " + 1);\n" << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] / t;\n" << "\t\treal_t tmp = precalcSumSquares + 1;\n" << "\t\treal_t x2 = 2 * vIn.x;\n" << "\t\treal_t y2 = 2 * vIn.y;\n" << "\t\treal_t xmax = 0.5 * (sqrt(tmp + x2) + sqrt(tmp - x2));\n" << "\t\treal_t ymax = 0.5 * (sqrt(tmp + y2) + sqrt(tmp - y2));\n" - << "\t\treal_t a = vIn.x / xmax;\n" + << "\t\treal_t a = vIn.x / Zeps(xmax);\n" << "\t\treal_t b = SafeSqrt(1 - SQR(a));\n" << "\n" << "\t\tvOut.x = " << vx << " * atan2(a, b) * r;\n" << "\n" - << "\t\ta = vIn.y / ymax;\n" + << "\t\ta = vIn.y / Zeps(ymax);\n" << "\t\tb = SafeSqrt(1 - SQR(a));\n" << "\n" << "\t\tvOut.y = " << vy << " * atan2(a, b) * r;\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -5098,7 +5144,7 @@ protected: m_Params.clear(); m_Params.push_back(ParamWithName(&m_X, prefix + "blocky_x", 1)); m_Params.push_back(ParamWithName(&m_Y, prefix + "blocky_y", 1)); - m_Params.push_back(ParamWithName(&m_Mp, prefix + "blocky_mp", 4)); + m_Params.push_back(ParamWithName(&m_Mp, prefix + "blocky_mp", 4, REAL_NONZERO)); m_Params.push_back(ParamWithName(true, &m_V, prefix + "blocky_v"));//Precalc. m_Params.push_back(ParamWithName(true, &m_Vx, prefix + "blocky_vx")); m_Params.push_back(ParamWithName(true, &m_Vy, prefix + "blocky_vy")); @@ -5189,7 +5235,7 @@ MAKEPREPOSTPARVAR(Blocky, blocky, BLOCKY) // virtual string OpenCLString() // { // ostringstream ss; -// int i = 0, varIndex = IndexInXform(); +// int varIndex = IndexInXform(); // // ss << "\t{\n" // << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x;\n" @@ -5220,7 +5266,7 @@ MAKEPREPOSTPARVAR(Blocky, blocky, BLOCKY) // virtual string OpenCLString() // { // ostringstream ss; -// int i = 0, varIndex = IndexInXform(); +// int varIndex = IndexInXform(); // // ss << "\t{\n" // << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * vIn.y;\n" diff --git a/Source/Ember/Variations05.h b/Source/Ember/Variations05.h index d721b32..fe31342 100644 --- a/Source/Ember/Variations05.h +++ b/Source/Ember/Variations05.h @@ -99,7 +99,7 @@ public: int n = Floor(T(0.5) * helper.In.y / m_Sc); T x = helper.In.x - (m * 2 + 1) * m_Sc; T y = helper.In.y - (n * 2 + 1) * m_Sc; - T u = Hypot(x, y); + T u = Zeps(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); @@ -139,6 +139,7 @@ public: 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 = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -161,7 +162,7 @@ public: << "\t\tint n = (int)floor(0.5 * vIn.y / " << sc << ");\n" << "\t\treal_t x = vIn.x - (m * 2 + 1) * " << sc << ";\n" << "\t\treal_t y = vIn.y - (n * 2 + 1) * " << sc << ";\n" - << "\t\treal_t u = Hypot(x, y);\n" + << "\t\treal_t u = Zeps(Hypot(x, y));\n" << "\t\treal_t v = (0.3 + 0.7 * CircleLinearDiscreteNoise2(m + 10, n + 3)) * " << sc << ";\n" << "\t\treal_t z1 = CircleLinearDiscreteNoise2((int)(m + " << seed << "), n);\n" << "\n" @@ -201,6 +202,7 @@ public: << "\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (x + (m * 2 + 1) * " << sc << ");\n" << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * (y + (n * 2 + 1) * " << sc << ");\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -227,7 +229,7 @@ protected: string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_Sc, prefix + "CircleLinear_Sc", 1)); + m_Params.push_back(ParamWithName(&m_Sc, prefix + "CircleLinear_Sc", 1, REAL_NONZERO)); m_Params.push_back(ParamWithName(&m_K, prefix + "CircleLinear_K", T(0.5))); m_Params.push_back(ParamWithName(&m_Dens1, prefix + "CircleLinear_Dens1", T(0.5))); m_Params.push_back(ParamWithName(&m_Dens2, prefix + "CircleLinear_Dens2", T(0.5))); @@ -295,6 +297,7 @@ public: 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 = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -330,6 +333,7 @@ public: << "\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (x + (m * 2 + 1) * " << sc << ");\n" << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * (y + (n * 2 + 1) * " << sc << ");\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -356,7 +360,7 @@ protected: string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_Sc, prefix + "CircleRand_Sc", 1)); + m_Params.push_back(ParamWithName(&m_Sc, prefix + "CircleRand_Sc", 1, REAL_NONZERO)); m_Params.push_back(ParamWithName(&m_Dens, prefix + "CircleRand_Dens", T(0.5))); m_Params.push_back(ParamWithName(&m_X, prefix + "CircleRand_X", 10)); m_Params.push_back(ParamWithName(&m_Y, prefix + "CircleRand_Y", 10)); @@ -421,6 +425,7 @@ public: helper.Out.x = m_Weight * ux; helper.Out.y = m_Weight * uy; + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -459,6 +464,7 @@ public: << "\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * ux;\n" << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * uy;\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -516,7 +522,7 @@ protected: string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_Sc, prefix + "CircleTrans1_Sc", 1)); + m_Params.push_back(ParamWithName(&m_Sc, prefix + "CircleTrans1_Sc", 1, REAL_NONZERO)); m_Params.push_back(ParamWithName(&m_Dens, prefix + "CircleTrans1_Dens", T(0.5))); m_Params.push_back(ParamWithName(&m_X, prefix + "CircleTrans1_X", 10)); m_Params.push_back(ParamWithName(&m_Y, prefix + "CircleTrans1_Y", 10)); @@ -1034,7 +1040,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t expx = exp(vIn.x) * 0.5;\n" @@ -1070,10 +1076,6 @@ public: T uu = SQR(helper.In.x); T vv = SQR(helper.In.y); T ww = SQR(helper.In.z); - T alpha = (vv + uu + EPS6); - T beta = (uu + ww + EPS6); - T delta = (vv + ww + EPS6); - T epsilon = (vv + uu + ww + EPS6); T atOmegaX = atan2(vv, ww); T atOmegaY = atan2(uu, ww); T atOmegaZ = atan2(vv, uu); @@ -1083,9 +1085,9 @@ public: T cv = cos(helper.In.y); T cucv = cu * cv; T sucv = su * cv; - T x = pow(ClampGte(cucv, EPS6), m_XPow) + (cucv * m_XPow) + (T(0.25) * atOmegaX);//Must clamp first argument to pow, because negative values will return NaN. - T y = pow(ClampGte(sucv, EPS6), m_YPow) + (sucv * m_YPow) + (T(0.25) * atOmegaY);//Original did not do this and would frequently return bad values. - T z = pow(ClampGte(sv, EPS6), m_ZPow) + sv * m_ZPow; + T x = pow(ClampGte(cucv, EPS), m_XPow) + (cucv * m_XPow) + (T(0.25) * atOmegaX);//Must clamp first argument to pow, because negative values will return NaN. + T y = pow(ClampGte(sucv, EPS), m_YPow) + (sucv * m_YPow) + (T(0.25) * atOmegaY);//Original did not do this and would frequently return bad values. + T z = pow(ClampGte(sv, EPS), m_ZPow) + sv * m_ZPow; helper.Out.x = m_Weight * x; helper.Out.y = m_Weight * y; @@ -1106,10 +1108,6 @@ public: << "\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 alpha = (vv + uu + EPS6);\n" - << "\t\treal_t beta = (uu + ww + EPS6);\n" - << "\t\treal_t delta = (vv + ww + EPS6);\n" - << "\t\treal_t epsilon = (vv + uu + ww + EPS6);\n" << "\t\treal_t atOmegaX = atan2(vv, ww);\n" << "\t\treal_t atOmegaY = atan2(uu, ww);\n" << "\t\treal_t atOmegaZ = atan2(vv, uu);\n" @@ -1119,9 +1117,9 @@ public: << "\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(ClampGte(cucv, EPS6), " << xpow << ") + (cucv * " << xpow << ") + (0.25 * atOmegaX);\n" - << "\t\treal_t y = pow(ClampGte(sucv, EPS6), " << ypow << ") + (sucv * " << ypow << ") + (0.25 * atOmegaY);\n" - << "\t\treal_t z = pow(ClampGte(sv, EPS6), " << zpow << ") + sv * " << zpow << ";\n" + << "\t\treal_t x = pow(ClampGte(cucv, EPS), " << xpow << ") + (cucv * " << xpow << ") + (0.25 * atOmegaX);\n" + << "\t\treal_t y = pow(ClampGte(sucv, EPS), " << ypow << ") + (sucv * " << ypow << ") + (0.25 * atOmegaY);\n" + << "\t\treal_t z = pow(ClampGte(sv, EPS), " << zpow << ") + sv * " << zpow << ";\n" << "\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * x;\n" << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * y;\n" @@ -1431,6 +1429,7 @@ public: 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 = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -1452,6 +1451,7 @@ public: << "\t\tvOut.y = vIn.y * r * " << y << ";\n" << "\t\tvOut.x += (1 - (" << twist << " * SQR(vIn.x)) + vIn.y) * xform->m_VariationWeights[" << varIndex << "];\n" << "\t\tvOut.y += " << tilt << " * vIn.x * xform->m_VariationWeights[" << varIndex << "];\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -1740,7 +1740,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * sin(vIn.x);\n" @@ -1800,7 +1800,7 @@ public: virtual void Precalc() { - m_InvWeight = 1 / (m_Weight + EPS6); + m_InvWeight = 1 / Zeps(m_Weight); } protected: @@ -1836,10 +1836,12 @@ public: 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; + //outPoint.m_X = 0; + //outPoint.m_Y = 0; } virtual string OpenCLString() @@ -1968,6 +1970,7 @@ public: helper.Out.x += helper.In.x * m_Px; helper.Out.y += helper.In.y * m_Py; + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -1976,10 +1979,10 @@ public: int i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); - 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; + 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 = xform->m_VariationWeights[" << varIndex << "] / (precalcSumSquares * 0.25 + 1);\n" @@ -2028,6 +2031,7 @@ public: << "\n" << "\t\tvOut.x += vIn.x * " << px << ";\n" << "\t\tvOut.y += vIn.y * " << py << ";\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -2073,12 +2077,13 @@ public: helper.Out.x = m_Weight * r * cos(a); helper.Out.y = m_Weight * r * sin(a); + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t a = M_PI / (precalcSqrtSumSquares + 1);\n" @@ -2089,6 +2094,7 @@ public: << "\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * r * cos(a);\n" << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * r * sin(a);\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); @@ -2227,7 +2233,7 @@ protected: string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_Scatter, prefix + "falloff_scatter", 1, REAL, EPS6, TMAX)); + m_Params.push_back(ParamWithName(&m_Scatter, prefix + "falloff_scatter", 1, REAL, EPS, TMAX)); m_Params.push_back(ParamWithName(&m_MinDist, prefix + "falloff_mindist", T(0.5), REAL, 0, TMAX)); m_Params.push_back(ParamWithName(&m_MulX, prefix + "falloff_mul_x", 1, REAL, 0, 1)); m_Params.push_back(ParamWithName(&m_MulY, prefix + "falloff_mul_y", 1, REAL, 0, 1)); @@ -2350,7 +2356,6 @@ public: string rMax = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" - << "\t\tconst real_t randx = MwcNextNeg1Pos1(mwc);\n" << "\t\tconst real_t randy = MwcNextNeg1Pos1(mwc);\n" << "\t\tconst real_t randz = MwcNextNeg1Pos1(mwc);\n" @@ -2424,7 +2429,7 @@ protected: string prefix = Prefix(); m_Params.clear(); - m_Params.push_back(ParamWithName(&m_Scatter, prefix + "falloff2_scatter", 1, REAL, EPS6, TMAX)); + m_Params.push_back(ParamWithName(&m_Scatter, prefix + "falloff2_scatter", 1, REAL, EPS, TMAX)); m_Params.push_back(ParamWithName(&m_MinDist, prefix + "falloff2_mindist", T(0.5), REAL, 0, TMAX)); m_Params.push_back(ParamWithName(&m_MulX, prefix + "falloff2_mul_x", 1, REAL, 0, 1)); m_Params.push_back(ParamWithName(&m_MulY, prefix + "falloff2_mul_y", 1, REAL, 0, 1)); @@ -2528,7 +2533,7 @@ public: break; case 2://Log. { - const T coeff = m_RMax <= EPS6 ? dist : dist + m_Alpha * (LogMap(dist) - dist); + const T coeff = m_RMax <= EPS ? dist : dist + m_Alpha * (LogMap(dist) - dist); helper.Out.x = helper.In.x + LogMap(m_MulX) * LogScale(random.x) * coeff, helper.Out.y = helper.In.y + LogMap(m_MulY) * LogScale(random.y) * coeff, @@ -2623,7 +2628,7 @@ public: << "\t\t break;\n" << "\t\tcase 2:\n" << "\t\t {\n" - << "\t\t real_t coeff = " << rMax << " <= EPS6 ? dist : dist + " << alpha << " * (LogMap(dist) - dist);\n" + << "\t\t real_t coeff = " << rMax << " <= EPS ? dist : dist + " << alpha << " * (LogMap(dist) - dist);\n" << "\n" << "\t\t vOut.x = vIn.x + LogMap(" << mulX << ") * LogScale(randx) * coeff,\n" << "\t\t vOut.y = vIn.y + LogMap(" << mulY << ") * LogScale(randy) * coeff,\n" @@ -2650,7 +2655,7 @@ protected: m_Params.clear(); m_Params.push_back(ParamWithName(&m_BlurType, prefix + "falloff3_blur_type", 0, INTEGER, 0, 3)); m_Params.push_back(ParamWithName(&m_BlurShape, prefix + "falloff3_blur_shape", 0, INTEGER, 0, 1)); - m_Params.push_back(ParamWithName(&m_BlurStrength, prefix + "falloff3_blur_strength", 1, REAL, EPS6, TMAX)); + m_Params.push_back(ParamWithName(&m_BlurStrength, prefix + "falloff3_blur_strength", 1, REAL, EPS, TMAX)); m_Params.push_back(ParamWithName(&m_MinDistance, prefix + "falloff3_min_distance", T(0.5), REAL, 0, TMAX)); m_Params.push_back(ParamWithName(&m_InvertDistance, prefix + "falloff3_invert_distance", 0, INTEGER, 0, 1)); m_Params.push_back(ParamWithName(&m_MulX, prefix + "falloff3_mul_x", 1, REAL, 0, 1)); @@ -2729,6 +2734,7 @@ public: InverseTrilinear(alpha, beta, x, y, rand); helper.Out.x = m_Weight * x; helper.Out.y = m_Weight * y; + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } virtual string OpenCLString() @@ -2850,6 +2856,7 @@ public: << "\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * x;\n" << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * y;\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t}\n"; return ss.str(); diff --git a/Source/Ember/VariationsDC.h b/Source/Ember/VariationsDC.h index 946f900..9a2f943 100644 --- a/Source/Ember/VariationsDC.h +++ b/Source/Ember/VariationsDC.h @@ -114,6 +114,7 @@ public: helper.Out.x = m_Weight * (m_Xform->m_Affine.A() * x + m_Xform->m_Affine.B() * y + m_Xform->m_Affine.E()); helper.Out.y = m_Weight * (m_Xform->m_Affine.C() * x + m_Xform->m_Affine.D() * y + m_Xform->m_Affine.F()); + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; outPoint.m_ColorX = fmod(fabs(outPoint.m_ColorX * T(0.5) * (1 + h) + x0_xor_y0 * (1 - h) * T(0.5)), T(1.0)); } @@ -136,6 +137,7 @@ public: << "\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (xform->m_A * x + xform->m_B * y + xform->m_E);\n" << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * (xform->m_C * x + xform->m_D * y + xform->m_F);\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" << "\t\toutPoint->m_ColorX = fmod(fabs(outPoint->m_ColorX * 0.5 * (1 + h) + x0_xor_y0 * (1 - h) * 0.5), 1.0);\n" << "\t}\n"; @@ -548,7 +550,7 @@ public: virtual string OpenCLString() { ostringstream ss; - int i = 0, varIndex = IndexInXform(); + int varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t x = LRint(vIn.x);\n" @@ -1001,7 +1003,7 @@ public: { m_X0_ = m_X0 < m_X1 ? m_X0 : m_X1; m_X1_ = m_X0 > m_X1 ? m_X0 : m_X1; - m_X1_m_x0 = m_X1_ - m_X0_ == 0 ? EPS6 : m_X1_ - m_X0_; + m_X1_m_x0 = Zeps(m_X1_ - m_X0_); } protected: diff --git a/Source/Ember/Xform.h b/Source/Ember/Xform.h index a181c02..aabe4dd 100644 --- a/Source/Ember/Xform.h +++ b/Source/Ember/Xform.h @@ -267,6 +267,17 @@ public: if (vec->size() < MAX_VARS_PER_XFORM) { vec->push_back(variation); + + //Flatten must always be last. + for (size_t i = 0; i < vec->size(); i++) + { + if ((i != vec->size() - 1) && ((*vec)[i]->Name().find("flatten") != string::npos)) + { + std::swap((*vec)[i], (*vec)[vec->size() - 1]); + break; + } + } + SetPrecalcFlags(); return true; } @@ -540,8 +551,8 @@ public: { T norm = 0; - std::for_each(variations.begin(), variations.end(), [&](Variation* var) { norm += var->m_Weight; }); - std::for_each(variations.begin(), variations.end(), [&](Variation* var) { var->m_Weight /= norm; }); + ForEach(variations, [&](Variation* var) { norm += var->m_Weight; }); + ForEach(variations, [&](Variation* var) { var->m_Weight /= norm; }); }); } @@ -843,8 +854,8 @@ public: if (m_NeedPrecalcAngles) { - helper.m_PrecalcSina = helper.m_TransX / helper.m_PrecalcSqrtSumSquares; - helper.m_PrecalcCosa = helper.m_TransY / helper.m_PrecalcSqrtSumSquares; + helper.m_PrecalcSina = helper.m_TransX / Zeps(helper.m_PrecalcSqrtSumSquares); + helper.m_PrecalcCosa = helper.m_TransY / Zeps(helper.m_PrecalcSqrtSumSquares); } } } @@ -856,6 +867,68 @@ public: helper.m_PrecalcAtanyx = atan2(helper.m_TransY, helper.m_TransX); } + /// + /// Flatten this xform by adding a flatten variation if none is present, and if any of the + /// variations or parameters in the vector are present. + /// + /// Vector of variation and parameter names + /// True if flatten was added, false if it already was present or if none of the specified variations or parameters were present. + bool Flatten(vector& names) + { + bool shouldFlatten = true; + + if (GetVariationById(VAR_FLATTEN) == NULL) + { + AllVarsFunc([&] (vector*>& variations, bool& keepGoing) + { + for (size_t i = 0; i < variations.size(); i++) + { + Variation* var = variations[i]; + + if (var->m_Weight != 0)//This should never happen, but just to be safe. + { + if (FindIf(names, [&] (const string& s) -> bool { return !_stricmp(s.c_str(), var->Name().c_str()); })) + { + shouldFlatten = false; + keepGoing = false; + break; + } + } + + //Now traverse the parameters for this variation. + if (ParametricVariation* parVar = dynamic_cast*>(var)) + { + ForEach(names, [&] (const string& s) + { + if (parVar->GetParamVal(s.c_str()) != 0) + { + shouldFlatten = false; + keepGoing = false; + } + }); + } + } + }); + + if (shouldFlatten) + { + Variation* var = new FlattenVariation(); + + if (AddVariation(var)) + { + return true; + } + else + { + delete var; + return false; + } + } + } + + return false; + } + /// /// Generate the OpenCL string for reading input values to /// be passed to a variation. diff --git a/Source/Ember/XmlToEmber.h b/Source/Ember/XmlToEmber.h index d7bce7b..60423c6 100644 --- a/Source/Ember/XmlToEmber.h +++ b/Source/Ember/XmlToEmber.h @@ -75,6 +75,7 @@ public: if (!m_Init) { + m_BadParamNames.reserve(100); m_BadParamNames.push_back(pair("swtin_distort", "stwin_distort"));//stwin. m_BadParamNames.push_back(pair("pow_numerator", "pow_block_numerator"));//pow_block. m_BadParamNames.push_back(pair("pow_denominator", "pow_block_denominator")); @@ -130,9 +131,111 @@ public: m_BadParamNames.push_back(pair("mobius_rect_y", "mobius_strip_rect_y")); m_BadParamNames.push_back(pair("mobius_rotate_x", "mobius_strip_rotate_x")); m_BadParamNames.push_back(pair("mobius_rotate_y", "mobius_strip_rotate_y")); + m_BadParamNames.push_back(pair("bwraps2_cellsize", "bwraps_cellsize"));//bwraps2. + m_BadParamNames.push_back(pair("bwraps2_space", "bwraps_space")); + m_BadParamNames.push_back(pair("bwraps2_gain", "bwraps_gain")); + m_BadParamNames.push_back(pair("bwraps2_inner_twist", "bwraps_inner_twist")); + m_BadParamNames.push_back(pair("bwraps2_outer_twist", "bwraps_outer_twist")); + m_BadParamNames.push_back(pair("bwraps7_cellsize", "bwraps_cellsize"));//bwraps7. + m_BadParamNames.push_back(pair("bwraps7_space", "bwraps_space")); + m_BadParamNames.push_back(pair("bwraps7_gain", "bwraps_gain")); + m_BadParamNames.push_back(pair("bwraps7_inner_twist", "bwraps_inner_twist")); + m_BadParamNames.push_back(pair("bwraps7_outer_twist", "bwraps_outer_twist")); + m_BadParamNames.push_back(pair("pre_bwraps2_cellsize", "pre_bwraps_cellsize")); + m_BadParamNames.push_back(pair("pre_bwraps2_space", "pre_bwraps_space")); + m_BadParamNames.push_back(pair("pre_bwraps2_gain", "pre_bwraps_gain")); + m_BadParamNames.push_back(pair("pre_bwraps2_inner_twist", "pre_bwraps_inner_twist")); + m_BadParamNames.push_back(pair("pre_bwraps2_outer_twist", "pre_bwraps_outer_twist")); + m_BadParamNames.push_back(pair("post_bwraps2_cellsize", "post_bwraps_cellsize")); + m_BadParamNames.push_back(pair("post_bwraps2_space", "post_bwraps_space")); + m_BadParamNames.push_back(pair("post_bwraps2_gain", "post_bwraps_gain")); + m_BadParamNames.push_back(pair("post_bwraps2_inner_twist", "post_bwraps_inner_twist")); + m_BadParamNames.push_back(pair("post_bwraps2_outer_twist", "post_bwraps_outer_twist")); + + m_FlattenNames.reserve(24); + m_FlattenNames.push_back("linear3D"); + m_FlattenNames.push_back("bubble"); + m_FlattenNames.push_back("cylinder"); + m_FlattenNames.push_back("zblur"); + m_FlattenNames.push_back("blur3D"); + m_FlattenNames.push_back("pre_ztranslate"); + m_FlattenNames.push_back("pre_rotate_x"); + m_FlattenNames.push_back("pre_rotate_y"); + m_FlattenNames.push_back("ztranslate"); + m_FlattenNames.push_back("zcone"); + m_FlattenNames.push_back("post_rotate_x"); + m_FlattenNames.push_back("post_rotate_y"); + m_FlattenNames.push_back("julia3D"); + m_FlattenNames.push_back("julia3Dz"); + m_FlattenNames.push_back("curl3D_cz"); + m_FlattenNames.push_back("hemisphere"); + m_FlattenNames.push_back("bwraps"); + m_FlattenNames.push_back("bwraps2"); + m_FlattenNames.push_back("falloff2"); + m_FlattenNames.push_back("crop"); + m_FlattenNames.push_back("pre_falloff2"); + m_FlattenNames.push_back("pre_crop"); + m_FlattenNames.push_back("post_falloff2"); + m_FlattenNames.push_back("post_crop"); + + //This is a vector of the param names as they are in the legacy, badly named flam3/Apophysis code. + vector badParams; + + badParams.reserve(6); + + badParams.push_back("bwraps7_cellsize"); + badParams.push_back("bwraps7_space"); + badParams.push_back("bwraps7_gain"); + badParams.push_back("bwraps7_inner_twist"); + badParams.push_back("bwraps7_outer_twist"); + m_BadVariationNames.push_back(make_pair(make_pair(string("bwraps7"), string("bwraps")), badParams));//bwraps7 is the same as bwraps. + badParams.clear(); + + badParams.push_back("bwraps2_cellsize"); + badParams.push_back("bwraps2_space"); + badParams.push_back("bwraps2_gain"); + badParams.push_back("bwraps2_inner_twist"); + badParams.push_back("bwraps2_outer_twist"); + m_BadVariationNames.push_back(make_pair(make_pair(string("bwraps2"), string("bwraps")), badParams));//bwraps2 is the same as bwraps. + badParams.clear(); + + badParams.push_back("pre_bwraps2_cellsize"); + badParams.push_back("pre_bwraps2_space"); + badParams.push_back("pre_bwraps2_gain"); + badParams.push_back("pre_bwraps2_inner_twist"); + badParams.push_back("pre_bwraps2_outer_twist"); + m_BadVariationNames.push_back(make_pair(make_pair(string("pre_bwraps2"), string("pre_bwraps")), badParams)); + badParams.clear(); + + badParams.push_back("post_bwraps2_cellsize"); + badParams.push_back("post_bwraps2_space"); + badParams.push_back("post_bwraps2_gain"); + badParams.push_back("post_bwraps2_inner_twist"); + badParams.push_back("post_bwraps2_outer_twist"); + m_BadVariationNames.push_back(make_pair(make_pair(string("post_bwraps2"), string("post_bwraps")), badParams)); + badParams.clear(); + + badParams.push_back("mobius_radius"); + badParams.push_back("mobius_width"); + badParams.push_back("mobius_rect_x"); + badParams.push_back("mobius_rect_y"); + badParams.push_back("mobius_rotate_x"); + badParams.push_back("mobius_rotate_y"); + m_BadVariationNames.push_back(make_pair(make_pair(string("mobius"), string("mobius_strip")), badParams));//mobius_strip clashes with Mobius. + badParams.clear(); + + badParams.push_back("post_dcztransl_x0"); + badParams.push_back("post_dcztransl_x1"); + badParams.push_back("post_dcztransl_factor"); + badParams.push_back("post_dcztransl_overwrite"); + badParams.push_back("post_dcztransl_clamp"); + m_BadVariationNames.push_back(make_pair(make_pair(string("post_dcztransl"), string("post_dc_ztransl")), badParams)); + badParams.clear(); + + m_BadVariationNames.push_back(make_pair(make_pair(string("pre_blur"), string("pre_gaussian_blur")), badParams)); + m_BadVariationNames.push_back(make_pair(make_pair(string("pre_spin_z"), string("pre_rotate_z")), badParams)); + m_BadVariationNames.push_back(make_pair(make_pair(string("post_spin_z"), string("post_rotate_z")), badParams)); - m_BadVariationNames.push_back(pair("post_dcztransl", "post_dc_ztransl"));//dc_ztransl. - m_BadVariationNames.push_back(pair("mobius", "mobius_strip"));//mobius_strip, case sensitive to not clash with Mobius. m_Init = true; } } @@ -360,6 +463,8 @@ public: return string(ch); } + static vector m_FlattenNames; + private: /// /// Scan the file for ember nodes, and parse them out into the vector of embers. @@ -425,6 +530,7 @@ private: bool ParseEmberElement(xmlNode* emberNode, Ember& currentEmber) { bool b = true; + unsigned int newLinear = 0; char* attStr; const char* loc = __FUNCTION__; int soloXform = -1; @@ -475,36 +581,37 @@ private: else if (ParseAndAssignInt(curAtt->name, attStr, "oversample", currentEmber.m_Supersample , b)) { } else if (ParseAndAssignInt(curAtt->name, attStr, "supersample", currentEmber.m_Supersample , b)) { } else if (ParseAndAssignInt(curAtt->name, attStr, "temporal_samples", currentEmber.m_TemporalSamples, b)) { } - else if (ParseAndAssignInt(curAtt->name, attStr, "soloxform", soloXform , b)) { } + else if (ParseAndAssignInt(curAtt->name, attStr, "soloxform", soloXform , b)) { } + else if (ParseAndAssignInt(curAtt->name, attStr, "new_linear", newLinear , b)) { } //Parse more complicated reads that have multiple possible values. else if (!Compare(curAtt->name, "interpolation")) { - if (!strcmp("linear", attStr)) + if (!_stricmp("linear", attStr)) currentEmber.m_Interp = EMBER_INTERP_LINEAR; - else if (!strcmp("smooth", attStr)) + else if (!_stricmp("smooth", attStr)) currentEmber.m_Interp = EMBER_INTERP_SMOOTH; else m_ErrorReport.push_back(string(loc) + " : Unrecognized interpolation type " + string(attStr)); } else if (!Compare(curAtt->name, "palette_interpolation")) { - if (!strcmp("hsv", attStr)) + if (!_stricmp("hsv", attStr)) currentEmber.m_PaletteInterp = INTERP_HSV; - else if (!strcmp("sweep", attStr)) + else if (!_stricmp("sweep", attStr)) currentEmber.m_PaletteInterp = INTERP_SWEEP; else m_ErrorReport.push_back(string(loc) + " : Unrecognized palette interpolation type " + string(attStr)); } else if (!Compare(curAtt->name, "interpolation_space") || !Compare(curAtt->name, "interpolation_type")) { - if (!strcmp("linear", attStr)) + if (!_stricmp("linear", attStr)) currentEmber.m_AffineInterp = INTERP_LINEAR; - else if (!strcmp("log", attStr)) + else if (!_stricmp("log", attStr)) currentEmber.m_AffineInterp = INTERP_LOG; - else if (!strcmp("old", attStr)) + else if (!_stricmp("old", attStr)) currentEmber.m_AffineInterp = INTERP_COMPAT; - else if (!strcmp("older", attStr)) + else if (!_stricmp("older", attStr)) currentEmber.m_AffineInterp = INTERP_OLDER; else m_ErrorReport.push_back(string(loc) + " : Unrecognized interpolation type " + string(attStr)); @@ -551,9 +658,9 @@ private: } else if (!Compare(curAtt->name, "palette_mode")) { - if (!strcmp("step", attStr)) + if (!_stricmp("step", attStr)) currentEmber.m_PaletteMode = PALETTE_STEP; - else if (!strcmp("linear", attStr)) + else if (!_stricmp("linear", attStr)) currentEmber.m_PaletteMode = PALETTE_LINEAR; else { @@ -750,9 +857,9 @@ private: { newFormat = true; - if (!strcmp(attStr, "RGB")) + if (!_stricmp(attStr, "RGB")) numBytes = 3; - else if (!strcmp(attStr, "RGBA")) + else if (!_stricmp(attStr, "RGBA")) numBytes = 4; else { @@ -898,6 +1005,9 @@ private: } } + //if (!newLinear) + // currentEmber.Flatten(m_FlattenNames); + for (i = 0; i < currentEmber.XformCount(); i++) if (soloXform >= 0 && i != soloXform) currentEmber.GetXform(i)->m_Opacity = 0;//Will calc the cached adjusted viz value later. @@ -963,11 +1073,11 @@ private: } else if (!Compare(curAtt->name, "motion_function")) { - if (!strcmp("sin", attStr)) + if (!_stricmp("sin", attStr)) xform.m_MotionFunc = MOTION_SIN; - else if (!strcmp("triangle", attStr)) + else if (!_stricmp("triangle", attStr)) xform.m_MotionFunc = MOTION_TRIANGLE; - else if (!strcmp("hill", attStr)) + else if (!_stricmp("hill", attStr)) xform.m_MotionFunc = MOTION_HILL; else { @@ -1013,7 +1123,7 @@ private: { m_ErrorReport.push_back(string(loc) + " : Motion element cannot have a plotmode attribute"); } - else if (!strcmp("off", attStr)) + else if (!_stricmp("off", attStr)) xform.m_Opacity = 0; } else if (!Compare(curAtt->name, "coefs")) @@ -1048,7 +1158,7 @@ private: } else { - string s = GetCorrectedName(m_BadVariationNames, (const char*)curAtt->name); + string s = GetCorrectedVariationName(m_BadVariationNames, curAtt); const char* name = s.c_str(); if (Variation* var = m_VariationList.GetVariation(s)) @@ -1130,7 +1240,7 @@ private: { for (curAtt = attPtr; curAtt; curAtt = curAtt->next) { - string s = GetCorrectedName(m_BadParamNames, (const char*)curAtt->name); + string s = GetCorrectedParamName(m_BadParamNames, (const char*)curAtt->name); const char* name = s.c_str(); if (parVar->ContainsParam(name)) @@ -1160,17 +1270,72 @@ private: /// Some Apophysis plugins use an inconsistent naming scheme for the parametric variation variables. /// This function identifies and converts them to Ember's consistent naming convention. /// - /// The name of the variable found in the Xml + /// The vector of corrected names to search + /// The current Xml node to check /// The corrected name if one was found, else the passed in name. - static string GetCorrectedName(vector>& vec, const char* name) + static string GetCorrectedParamName(vector>& vec, const char* name) { for (size_t i = 0; i < vec.size(); i++) - if (!strcmp(vec[i].first.c_str(), name))//Case sensitive is intentional. + { + if (!_stricmp(vec[i].first.c_str(), name)) return vec[i].second; + } return name; } + /// + /// Some Apophysis plugins use an inconsistent naming scheme for variation names. + /// This function identifies and converts them to Ember's consistent naming convention. + /// It uses some additional intelligence to ensure the variation is the expected one, + /// by examining the rest of the xform for the existence of parameter names. + /// + /// The vector of corrected names to search + /// The current Xml node to check + /// The corrected name if one was found, else the passed in name. + static string GetCorrectedVariationName(vector, vector>>& vec, xmlAttrPtr att) + { + for (size_t i = 0; i < vec.size(); i++) + { + if (!_stricmp(vec[i].first.first.c_str(), (const char*)att->name))//Do case insensitive here. + { + if (!vec[i].second.empty()) + { + for (size_t j = 0; j < vec[i].second.size(); j++) + { + if (XmlContainsTag(att, vec[i].second[j].c_str())) + return vec[i].first.second; + } + } + else + { + return vec[i].first.second; + } + } + } + + return string((const char*)att->name); + } + + /// + /// Determine if an Xml node contains a given tag. + /// + /// The Xml node to search + /// The node name to search for + /// True if name was found, else false. + static bool XmlContainsTag(xmlAttrPtr att, const char* name) + { + xmlAttrPtr temp = att; + + do + { + if (!_stricmp(name, (const char*)temp->name)) + return true; + } while (temp = temp->next); + + return false; + } + /// /// Parse hexadecimal colors. /// This can read RGB and RGBA, however only RGB will be stored. @@ -1331,10 +1496,12 @@ private: bool ParseAndAssignInt(const xmlChar* name, char* attStr, char* str, int& val, bool& b) { bool ret = false; + T fval = 0; if (!Compare(name, str)) { - b &= Atoi(attStr, val); + b &= Atof(attStr, fval); + val = (int)fval; ret = true;//Means the strcmp() was right, but doesn't necessarily mean the conversion went ok. } @@ -1343,7 +1510,7 @@ private: static bool m_Init; static vector> m_BadParamNames; - static vector> m_BadVariationNames; + static vector, vector>> m_BadVariationNames; VariationList m_VariationList;//The variation list used to make copies of variations to populate the embers with. PaletteList m_PaletteList; }; diff --git a/Source/EmberAnimate/EmberAnimate.rc b/Source/EmberAnimate/EmberAnimate.rc index 29fd2cd..d68b6fb 100644 --- a/Source/EmberAnimate/EmberAnimate.rc +++ b/Source/EmberAnimate/EmberAnimate.rc @@ -49,8 +49,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,4,0,4 - PRODUCTVERSION 0,4,0,4 + FILEVERSION 0,4,0,5 + PRODUCTVERSION 0,4,0,5 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -67,12 +67,12 @@ BEGIN BEGIN VALUE "CompanyName", "Open Source" VALUE "FileDescription", "Renders fractal flames as animations with motion blur" - VALUE "FileVersion", "0.4.0.4" + VALUE "FileVersion", "0.4.0.5" VALUE "InternalName", "EmberAnimate.rc" VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2013, GPL v3" VALUE "OriginalFilename", "EmberAnimate.rc" VALUE "ProductName", "Ember Animate" - VALUE "ProductVersion", "0.4.0.4" + VALUE "ProductVersion", "0.4.0.5" END END BLOCK "VarFileInfo" diff --git a/Source/EmberCL/EmberCLFunctions.h b/Source/EmberCL/EmberCLFunctions.h index 735588c..bdd1782 100644 --- a/Source/EmberCL/EmberCLFunctions.h +++ b/Source/EmberCL/EmberCLFunctions.h @@ -168,8 +168,8 @@ static const char* RandFunctionString = "\n" "inline real_t MwcNextNeg1Pos1(uint2* s)\n" "{\n" - " real_t f = (real_t)MwcNext(s) / UINT_MAX;\n" - " return -1.0 + (f * (1.0 - (-1.0)));\n" + " real_t f = (real_t)MwcNext(s) / (real_t)UINT_MAX;\n" + " return -1.0 + (f * 2.0);\n" "}\n" "\n"; @@ -266,7 +266,7 @@ static const char* InlineMathFunctionsString = "\n" "inline real_t Zeps(real_t x)\n" "{\n" - " return x == 0.0 ? EPS6 : x;\n" + " return x == 0.0 ? EPS : x;\n" "}\n" "\n" "inline real_t Lerp(real_t a, real_t b, real_t p)\n" diff --git a/Source/EmberCL/EmberCLPch.h b/Source/EmberCL/EmberCLPch.h index c1492b4..8d1393f 100644 --- a/Source/EmberCL/EmberCLPch.h +++ b/Source/EmberCL/EmberCLPch.h @@ -36,4 +36,5 @@ using namespace std; using namespace EmberNs; -//#define TEST_CL 1 \ No newline at end of file +//#define TEST_CL 1 +//#define TEST_CL_BUFFERS 1 \ No newline at end of file diff --git a/Source/EmberCL/EmberCLStructs.h b/Source/EmberCL/EmberCLStructs.h index 8d606f6..49a2a2f 100644 --- a/Source/EmberCL/EmberCLStructs.h +++ b/Source/EmberCL/EmberCLStructs.h @@ -35,21 +35,24 @@ static string ConstantDefinesString(bool doublePrecision) << "typedef long intPrec;\n" << "typedef ulong atomi;\n" << "typedef double real_t;\n" - << "typedef double4 real4;\n"; + << "typedef double4 real4;\n" + << "#define EPS (DBL_EPSILON)\n" + ; } else { os << "typedef int intPrec;\n" "typedef unsigned int atomi;\n" "typedef float real_t;\n" - "typedef float4 real4;\n"; + "typedef float4 real4;\n" + "#define EPS (FLT_EPSILON)\n" + ; } os << "typedef long int int64;\n" "typedef unsigned long int uint64;\n" "\n" - "#define EPS ((1e-10))\n"//May need to change this, it might not be enough in some cases. Maybe try 1e-9 if things look funny when close to zero. "#define EPS6 ((1e-6))\n" "\n" "//The number of threads per block used in the iteration function. Don't change\n" @@ -122,7 +125,7 @@ struct ALIGN PointCL T m_Y; T m_Z; T m_ColorX; - T m_LastXfUsed; + unsigned int m_LastXfUsed; }; /// @@ -188,7 +191,6 @@ static const char* XformCLStructString = template struct ALIGN EmberCL { - unsigned int m_FinalXformIndex; XformCL m_Xforms[MAX_CL_XFORM]; T m_CamZPos; T m_CamPerspective; @@ -207,7 +209,6 @@ struct ALIGN EmberCL static const char* EmberCLStructString = "typedef struct __attribute__ " ALIGN_CL " _EmberCL\n" "{\n" -" uint m_FinalXformIndex;\n" " XformCL m_Xforms[" MAX_CL_XFORM_STRING "];\n" " real_t m_CamZPos;\n" " real_t m_CamPerspective;\n" diff --git a/Source/EmberCL/IterOpenCLKernelCreator.cpp b/Source/EmberCL/IterOpenCLKernelCreator.cpp index 8f4339c..7542f22 100644 --- a/Source/EmberCL/IterOpenCLKernelCreator.cpp +++ b/Source/EmberCL/IterOpenCLKernelCreator.cpp @@ -52,7 +52,7 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin xformFuncs << "\n" << parVarDefines << endl; ember.GetPresentVariations(variations); - std::for_each(variations.begin(), variations.end(), [&](Variation* var) { if (var) xformFuncs << var->OpenCLFuncsString(); }); + ForEach(variations, [&](Variation* var) { if (var) xformFuncs << var->OpenCLFuncsString(); }); for (i = 0; i < totalXformCount; i++) { @@ -99,7 +99,7 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin if (needPrecalcAtanYX) xformFuncs << "\treal_t precalcAtanyx;\n"; - xformFuncs << "\treal_t tempColor = outPoint->m_ColorX = xform->m_ColorSpeedCache + (xform->m_OneMinusColorCache * inPoint->m_ColorX);\n"; + xformFuncs << "\treal_t tempColor = outPoint->m_ColorX = xform->m_ColorSpeedCache + (xform->m_OneMinusColorCache * inPoint->m_ColorX);\n\n"; if (xform->PreVariationCount() + xform->VariationCount() == 0) { @@ -145,8 +145,8 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin if (xform->NeedPrecalcAngles()) { - xformFuncs << "\tprecalcSina = transX / precalcSqrtSumSquares;\n"; - xformFuncs << "\tprecalcCosa = transY / precalcSqrtSumSquares;\n"; + xformFuncs << "\tprecalcSina = transX / Zeps(precalcSqrtSumSquares);\n"; + xformFuncs << "\tprecalcCosa = transY / Zeps(precalcSqrtSumSquares);\n"; } if (xform->NeedPrecalcAtanXY()) @@ -268,9 +268,9 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin " __local Point swap[NTHREADS];\n" " __local uint xfsel[NWARPS];\n" "\n" - " unsigned int pointsIndex = INDEX_IN_GRID_2D;\n" - " mwc.x = (pointsIndex + 1 * seed) & 0x7FFFFFFF;\n" - " mwc.y = ((BLOCK_ID_X + 1) + (pointsIndex + 1) * seed) & 0x7FFFFFFF;\n" + " uint pointsIndex = INDEX_IN_GRID_2D;\n" + " mwc.x = (pointsIndex + 1 * seed);\n" + " mwc.y = ((BLOCK_ID_X + 1) * (pointsIndex + 1) * seed);\n" " iPaletteCoord.y = 0;\n" "\n" " if (fuseCount > 0)\n" @@ -308,14 +308,18 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin "\n" " do\n" " {\n"; + + //If xaos is present, the cuburn method is effectively ceased. Every thread will be picking a random xform. if (ember.XaosPresent()) { os << - " secondPoint.m_LastXfUsed = xformDistributions[xfsel[THREAD_ID_Y] + (" << CHOOSE_XFORM_GRAIN << " * (firstPoint.m_LastXfUsed + 1u))];\n\n"; + " secondPoint.m_LastXfUsed = xformDistributions[MwcNext(&mwc) % " << CHOOSE_XFORM_GRAIN << " + (" << CHOOSE_XFORM_GRAIN << " * (firstPoint.m_LastXfUsed + 1u))];\n\n"; + //" secondPoint.m_LastXfUsed = xformDistributions[xfsel[THREAD_ID_Y] + (" << CHOOSE_XFORM_GRAIN << " * (firstPoint.m_LastXfUsed + 1u))];\n\n";//Partial cuburn hybrid. } else { os << + //" secondPoint.m_LastXfUsed = xformDistributions[MwcNext(&mwc) % " << CHOOSE_XFORM_GRAIN << "];\n\n";//For testing, using straight rand flam4/fractron style instead of cuburn. " secondPoint.m_LastXfUsed = xformDistributions[xfsel[THREAD_ID_Y]];\n\n"; } @@ -391,12 +395,15 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin if (ember.UseFinalXform()) { + unsigned int finalIndex = ember.TotalXformCount() - 1; + //CPU takes an extra step here to preserve the opacity of the randomly selected xform, rather than the final xform's opacity. //The same thing takes place here automatically because secondPoint.m_LastXfUsed is used below to retrieve the opacity when accumulating. os << - " if ((ember->m_Xforms[ember->m_FinalXformIndex].m_Opacity == 1) || (MwcNext01(&mwc) < ember->m_Xforms[ember->m_FinalXformIndex].m_Opacity))\n" + " if ((ember->m_Xforms[" << finalIndex << "].m_Opacity == 1) || (MwcNext01(&mwc) < ember->m_Xforms[" << finalIndex << "].m_Opacity))\n" " {\n" - " Xform" << (ember.TotalXformCount() - 1) << "(&(ember->m_Xforms[ember->m_FinalXformIndex]), parVars, &secondPoint, &tempPoint, &mwc);\n" + " tempPoint.m_LastXfUsed = secondPoint.m_LastXfUsed;\n" + " Xform" << finalIndex << "(&(ember->m_Xforms[" << finalIndex << "]), parVars, &secondPoint, &tempPoint, &mwc);\n" " secondPoint = tempPoint;\n" " }\n" "\n"; @@ -511,7 +518,14 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin //At this point, iterating for this round is done, so write the final points back out //to the global points buffer to be used as inputs for the next round. This preserves point trajectory //between kernel calls. +#ifdef TEST_CL_BUFFERS//Use this to populate with test values and read back in EmberTester. + " points[pointsIndex].m_X = MwcNextNeg1Pos1(&mwc);\n" + " points[pointsIndex].m_Y = MwcNextNeg1Pos1(&mwc);\n" + " points[pointsIndex].m_Z = MwcNextNeg1Pos1(&mwc);\n" + " points[pointsIndex].m_ColorX = MwcNextNeg1Pos1(&mwc);\n" +#else " points[pointsIndex] = firstPoint;\n" +#endif " barrier(CLK_GLOBAL_MEM_FENCE);\n" "}\n"; @@ -562,7 +576,6 @@ void IterOpenCLKernelCreator::ParVarIndexDefines(Ember& ember, pair* xform; - ParametricVariation* parVar; ostringstream os; if (doVals) @@ -576,7 +589,7 @@ void IterOpenCLKernelCreator::ParVarIndexDefines(Ember& ember, pair*>(xform->GetVariation(j))) + if (ParametricVariation* parVar = dynamic_cast*>(xform->GetVariation(j))) { for (k = 0; k < parVar->ParamCount(); k++) { @@ -711,7 +724,7 @@ string IterOpenCLKernelCreator::CreateProjectionString(Ember& ember) "\n" " z = ember->m_C02 * secondPoint.m_X + ember->m_C12 * secondPoint.m_Y + ember->m_C22 * z;\n" "\n" - " real_t zr = 1 - ember->m_CamPerspective * z;\n" + " real_t zr = Zeps(1 - ember->m_CamPerspective * z);\n" " real_t dr = MwcNext01(&mwc) * ember->m_BlurCoef * z;\n" "\n" " dsin = sin(t);\n" @@ -731,7 +744,7 @@ string IterOpenCLKernelCreator::CreateProjectionString(Ember& ember) " z = secondPoint.m_Z - ember->m_CamZPos;\n" " y = ember->m_C11 * secondPoint.m_Y + ember->m_C21 * z;\n" " z = ember->m_C12 * secondPoint.m_Y + ember->m_C22 * z;\n" - " zr = 1 - ember->m_CamPerspective * z;\n" + " zr = Zeps(1 - ember->m_CamPerspective * z);\n" "\n" " dsin = sin(t);\n" " dcos = cos(t);\n" @@ -751,7 +764,7 @@ string IterOpenCLKernelCreator::CreateProjectionString(Ember& ember) " real_t z = secondPoint.m_Z - ember->m_CamZPos;\n" " real_t x = ember->m_C00 * secondPoint.m_X + ember->m_C10 * secondPoint.m_Y;\n" " real_t y = ember->m_C01 * secondPoint.m_X + ember->m_C11 * secondPoint.m_Y + ember->m_C21 * z;\n" - " real_t zr = 1 - ember->m_CamPerspective * (ember->m_C02 * secondPoint.m_X + ember->m_C12 * secondPoint.m_Y + ember->m_C22 * z);\n" + " real_t zr = Zeps(1 - ember->m_CamPerspective * (ember->m_C02 * secondPoint.m_X + ember->m_C12 * secondPoint.m_Y + ember->m_C22 * z));\n" "\n" " secondPoint.m_X = x / zr;\n" " secondPoint.m_Y = y / zr;\n" @@ -762,7 +775,7 @@ string IterOpenCLKernelCreator::CreateProjectionString(Ember& ember) os << " real_t z = secondPoint.m_Z - ember->m_CamZPos;\n" " real_t y = ember->m_C11 * secondPoint.m_Y + ember->m_C21 * z;\n" - " real_t zr = 1 - ember->m_CamPerspective * (ember->m_C12 * secondPoint.m_Y + ember->m_C22 * z);\n" + " real_t zr = Zeps(1 - ember->m_CamPerspective * (ember->m_C12 * secondPoint.m_Y + ember->m_C22 * z));\n" "\n" " secondPoint.m_X /= zr;\n" " secondPoint.m_Y = y / zr;\n" @@ -772,7 +785,7 @@ string IterOpenCLKernelCreator::CreateProjectionString(Ember& ember) else { os << - " real_t zr = 1 - ember->m_CamPerspective * (secondPoint.m_Z - ember->m_CamZPos);\n" + " real_t zr = Zeps(1 - ember->m_CamPerspective * (secondPoint.m_Z - ember->m_CamZPos));\n" "\n" " secondPoint.m_X /= zr;\n" " secondPoint.m_Y /= zr;\n" diff --git a/Source/EmberCL/OpenCLWrapper.cpp b/Source/EmberCL/OpenCLWrapper.cpp index ebf28dd..92cbf01 100644 --- a/Source/EmberCL/OpenCLWrapper.cpp +++ b/Source/EmberCL/OpenCLWrapper.cpp @@ -1262,6 +1262,8 @@ bool OpenCLWrapper::CreateSPK(std::string& name, std::string& program, std::stri err = spk.m_Program.build(m_DeviceVec, "-cl-mad-enable");//Tinker with other options later. else err = spk.m_Program.build(m_DeviceVec, "-cl-mad-enable -cl-no-signed-zeros -cl-single-precision-constant"); + //err = spk.m_Program.build(m_DeviceVec, "-cl-single-precision-constant"); + //err = spk.m_Program.build(m_DeviceVec, "-cl-mad-enable -cl-single-precision-constant"); //err = spk.m_Program.build(m_DeviceVec, "-cl-mad-enable -cl-no-signed-zeros -cl-fast-relaxed-math -cl-single-precision-constant");//This can cause some rounding. //err = spk.m_Program.build(m_DeviceVec, "-cl-mad-enable -cl-single-precision-constant"); diff --git a/Source/EmberCL/RendererCL.cpp b/Source/EmberCL/RendererCL.cpp index 339e4ab..4e14109 100644 --- a/Source/EmberCL/RendererCL.cpp +++ b/Source/EmberCL/RendererCL.cpp @@ -40,6 +40,7 @@ RendererCL::RendererCL(unsigned int platform, unsigned int device, bool share //based on the cuburn model of each kernel launch containing //256 threads. 32 wide by 8 high. Everything done in the OpenCL //iteraion kernel depends on these dimensions. + m_IterCountPerKernel = 256; m_IterBlockWidth = 32; m_IterBlockHeight = 8; m_IterBlocksWide = 64; @@ -125,6 +126,7 @@ bool RendererCL::Init(unsigned int platform, unsigned int device, bool shared /// OpenCL property accessors, getters only. /// +template unsigned int RendererCL::IterCountPerKernel() { return m_IterCountPerKernel; } template unsigned int RendererCL::IterBlocksWide() { return m_IterBlocksWide; } template unsigned int RendererCL::IterBlocksHigh() { return m_IterBlocksHigh; } template unsigned int RendererCL::IterBlockWidth() { return m_IterBlockWidth; } @@ -322,7 +324,7 @@ void RendererCL::ClearErrorReport() template unsigned int RendererCL::SubBatchSize() const { - return m_IterBlocksWide * m_IterBlocksHigh * 256 * 256; + return m_IterBlocksWide * m_IterBlocksHigh * SQR(m_IterCountPerKernel); } /// @@ -614,7 +616,7 @@ EmberStats RendererCL::Iterate(unsigned __int64 iterCount, unsigned int pass, if (b) { - if (m_ProcessState == ITER_STARTED) + if (m_Stats.m_Iters == 0)//Only reset the call count on the beginning of a new render. Do not reset on KEEP_ITERATING. m_Calls = 0; b = RunIter(iterCount, pass, temporalSample, stats.m_Iters); @@ -684,9 +686,10 @@ bool RendererCL::RunIter(unsigned __int64 iterCount, unsigned int pass, unsig Timing t;//, t2(4); bool b = false; unsigned int fuse, argIndex; - unsigned int iterCountPerKernel = 256; + unsigned int iterCountPerKernel = m_IterCountPerKernel; unsigned int iterCountPerBlock = iterCountPerKernel * m_IterBlockWidth * m_IterBlockHeight; unsigned int seed; + unsigned int fuseFreq = m_SubBatchSize / m_IterCountPerKernel; unsigned __int64 itersRemaining, localIterCount = 0; int kernelIndex = m_Wrapper.FindKernelIndex(m_IterOpenCLKernelCreator.IterEntryPoint()); double percent, etaMs; @@ -707,7 +710,7 @@ bool RendererCL::RunIter(unsigned __int64 iterCount, unsigned int pass, unsig if (!m_Wrapper.AddAndWriteBuffer(m_DistBufferName, (void*)XformDistributions(), XformDistributionsSize())) { m_ErrorReport.push_back(loc); return false; }//Will be resized for xaos. if (!m_Wrapper.WriteBuffer (m_CarToRasBufferName, (void*)&m_CarToRasCL, sizeof(m_CarToRasCL))) { m_ErrorReport.push_back(loc); return false; } - if (!m_Wrapper.AddAndWriteImage("Palette", CL_MEM_READ_ONLY, m_PaletteFormat, 256, 1, 0, m_Dmap.m_Entries.data())) { m_ErrorReport.push_back(loc); return false; } + if (!m_Wrapper.AddAndWriteImage("Palette", CL_MEM_READ_ONLY, m_PaletteFormat, m_Dmap.m_Entries.size(), 1, 0, m_Dmap.m_Entries.data())) { m_ErrorReport.push_back(loc); return false; } //If animating, treat each temporal sample as a newly started render for fusing purposes. if (temporalSample > 0) @@ -718,11 +721,12 @@ bool RendererCL::RunIter(unsigned __int64 iterCount, unsigned int pass, unsig argIndex = 0; seed = m_Rand[0].Rand(); #ifdef TEST_CL - fuse = false; + fuse = 0; #else - fuse = ((m_Calls % 4) == 0 ? 100 : 0); -#endif //fuse = 100; + fuse = ((m_Calls % fuseFreq) == 0 ? (EarlyClip() ? 100u : 15u) : 0u); + //fuse = ((m_Calls % 4) == 0 ? 100u : 0u); +#endif itersRemaining = iterCount - itersRan; unsigned int gridW = (unsigned int)min(ceil((double)itersRemaining / (double)iterCountPerBlock), (double)IterBlocksWide()); unsigned int gridH = (unsigned int)min(ceil((double)itersRemaining / ((double)gridW * iterCountPerBlock)), (double)IterBlocksHigh()); @@ -736,17 +740,17 @@ bool RendererCL::RunIter(unsigned __int64 iterCount, unsigned int pass, unsig iterCountThisLaunch = iterCountPerKernel * (gridW * gridH * m_IterBlockWidth * m_IterBlockHeight); } - if (!m_Wrapper.SetArg (kernelIndex, argIndex, iterCountPerKernel)) { m_ErrorReport.push_back(loc); return false; } argIndex++;//Number of iters for each thread to run. - if (!m_Wrapper.SetArg (kernelIndex, argIndex, fuse)) { m_ErrorReport.push_back(loc); return false; } argIndex++;//Number of iters to fuse. - if (!m_Wrapper.SetArg (kernelIndex, argIndex, seed)) { m_ErrorReport.push_back(loc); return false; } argIndex++;//Seed. - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex, m_EmberBufferName)) { m_ErrorReport.push_back(loc); return false; } argIndex++;//Flame. - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex, m_ParVarsBufferName)) { m_ErrorReport.push_back(loc); return false; } argIndex++;//Parametric variation parameters. - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex, m_DistBufferName)) { m_ErrorReport.push_back(loc); return false; } argIndex++;//Xform distributions. - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex, m_CarToRasBufferName)) { m_ErrorReport.push_back(loc); return false; } argIndex++;//Coordinate converter. - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex, m_HistBufferName)) { m_ErrorReport.push_back(loc); return false; } argIndex++;//Histogram. - if (!m_Wrapper.SetArg (kernelIndex, argIndex, SuperSize())) { m_ErrorReport.push_back(loc); return false; } argIndex++;//Histogram size. - if (!m_Wrapper.SetImageArg (kernelIndex, argIndex, false, "Palette")) { m_ErrorReport.push_back(loc); return false; } argIndex++;//Palette. - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex, m_PointsBufferName)) { m_ErrorReport.push_back(loc); return false; } argIndex++;//Random start points. + if (!m_Wrapper.SetArg (kernelIndex, argIndex++, iterCountPerKernel)) { m_ErrorReport.push_back(loc); return false; }//Number of iters for each thread to run. + if (!m_Wrapper.SetArg (kernelIndex, argIndex++, fuse)) { m_ErrorReport.push_back(loc); return false; }//Number of iters to fuse. + if (!m_Wrapper.SetArg (kernelIndex, argIndex++, seed)) { m_ErrorReport.push_back(loc); return false; }//Seed. + if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_EmberBufferName)) { m_ErrorReport.push_back(loc); return false; }//Flame. + if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_ParVarsBufferName)) { m_ErrorReport.push_back(loc); return false; }//Parametric variation parameters. + if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_DistBufferName)) { m_ErrorReport.push_back(loc); return false; }//Xform distributions. + if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_CarToRasBufferName)) { m_ErrorReport.push_back(loc); return false; }//Coordinate converter. + if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_HistBufferName)) { m_ErrorReport.push_back(loc); return false; }//Histogram. + if (!m_Wrapper.SetArg (kernelIndex, argIndex++, SuperSize())) { m_ErrorReport.push_back(loc); return false; }//Histogram size. + if (!m_Wrapper.SetImageArg (kernelIndex, argIndex++, false, "Palette")) { m_ErrorReport.push_back(loc); return false; }//Palette. + if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_PointsBufferName)) { m_ErrorReport.push_back(loc); return false; }//Random start points. if (!m_Wrapper.RunKernel(kernelIndex, gridW * IterBlockWidth(),//Total grid dims. @@ -837,9 +841,9 @@ eRenderStatus RendererCL::RunLogScaleFilter() if (!m_Wrapper.AddAndWriteBuffer(m_DEFilterParamsBufferName, (void*)&m_DensityFilterCL, sizeof(m_DensityFilterCL))) { m_ErrorReport.push_back(loc); return RENDER_ERROR; } - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex, m_HistBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; } argIndex++;//Histogram. - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex, m_AccumBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; } argIndex++;//Accumulator. - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex, m_DEFilterParamsBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; } argIndex++;//DensityFilterCL. + if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_HistBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; }//Histogram. + if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_AccumBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; }//Accumulator. + if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_DEFilterParamsBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; }//DensityFilterCL. //t.Tic(); if (!m_Wrapper.RunKernel(kernelIndex, gridW, gridH, 1, blockW, blockH, 1)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; } @@ -981,8 +985,8 @@ eRenderStatus RendererCL::RunFinalAccum() gridH = m_SpatialFilterCL.m_SuperRasH; OpenCLWrapper::MakeEvenGridDims(blockW, blockH, gridW, gridH); - if (!m_Wrapper.SetBufferArg(gammaCorrectKernelIndex, argIndex, m_AccumBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; } argIndex++;//Accumulator. - if (!m_Wrapper.SetBufferArg(gammaCorrectKernelIndex, argIndex, m_SpatialFilterParamsBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; } argIndex++;//SpatialFilterCL. + if (!m_Wrapper.SetBufferArg(gammaCorrectKernelIndex, argIndex++, m_AccumBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; }//Accumulator. + if (!m_Wrapper.SetBufferArg(gammaCorrectKernelIndex, argIndex++, m_SpatialFilterParamsBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; }//SpatialFilterCL. if (!m_Wrapper.RunKernel(gammaCorrectKernelIndex, gridW, gridH, 1, blockW, blockH, 1)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; } } @@ -1000,12 +1004,12 @@ eRenderStatus RendererCL::RunFinalAccum() gridH = m_SpatialFilterCL.m_FinalRasH; OpenCLWrapper::MakeEvenGridDims(blockW, blockH, gridW, gridH); - if (!m_Wrapper.SetBufferArg(accumKernelIndex, argIndex, m_AccumBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; } argIndex++;//Accumulator. - if (!m_Wrapper.SetImageArg(accumKernelIndex, argIndex, m_Wrapper.Shared(), m_FinalImageName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; } argIndex++;//Final image. - if (!m_Wrapper.SetBufferArg(accumKernelIndex, argIndex, m_SpatialFilterParamsBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; } argIndex++;//SpatialFilterCL. - if (!m_Wrapper.SetBufferArg(accumKernelIndex, argIndex, m_SpatialFilterCoefsBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; } argIndex++;//Filter coefs. - if (!m_Wrapper.SetArg(accumKernelIndex, argIndex, alphaBase)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; } argIndex++;//Alpha base. - if (!m_Wrapper.SetArg(accumKernelIndex, argIndex, alphaScale)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; } argIndex++;//Alpha scale. + if (!m_Wrapper.SetBufferArg(accumKernelIndex, argIndex++, m_AccumBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; }//Accumulator. + if (!m_Wrapper.SetImageArg(accumKernelIndex, argIndex++, m_Wrapper.Shared(), m_FinalImageName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; }//Final image. + if (!m_Wrapper.SetBufferArg(accumKernelIndex, argIndex++, m_SpatialFilterParamsBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; }//SpatialFilterCL. + if (!m_Wrapper.SetBufferArg(accumKernelIndex, argIndex++, m_SpatialFilterCoefsBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; }//Filter coefs. + if (!m_Wrapper.SetArg (accumKernelIndex, argIndex++, alphaBase)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; }//Alpha base. + if (!m_Wrapper.SetArg (accumKernelIndex, argIndex++, alphaScale)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; }//Alpha scale. if (m_Wrapper.Shared()) if (!m_Wrapper.EnqueueAcquireGLObjects(m_FinalImageName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; } @@ -1050,9 +1054,9 @@ bool RendererCL::ClearBuffer(string bufferName, unsigned int width, unsigned OpenCLWrapper::MakeEvenGridDims(blockW, blockH, gridW, gridH); - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex, bufferName)) { m_ErrorReport.push_back(loc); return false; } argIndex++;//Buffer of unsigned char. - if (!m_Wrapper.SetArg (kernelIndex, argIndex, width * elementSize)) { m_ErrorReport.push_back(loc); return false; } argIndex++;//Width. - if (!m_Wrapper.SetArg (kernelIndex, argIndex, height)) { m_ErrorReport.push_back(loc); return false; } argIndex++;//Height. + if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex++, bufferName)) { m_ErrorReport.push_back(loc); return false; }//Buffer of unsigned char. + if (!m_Wrapper.SetArg (kernelIndex, argIndex++, width * elementSize)) { m_ErrorReport.push_back(loc); return false; }//Width. + if (!m_Wrapper.SetArg (kernelIndex, argIndex++, height)) { m_ErrorReport.push_back(loc); return false; }//Height. if (!m_Wrapper.RunKernel(kernelIndex, gridW, gridH, 1, blockW, blockH, 1)) { m_ErrorReport.push_back(loc); return false; } return true; @@ -1281,7 +1285,6 @@ EmberCL RendererCL::ConvertEmber(Ember& ember) emberCL.m_CamPitch = ember.m_CamPitch; emberCL.m_CamDepthBlur = ember.m_CamDepthBlur; emberCL.m_BlurCoef = ember.BlurCoef(); - emberCL.m_FinalXformIndex = ember.UseFinalXform() ? ember.TotalXformCount() - 1 : -1; for (unsigned int i = 0; i < ember.TotalXformCount() && i < MAX_CL_XFORM; i++)//Copy the relevant values for each xform, capped at the max. { diff --git a/Source/EmberCL/RendererCL.h b/Source/EmberCL/RendererCL.h index 241695d..06d96b3 100644 --- a/Source/EmberCL/RendererCL.h +++ b/Source/EmberCL/RendererCL.h @@ -38,6 +38,7 @@ public: //Ordinary member functions for OpenCL specific tasks. bool Init(unsigned int platform, unsigned int device, bool shared, GLuint outputTexID); + inline unsigned int IterCountPerKernel(); inline unsigned int IterBlocksWide(); inline unsigned int IterBlocksHigh(); inline unsigned int IterBlockWidth(); @@ -106,6 +107,7 @@ private: bool m_Init; bool m_NVidia; bool m_DoublePrecision; + unsigned int m_IterCountPerKernel; unsigned int m_IterBlocksWide, m_IterBlockWidth; unsigned int m_IterBlocksHigh, m_IterBlockHeight; unsigned int m_MaxDEBlockSizeW; diff --git a/Source/EmberCommon/EmberCommon.h b/Source/EmberCommon/EmberCommon.h index e2e9cce..c214764 100644 --- a/Source/EmberCommon/EmberCommon.h +++ b/Source/EmberCommon/EmberCommon.h @@ -41,7 +41,7 @@ public: if (m_LastStage != stage) cout << endl; - cout << "\r" << string(m_S.length(), ' ');//Clear what was previously here. + cout << "\r" << string(m_S.length() * 2, ' ');//Clear what was previously here, * 2 just to be safe because the end parts of previous strings might be longer. m_SS.str("");//Begin new output. m_SS << "\rStage = " << (stage ? "filtering" : "chaos"); m_SS << ", progress = " << int(fraction) << "%"; diff --git a/Source/EmberCommon/EmberOptions.h b/Source/EmberCommon/EmberOptions.h index fc06f78..a41e633 100644 --- a/Source/EmberCommon/EmberOptions.h +++ b/Source/EmberCommon/EmberOptions.h @@ -302,7 +302,7 @@ public: INITUINTOPTION(ThreadCount, Eou(OPT_USE_ALL, OPT_NTHREADS, _T("--nthreads"), 0, SO_REQ_SEP, "\t--nthreads= The number of threads to use [default: use all available cores].\n")); INITUINTOPTION(Strips, Eou(OPT_USE_RENDER, OPT_STRIPS, _T("--nstrips"), 1, SO_REQ_SEP, "\t--nstrips= The number of fractions to split a single render frame into. Useful for print size renders or low memory systems [default: 1].\n")); INITUINTOPTION(BitsPerChannel, Eou(OPT_RENDER_ANIM, OPT_BPC, _T("--bpc"), 8, SO_REQ_SEP, "\t--bpc= Bits per channel. 8 or 16 for PNG, 8 for all others [default: 8].\n")); - INITUINTOPTION(SubBatchSize, Eou(OPT_USE_ALL, OPT_SBS, _T("--sub_batch_size"), 10000, SO_REQ_SEP, "\t--sub_batch_size= The chunk size that iterating will be broken into [default: 10000].\n")); + INITUINTOPTION(SubBatchSize, Eou(OPT_USE_ALL, OPT_SBS, _T("--sub_batch_size"), 10240, SO_REQ_SEP, "\t--sub_batch_size= The chunk size that iterating will be broken into [default: 10k].\n")); INITUINTOPTION(Bits, Eou(OPT_USE_ALL, OPT_BITS, _T("--bits"), 33, SO_REQ_SEP, "\t--bits= Determines the types used for the histogram and accumulator [default: 33].\n" "\t\t\t\t\t32: Histogram: float, Accumulator: float.\n" "\t\t\t\t\t33: Histogram: float, Accumulator: float.\n"//This differs from the original which used an int hist for bits 33. @@ -510,11 +510,11 @@ public: CSimpleOpt::SOption endOption = SO_END_OF_OPTIONS; entries.reserve(75); - std::for_each(m_BoolArgs.begin(), m_BoolArgs.end(), [&](Eob* entry) { if (entry->m_OptionUse & optUsage) entries.push_back(entry->m_Option); }); - std::for_each(m_IntArgs.begin(), m_IntArgs.end(), [&](Eoi* entry) { if (entry->m_OptionUse & optUsage) entries.push_back(entry->m_Option); }); - std::for_each(m_UintArgs.begin(), m_UintArgs.end(), [&](Eou* entry) { if (entry->m_OptionUse & optUsage) entries.push_back(entry->m_Option); }); - std::for_each(m_DoubleArgs.begin(), m_DoubleArgs.end(), [&](Eod* entry) { if (entry->m_OptionUse & optUsage) entries.push_back(entry->m_Option); }); - std::for_each(m_StringArgs.begin(), m_StringArgs.end(), [&](Eos* entry) { if (entry->m_OptionUse & optUsage) entries.push_back(entry->m_Option); }); + ForEach(m_BoolArgs, [&](Eob* entry) { if (entry->m_OptionUse & optUsage) entries.push_back(entry->m_Option); }); + ForEach(m_IntArgs, [&](Eoi* entry) { if (entry->m_OptionUse & optUsage) entries.push_back(entry->m_Option); }); + ForEach(m_UintArgs, [&](Eou* entry) { if (entry->m_OptionUse & optUsage) entries.push_back(entry->m_Option); }); + ForEach(m_DoubleArgs, [&](Eod* entry) { if (entry->m_OptionUse & optUsage) entries.push_back(entry->m_Option); }); + ForEach(m_StringArgs, [&](Eos* entry) { if (entry->m_OptionUse & optUsage) entries.push_back(entry->m_Option); }); entries.push_back(endOption); return entries; @@ -529,11 +529,11 @@ public: { ostringstream os; - std::for_each(m_BoolArgs.begin(), m_BoolArgs.end(), [&](Eob* entry) { if (entry->m_OptionUse & optUsage) os << entry->m_DocString << endl; }); - std::for_each(m_IntArgs.begin(), m_IntArgs.end(), [&](Eoi* entry) { if (entry->m_OptionUse & optUsage) os << entry->m_DocString << endl; }); - std::for_each(m_UintArgs.begin(), m_UintArgs.end(), [&](Eou* entry) { if (entry->m_OptionUse & optUsage) os << entry->m_DocString << endl; }); - std::for_each(m_DoubleArgs.begin(), m_DoubleArgs.end(), [&](Eod* entry) { if (entry->m_OptionUse & optUsage) os << entry->m_DocString << endl; }); - std::for_each(m_StringArgs.begin(), m_StringArgs.end(), [&](Eos* entry) { if (entry->m_OptionUse & optUsage) os << entry->m_DocString << endl; }); + ForEach(m_BoolArgs, [&](Eob* entry) { if (entry->m_OptionUse & optUsage) os << entry->m_DocString << endl; }); + ForEach(m_IntArgs, [&](Eoi* entry) { if (entry->m_OptionUse & optUsage) os << entry->m_DocString << endl; }); + ForEach(m_UintArgs, [&](Eou* entry) { if (entry->m_OptionUse & optUsage) os << entry->m_DocString << endl; }); + ForEach(m_DoubleArgs, [&](Eod* entry) { if (entry->m_OptionUse & optUsage) os << entry->m_DocString << endl; }); + ForEach(m_StringArgs, [&](Eos* entry) { if (entry->m_OptionUse & optUsage) os << entry->m_DocString << endl; }); return os.str(); } @@ -548,11 +548,11 @@ public: ostringstream os; os << std::boolalpha; - std::for_each(m_BoolArgs.begin(), m_BoolArgs.end(), [&](Eob* entry) { if (entry->m_OptionUse & optUsage) os << entry->m_NameWithoutDashes << ": " << (*entry)() << endl; }); - std::for_each(m_IntArgs.begin(), m_IntArgs.end(), [&](Eoi* entry) { if (entry->m_OptionUse & optUsage) os << entry->m_NameWithoutDashes << ": " << (*entry)() << endl; }); - std::for_each(m_UintArgs.begin(), m_UintArgs.end(), [&](Eou* entry) { if (entry->m_OptionUse & optUsage) os << entry->m_NameWithoutDashes << ": " << (*entry)() << endl; }); - std::for_each(m_DoubleArgs.begin(), m_DoubleArgs.end(), [&](Eod* entry) { if (entry->m_OptionUse & optUsage) os << entry->m_NameWithoutDashes << ": " << (*entry)() << endl; }); - std::for_each(m_StringArgs.begin(), m_StringArgs.end(), [&](Eos* entry) { if (entry->m_OptionUse & optUsage) os << entry->m_NameWithoutDashes << ": " << (*entry)() << endl; }); + ForEach(m_BoolArgs, [&](Eob* entry) { if (entry->m_OptionUse & optUsage) os << entry->m_NameWithoutDashes << ": " << (*entry)() << endl; }); + ForEach(m_IntArgs, [&](Eoi* entry) { if (entry->m_OptionUse & optUsage) os << entry->m_NameWithoutDashes << ": " << (*entry)() << endl; }); + ForEach(m_UintArgs, [&](Eou* entry) { if (entry->m_OptionUse & optUsage) os << entry->m_NameWithoutDashes << ": " << (*entry)() << endl; }); + ForEach(m_DoubleArgs, [&](Eod* entry) { if (entry->m_OptionUse & optUsage) os << entry->m_NameWithoutDashes << ": " << (*entry)() << endl; }); + ForEach(m_StringArgs, [&](Eos* entry) { if (entry->m_OptionUse & optUsage) os << entry->m_NameWithoutDashes << ": " << (*entry)() << endl; }); return os.str(); } diff --git a/Source/EmberGenome/EmberGenome.rc b/Source/EmberGenome/EmberGenome.rc index 39db17d..cb57c64 100644 --- a/Source/EmberGenome/EmberGenome.rc +++ b/Source/EmberGenome/EmberGenome.rc @@ -49,8 +49,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,4,0,4 - PRODUCTVERSION 0,4,0,4 + FILEVERSION 0,4,0,5 + PRODUCTVERSION 0,4,0,5 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -67,12 +67,12 @@ BEGIN BEGIN VALUE "CompanyName", "Open Source" VALUE "FileDescription", "Manipulates fractal flames parameter files" - VALUE "FileVersion", "0.4.0.4" + VALUE "FileVersion", "0.4.0.5" VALUE "InternalName", "EmberGenome.rc" VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2013, GPL v3" VALUE "OriginalFilename", "EmberGenome.rc" VALUE "ProductName", "Ember Genome" - VALUE "ProductVersion", "0.4.0.4" + VALUE "ProductVersion", "0.4.0.5" END END BLOCK "VarFileInfo" diff --git a/Source/EmberRender/EmberRender.cpp b/Source/EmberRender/EmberRender.cpp index 84040b5..146ca40 100644 --- a/Source/EmberRender/EmberRender.cpp +++ b/Source/EmberRender/EmberRender.cpp @@ -157,7 +157,7 @@ bool EmberRender(EmberOptions& opt) if (opt.Verbose() && embers.size() > 1) cout << "\nFlame = " << i + 1 << "/" << embers.size() << endl; else - cout << endl; + VerbosePrint(endl); embers[i].m_TemporalSamples = 1;//Force temporal samples to 1 for render. embers[i].m_Quality *= T(opt.QualityScale()); diff --git a/Source/EmberRender/EmberRender.rc b/Source/EmberRender/EmberRender.rc index 6682b73..36fc954 100644 --- a/Source/EmberRender/EmberRender.rc +++ b/Source/EmberRender/EmberRender.rc @@ -49,8 +49,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,4,0,4 - PRODUCTVERSION 0,4,0,4 + FILEVERSION 0,4,0,5 + PRODUCTVERSION 0,4,0,5 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -67,12 +67,12 @@ BEGIN BEGIN VALUE "CompanyName", "Open Source" VALUE "FileDescription", "Renders fractal flames as single images" - VALUE "FileVersion", "0.4.0.4" + VALUE "FileVersion", "0.4.0.5" VALUE "InternalName", "EmberRender.rc" VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2013, GPL v3" VALUE "OriginalFilename", "EmberRender.rc" VALUE "ProductName", "Ember Render" - VALUE "ProductVersion", "0.4.0.4" + VALUE "ProductVersion", "0.4.0.5" END END BLOCK "VarFileInfo" diff --git a/Source/EmberTester/EmberTester.cpp b/Source/EmberTester/EmberTester.cpp index 9097533..f454006 100644 --- a/Source/EmberTester/EmberTester.cpp +++ b/Source/EmberTester/EmberTester.cpp @@ -1028,7 +1028,7 @@ bool TestVarAssignVals() { bool success = true; VariationList vlf; - vector xout, yout; + vector xout, yout, zout; xout.push_back("vOut.x ="); xout.push_back("vOut.x +="); @@ -1041,6 +1041,12 @@ bool TestVarAssignVals() yout.push_back("vOut.y -="); yout.push_back("vOut.y *="); yout.push_back("vOut.y /="); + + zout.push_back("vOut.z ="); + zout.push_back("vOut.z +="); + zout.push_back("vOut.z -="); + zout.push_back("vOut.z *="); + zout.push_back("vOut.z /="); for (size_t i = 0; i < vlf.Size(); i++) { @@ -1057,6 +1063,12 @@ bool TestVarAssignVals() cout << "Variation " << var->Name() << " did not set its y output point. If unused, at least pass through or set to 0." << endl; success = false; } + + if (!SearchVar(var, zout, false)) + { + cout << "Variation " << var->Name() << " did not set its z output point. If unused, at least pass through or set to 0." << endl; + success = false; + } } return success; @@ -1278,7 +1290,7 @@ void TestVarTime() } std::sort(times.begin(), times.end(), &SortPairByTime); - //std::for_each(times.begin(), times.end(), [&](pair& p) { cout << p.first << "\t" << p.second << "" << endl; }); + //ForEach(times, [&](pair& p) { cout << p.first << "\t" << p.second << "" << endl; }); } template @@ -1384,13 +1396,13 @@ void TestVarsSimilar() if (parVar) { for (unsigned int v = 0; v < parVar->ParamCount(); v++) - parVar->SetParamVal(v, iter); + parVar->SetParamVal(v, (T)iter); } if (parVarComp) { for (unsigned int v = 0; v < parVarComp->ParamCount(); v++) - parVarComp->SetParamVal(v, iter); + parVarComp->SetParamVal(v, (T)iter); } //For debugging. @@ -1400,13 +1412,13 @@ void TestVarsSimilar() } helper.Out = v4T(0); - var->m_Weight = iter + 1; + var->m_Weight = T(iter + 1); var->Precalc(); var->Func(helper, p, rand); v4T varOut = helper.Out; helper.Out = v4T(0); - varComp->m_Weight = iter + 1; + varComp->m_Weight = T(iter + 1); varComp->Precalc(); varComp->Func(helper, pComp, rand); v4T varCompOut = helper.Out; @@ -1437,6 +1449,7 @@ void TestVarsSimilar() //std::sort(times.begin(), times.end(), &SortPairByTime); } +#ifdef TEST_CL template void TestCpuGpuResults() { @@ -1537,9 +1550,179 @@ void TestCpuGpuResults() cout << "Skipped " << skipped << endl; } +template +void TestGpuVectorRead() +{ + T minx = TMAX, miny = TMAX, minz = TMAX, mincolorx = TMAX; + T maxx = TLOW, maxy = TLOW, maxz = TLOW, maxcolorx = TLOW; + double sumx = 0, avgx = 0; + double sumy = 0, avgy = 0; + double sumz = 0, avgz = 0; + double sumcolorx = 0, avgcolorx = 0; + Timing t; + VariationList vlf; + QTIsaac rand; + vector> points; + RendererCL renderer; + + if (!renderer.Init(1, 0, false, 0)) + return; + + points.resize(renderer.TotalIterKernelCount()); + + Variation* var = vlf.GetVariation(VAR_LINEAR); + + bool newAlloc = false; + Point p, p2; + Ember ember; + Xform xform; + Variation* varCopy = var->Copy(); + + p.m_X = rand.Frand(-5, 5); + p.m_Y = rand.Frand(-5, 5); + p.m_Z = rand.Frand(-5, 5); + p.m_ColorX = rand.Frand01(); + p.m_VizAdjusted = rand.Frand01(); + + varCopy->Random(rand); + xform.AddVariation(varCopy); + ember.AddXform(xform); + ember.CacheXforms(); + renderer.SetEmber(ember); + renderer.CreateSpatialFilter(newAlloc); + renderer.CreateDEFilter(newAlloc); + renderer.ComputeBounds(); + renderer.ComputeCamera(); + renderer.AssignIterator(); + + if (!renderer.Alloc()) + return; + + unsigned int i, iters = renderer.IterCountPerKernel() * renderer.TotalIterKernelCount();//Make each thread in each block run at least once. + renderer.Iterate(iters, 0, 1); + renderer.ReadPoints(points); + + cout << __FUNCTION__ << ": GPU point test value results:" << endl; + + for (i = 0; i < points.size(); i++) + { + cout << "point[" << i << "].m_X = " << points[i].m_X << endl; + cout << "point[" << i << "].m_Y = " << points[i].m_Y << endl; + cout << "point[" << i << "].m_Z = " << points[i].m_Z << endl; + cout << "point[" << i << "].m_ColorX = " << points[i].m_ColorX << endl << endl; + + minx = min(points[i].m_X, minx); + miny = min(points[i].m_Y, miny); + minz = min(points[i].m_Z, minz); + mincolorx = min(points[i].m_ColorX, mincolorx); + + maxx = max(points[i].m_X, maxx); + maxy = max(points[i].m_Y, maxy); + maxz = max(points[i].m_Z, maxz); + maxcolorx = max(points[i].m_ColorX, maxcolorx); + + sumx += points[i].m_X; + sumy += points[i].m_Y; + sumz += points[i].m_Z; + sumcolorx += points[i].m_ColorX; + } + + avgx = sumx / i; + avgy = sumy / i; + avgz = sumz / i; + avgcolorx = sumcolorx / i; + + cout << "avgx = " << avgx << endl; + cout << "avgy = " << avgy << endl; + cout << "avgz = " << avgz << endl; + cout << "avgcolorx = " << avgcolorx << endl; + + cout << "minx = " << minx << endl; + cout << "miny = " << miny << endl; + cout << "minz = " << minz << endl; + cout << "mincolorx = " << mincolorx << endl << endl; + + cout << "maxx = " << maxx << endl; + cout << "maxy = " << maxy << endl; + cout << "maxz = " << maxz << endl; + cout << "maxcolorx = " << maxcolorx << endl << endl << endl; +} +#endif + +template +void TestRandomAccess(size_t vsize, size_t ipp, bool cache) +{ + size_t iters = vsize * ipp; + vector vec; + QTIsaac rand; + + vec.resize(vsize); + v4T* vdata = vec.data(); + + if (cache) + { + for (size_t i = 0; i < iters; i++) + { + v4T v4(rand.Frand11(), rand.Frand11(), rand.Frand11(), rand.Frand11()); + int index = rand.Rand((ISAAC_INT)vsize); + v4T v42 = vdata[index]; + + v4.x = log(v4.x); + v4.y = sqrt(v4.y); + v4.z = sin(v4.z); + v4.w = cos(v4.w); + v4 += T(1.234); + v4 *= T(55.55); + v4 /= T(0.0045); + + vdata[index] = v4 + v42; + } + } + else + { + for (size_t i = 0; i < iters; i++) + { + v4T v4(rand.Frand11(), rand.Frand11(), rand.Frand11(), rand.Frand11()); + int index = rand.Rand((ISAAC_INT)vsize); + + v4.x = log(v4.x); + v4.y = sqrt(v4.y); + v4.z = sin(v4.z); + v4.w = cos(v4.w); + v4 += T(1.234); + v4 *= T(55.55); + v4 /= T(0.0045); + + vdata[index] += v4; + } + } +} + +template +void TestCross(T x, T y, T weight) +{ + T s = x * x - y * y; + T r = weight * sqrt(1 / (s * s + EPS)); + T outX = x * r; + T outY = y * r; + + cout << "First way, outX, outY == " << outX << ", " << outY << endl; + + r = fabs((x - y) * (x + y) + EPS); + + if (r < 0) + r = -r; + + r = weight / r; + outX = x * r; + outY = y * r; + cout << "Second way, outX, outY == " << outX << ", " << outY << endl; +} + int _tmain(int argc, _TCHAR* argv[]) { Timing t(4); + QTIsaac rand; //cout << pow(-1, 5.1) << endl; @@ -1560,9 +1743,40 @@ int _tmain(int argc, _TCHAR* argv[]) cout << preLinV->BaseName() << endl; cout << postLinV->BaseName() << endl;*/ - //auto_ptr> preFarblurV(new PreFarblurVariation()); + //float num = 1; + //float denom = 4294967296.0f; + //float frac = num / denom; + // + //cout << "num, denom, frac = " << num << ", " << denom << ", " << frac << endl; + //TestGpuVectorRead(); + //TestGpuVectorRead(); + //return 0; + //auto_ptr> preFarblurV(new PreFarblurVariation()); + //size_t vsize = 1024 * 1024; + // + //t.Tic(); + //TestRandomAccess(vsize, 10, true); + //t.Toc("TestRandomAccess(true)"); + // + //t.Tic(); + //TestRandomAccess(vsize, 10, false); + //t.Toc("TestRandomAccess(false)"); + // + //t.Tic(); + //TestRandomAccess(vsize, 10, true); + //t.Toc("TestRandomAccess(true)"); + // + //t.Tic(); + //TestRandomAccess(vsize, 10, false); + //t.Toc("TestRandomAccess(false)"); + //TestCross(rand.Frand(-5, 5), rand.Frand(-5, 5), rand.Frand(-5, 5)); + //TestCross(rand.Frand(-5, 5), rand.Frand(-5, 5), rand.Frand(-5, 5)); + //TestCross(rand.Frand(-5, 5), rand.Frand(-5, 5), rand.Frand(-5, 5)); + //TestCross(rand.Frand(-5, 5), rand.Frand(-5, 5), rand.Frand(-5, 5)); + //TestCross(rand.Frand(-5, 5), rand.Frand(-5, 5), rand.Frand(-5, 5)); //MakeTestAllVarsRegPrePostComboFile("testallvarsout.flame"); + //return 0; //std::complex cd, cd2; @@ -1611,58 +1825,60 @@ int _tmain(int argc, _TCHAR* argv[]) TestVarCopy(); t.Toc("TestVarCopy()"); #endif - //t.Tic(); - //TestVarRegPrePost(); - //t.Toc("TestVarRegPrePost()"); - // - //t.Tic(); - //TestParVars(); - //t.Toc("TestParVars()"); - // - //t.Tic(); - //TestVarPrePostNames(); - //t.Toc("TestVarPrePostNames()"); - // - //t.Tic(); - //TestVarPrecalcUsedCL(); - //t.Toc("TestVarPrecalcUsedCL()"); - // - //t.Tic(); - //TestVarAssignTypes(); - //t.Toc("TestVarAssignTypes()"); - // - //t.Tic(); - //TestVarAssignVals(); - //t.Toc("TestVarAssignVals()"); - // - //t.Tic(); - //TestConstants(); - //t.Toc("TestConstants()"); - // - //t.Tic(); - //TestXformsInOutPoints(); - //t.Toc("TestXformsInOutPoints()"); - // - //t.Tic(); - //TestVarTime(); - //t.Toc("TestVarTime()"); - // - //t.Tic(); - //TestOperations(); - //t.Toc("TestMod()"); + t.Tic(); + TestVarRegPrePost(); + t.Toc("TestVarRegPrePost()"); + + t.Tic(); + TestParVars(); + t.Toc("TestParVars()"); + + t.Tic(); + TestVarPrePostNames(); + t.Toc("TestVarPrePostNames()"); + + t.Tic(); + TestVarPrecalcUsedCL(); + t.Toc("TestVarPrecalcUsedCL()"); + + t.Tic(); + TestVarAssignTypes(); + t.Toc("TestVarAssignTypes()"); + + t.Tic(); + TestVarAssignVals(); + t.Toc("TestVarAssignVals()"); + + t.Tic(); + TestConstants(); + t.Toc("TestConstants()"); + + t.Tic(); + TestXformsInOutPoints(); + t.Toc("TestXformsInOutPoints()"); + + t.Tic(); + TestVarTime(); + t.Toc("TestVarTime()"); + + t.Tic(); + TestOperations(); + t.Toc("TestOperations()"); //t.Tic(); //TestVarsSimilar(); //t.Toc("TestVarsSimilar()"); - /**/t.Tic(); - TestCpuGpuResults(); - t.Toc("TestCpuGpuResults()"); +#ifdef TEST_CL + //t.Tic(); + //TestCpuGpuResults(); + //t.Toc("TestCpuGpuResults()"); #ifdef DO_DOUBLE - t.Tic(); - TestCpuGpuResults(); - t.Toc("TestCpuGpuResults()"); + //t.Tic(); + //TestCpuGpuResults(); + //t.Toc("TestCpuGpuResults()"); +#endif #endif //PrintAllVars(); diff --git a/Source/Fractorium/AboutDialog.ui b/Source/Fractorium/AboutDialog.ui index dcdeb49..ecee0f4 100644 --- a/Source/Fractorium/AboutDialog.ui +++ b/Source/Fractorium/AboutDialog.ui @@ -52,7 +52,7 @@ - <html><head/><body><p align="center"><br/><span style=" font-size:12pt;">Fractorium 0.4.0.4 Beta</span></p><p align="center"><span style=" font-size:10pt;"><br/>A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.</span></p><p align="center"><span style=" font-size:10pt;">Matt Feemster</span></p></body></html> + <html><head/><body><p align="center"><br/><span style=" font-size:12pt;">Fractorium 0.4.0.5 Beta</span></p><p align="center"><span style=" font-size:10pt;"><br/>A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.</span></p><p align="center"><span style=" font-size:10pt;">Matt Feemster</span></p></body></html> Qt::RichText diff --git a/Source/Fractorium/EmberFile.h b/Source/Fractorium/EmberFile.h index 1486582..4bd6e02 100644 --- a/Source/Fractorium/EmberFile.h +++ b/Source/Fractorium/EmberFile.h @@ -117,12 +117,13 @@ public: int counter = 2; QString newPath; QFileInfo original(filename); + QString path = original.absolutePath() + QDir::separator(); QString base = original.completeBaseName(); QString extension = original.suffix(); do { - newPath = base + "_" + QString::number(counter++) + "." + extension; + newPath = path + base + "_" + QString::number(counter++) + "." + extension; } while (QFile::exists(newPath)); diff --git a/Source/Fractorium/FinalRenderEmberController.cpp b/Source/Fractorium/FinalRenderEmberController.cpp index e5bf103..55fb19b 100644 --- a/Source/Fractorium/FinalRenderEmberController.cpp +++ b/Source/Fractorium/FinalRenderEmberController.cpp @@ -345,6 +345,9 @@ int FinalRenderEmberController::ProgressFunc(Ember& ember, void* foo, doub } m_FinishedImageCount++; + QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderIterationProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, int(100)));//Just to be safe. + QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderFilteringProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, int(100))); + QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderAccumProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, int(100))); QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderTotalProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, int(((float)m_FinishedImageCount / (float)m_ImageCount) * 100))); QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderImageCountLabel, "setText", Qt::QueuedConnection, Q_ARG(QString, QString::number(m_FinishedImageCount) + " / " + QString::number(m_ImageCount))); diff --git a/Source/Fractorium/Fractorium.cpp b/Source/Fractorium/Fractorium.cpp index dd1329b..3429e53 100644 --- a/Source/Fractorium/Fractorium.cpp +++ b/Source/Fractorium/Fractorium.cpp @@ -325,7 +325,7 @@ void Fractorium::dropEvent(QDropEvent* e) void Fractorium::SetupCombo(QTableWidget* table, const QObject* receiver, int& row, int col, StealthComboBox*& comboBox, vector& vals, const char* signal, const char* slot, Qt::ConnectionType connectionType) { comboBox = new StealthComboBox(table); - std::for_each(vals.begin(), vals.end(), [&](string s) { comboBox->addItem(s.c_str()); }); + ForEach(vals, [&](string s) { comboBox->addItem(s.c_str()); }); table->setCellWidget(row, col, comboBox); connect(comboBox, signal, receiver, slot, connectionType); row++; diff --git a/Source/Fractorium/Fractorium.h b/Source/Fractorium/Fractorium.h index 0f5c8a9..982ebd9 100644 --- a/Source/Fractorium/Fractorium.h +++ b/Source/Fractorium/Fractorium.h @@ -109,6 +109,8 @@ public slots: void OnActionAddReflectiveSymmetry(bool checked);//Tools. void OnActionAddRotationalSymmetry(bool checked); void OnActionAddBothSymmetry(bool checked); + void OnActionFlatten(bool checked); + void OnActionUnflatten(bool checked); void OnActionClearFlame(bool checked); void OnActionRenderPreviews(bool checked); void OnActionStopRenderingPreviews(bool checked); diff --git a/Source/Fractorium/Fractorium.qrc b/Source/Fractorium/Fractorium.qrc index 173695c..4526a6f 100644 --- a/Source/Fractorium/Fractorium.qrc +++ b/Source/Fractorium/Fractorium.qrc @@ -1,44 +1,46 @@ - - Icons/arrow-undo.png - Icons/arrow-redo.png - Icons/stop.png - Icons/application_side_boxes.png - Icons/page_copy.png - Icons/page_paste.png - Icons/window-close.png - Icons/068123-3d-transparent-glass-icon-alphanumeric-question-mark3.png - Icons/layer--plus.png - Icons/layers.png - Icons/layers-stack.png - Icons/monitor.png - Icons/016938-3d-transparent-glass-icon-symbols-shapes-shape-square-clear-16.png - Icons/document-hf-insert.png - Icons/010425-3d-transparent-glass-icon-animals-spiderweb2.png - Icons/database-medium.png - Icons/databases.png - Icons/drive-harddisk-5.png - Icons/folder-visiting-4.png - Icons/display-brightness-off.png - Icons/cog.png - Icons/proxy.png - Icons/shape_flip_horizontal.png - Icons/shape_flip_vertical.png - Icons/arrow_down.png - Icons/arrow_in.png - Icons/arrow_left.png - Icons/arrow_out.png - Icons/arrow_right.png - Icons/arrow_rotate_anticlockwise.png - Icons/arrow_rotate_clockwise.png - Icons/arrow_turn_left.png - Icons/arrow_turn_right.png - Icons/arrow_up.png - Icons/configure.png - Icons/infomation.png - Icons/del.png - Icons/add.png - Icons/eraser.png - Icons/editraise.png - + + Icons/arrow-undo.png + Icons/arrow-redo.png + Icons/stop.png + Icons/application_side_boxes.png + Icons/page_copy.png + Icons/page_paste.png + Icons/window-close.png + Icons/068123-3d-transparent-glass-icon-alphanumeric-question-mark3.png + Icons/layer--plus.png + Icons/layers.png + Icons/layers-stack.png + Icons/monitor.png + Icons/016938-3d-transparent-glass-icon-symbols-shapes-shape-square-clear-16.png + Icons/document-hf-insert.png + Icons/010425-3d-transparent-glass-icon-animals-spiderweb2.png + Icons/database-medium.png + Icons/databases.png + Icons/drive-harddisk-5.png + Icons/folder-visiting-4.png + Icons/display-brightness-off.png + Icons/cog.png + Icons/proxy.png + Icons/shape_flip_horizontal.png + Icons/shape_flip_vertical.png + Icons/arrow_down.png + Icons/arrow_in.png + Icons/arrow_left.png + Icons/arrow_out.png + Icons/arrow_right.png + Icons/arrow_rotate_anticlockwise.png + Icons/arrow_rotate_clockwise.png + Icons/arrow_turn_left.png + Icons/arrow_turn_right.png + Icons/arrow_up.png + Icons/configure.png + Icons/infomation.png + Icons/del.png + Icons/add.png + Icons/eraser.png + Icons/editraise.png + Icons/square.png + Icons/cube.png + diff --git a/Source/Fractorium/Fractorium.rc b/Source/Fractorium/Fractorium.rc index 370d111..134c3bb 100644 Binary files a/Source/Fractorium/Fractorium.rc and b/Source/Fractorium/Fractorium.rc differ diff --git a/Source/Fractorium/Fractorium.ui b/Source/Fractorium/Fractorium.ui index 81e19ae..a7406b8 100644 --- a/Source/Fractorium/Fractorium.ui +++ b/Source/Fractorium/Fractorium.ui @@ -174,6 +174,9 @@ + + + @@ -5282,6 +5285,30 @@ SpinBox Ctrl+V + + + + :/Fractorium/Icons/square.png:/Fractorium/Icons/square.png + + + &Flatten + + + Add the Flatten variation to each xform + + + + + + :/Fractorium/Icons/cube.png:/Fractorium/Icons/cube.png + + + &Unflatten + + + Remove the Flatten variation from each xform + + diff --git a/Source/Fractorium/FractoriumEmberController.h b/Source/Fractorium/FractoriumEmberController.h index 1f0951c..06ed8b7 100644 --- a/Source/Fractorium/FractoriumEmberController.h +++ b/Source/Fractorium/FractoriumEmberController.h @@ -91,6 +91,8 @@ public: virtual void AddReflectiveSymmetry() { }//Tools. virtual void AddRotationalSymmetry() { } virtual void AddBothSymmetry() { } + virtual void Flatten() { } + virtual void Unflatten() { } virtual void ClearFlame() { } //Toolbar. @@ -298,6 +300,8 @@ public: virtual void AddReflectiveSymmetry(); virtual void AddRotationalSymmetry(); virtual void AddBothSymmetry(); + virtual void Flatten(); + virtual void Unflatten(); virtual void ClearFlame(); //Toolbar. diff --git a/Source/Fractorium/FractoriumMenus.cpp b/Source/Fractorium/FractoriumMenus.cpp index 1ef86c8..0693a39 100644 --- a/Source/Fractorium/FractoriumMenus.cpp +++ b/Source/Fractorium/FractoriumMenus.cpp @@ -31,6 +31,8 @@ void Fractorium::InitMenusUI() connect(ui.ActionAddRotationalSymmetry, SIGNAL(triggered(bool)), this, SLOT(OnActionAddRotationalSymmetry(bool)), Qt::QueuedConnection); connect(ui.ActionAddBothSymmetry, SIGNAL(triggered(bool)), this, SLOT(OnActionAddBothSymmetry(bool)), Qt::QueuedConnection); connect(ui.ActionClearFlame, SIGNAL(triggered(bool)), this, SLOT(OnActionClearFlame(bool)), Qt::QueuedConnection); + connect(ui.ActionFlatten, SIGNAL(triggered(bool)), this, SLOT(OnActionFlatten(bool)), Qt::QueuedConnection); + connect(ui.ActionUnflatten, SIGNAL(triggered(bool)), this, SLOT(OnActionUnflatten(bool)), Qt::QueuedConnection); connect(ui.ActionStopRenderingPreviews, SIGNAL(triggered(bool)), this, SLOT(OnActionStopRenderingPreviews(bool)), Qt::QueuedConnection); connect(ui.ActionRenderPreviews, SIGNAL(triggered(bool)), this, SLOT(OnActionRenderPreviews(bool)), Qt::QueuedConnection); connect(ui.ActionFinalRender, SIGNAL(triggered(bool)), this, SLOT(OnActionFinalRender(bool)), Qt::QueuedConnection); @@ -659,6 +661,22 @@ void FractoriumEmberController::AddBothSymmetry() void Fractorium::OnActionAddBothSymmetry(bool checked) { m_Controller->AddBothSymmetry(); } +/// +/// Adds a FlattenVariation to every xform in the current ember. +/// Resets the rendering process. +/// +template +void FractoriumEmberController::Flatten() { UpdateCurrentXform([&] (Xform* xform) { m_Ember.Flatten(XmlToEmber::m_FlattenNames); FillVariationTreeWithXform(xform); }); } +void Fractorium::OnActionFlatten(bool checked) { m_Controller->Flatten(); } + +/// +/// Removes pre/reg/post FlattenVariation from every xform in the current ember. +/// Resets the rendering process. +/// +template +void FractoriumEmberController::Unflatten() { UpdateCurrentXform([&] (Xform* xform) { m_Ember.Unflatten(); FillVariationTreeWithXform(xform); }); } +void Fractorium::OnActionUnflatten(bool checked) { m_Controller->Unflatten(); } + /// /// Delete all but one xform in the current ember. /// Clear that xform's variations. diff --git a/Source/Fractorium/FractoriumParams.cpp b/Source/Fractorium/FractoriumParams.cpp index fed89c9..66c995d 100644 --- a/Source/Fractorium/FractoriumParams.cpp +++ b/Source/Fractorium/FractoriumParams.cpp @@ -22,12 +22,13 @@ void Fractorium::InitParamsUI() SetFixedTableHeader(ui.IterationTableHeader->horizontalHeader()); //Color. - SetupSpinner(table, this, row, 1, m_BrightnessSpin, spinHeight, 0.05, 100, 1, SIGNAL(valueChanged(double)), SLOT(OnBrightnessChanged(double)), true, 4.0, 4.0, 4.0); - SetupSpinner(table, this, row, 1, m_GammaSpin, spinHeight, 1, 9999, 0.5, SIGNAL(valueChanged(double)), SLOT(OnGammaChanged(double)), true, 4.0, 4.0, 4.0); - SetupSpinner(table, this, row, 1, m_GammaThresholdSpin, spinHeight, 0, 10, 0.1, SIGNAL(valueChanged(double)), SLOT(OnGammaThresholdChanged(double)), true, 0.1, 0.1, 0.1); - SetupSpinner(table, this, row, 1, m_VibrancySpin, spinHeight, 0, 1, 0.01, SIGNAL(valueChanged(double)), SLOT(OnVibrancyChanged(double)), true, 1.0, 1.0, 1.0); - SetupSpinner(table, this, row, 1, m_HighlightSpin, spinHeight, -1.0, 2.0, 0.1, SIGNAL(valueChanged(double)), SLOT(OnHighlightPowerChanged(double)), true, -1.0, -1.0, -1.0); + SetupSpinner(table, this, row, 1, m_BrightnessSpin, spinHeight, 0.05, 100, 1, SIGNAL(valueChanged(double)), SLOT(OnBrightnessChanged(double)), true, 4.0, 4.0, 4.0); + SetupSpinner(table, this, row, 1, m_GammaSpin, spinHeight, 1, 9999, 0.5, SIGNAL(valueChanged(double)), SLOT(OnGammaChanged(double)), true, 4.0, 4.0, 4.0); + SetupSpinner(table, this, row, 1, m_GammaThresholdSpin, spinHeight, 0, 10, 0.01, SIGNAL(valueChanged(double)), SLOT(OnGammaThresholdChanged(double)), true, 0.1, 0.1, 0.0); + SetupSpinner(table, this, row, 1, m_VibrancySpin, spinHeight, 0, 30, 0.01, SIGNAL(valueChanged(double)), SLOT(OnVibrancyChanged(double)), true, 1.0, 1.0, 0.0); + SetupSpinner(table, this, row, 1, m_HighlightSpin, spinHeight, -1.0, 2.0, 0.1, SIGNAL(valueChanged(double)), SLOT(OnHighlightPowerChanged(double)), true, -1.0, -1.0, -1.0); + m_GammaThresholdSpin->setDecimals(4); m_BackgroundColorButton = new QPushButton("...", table); m_BackgroundColorButton->setMinimumWidth(21); m_BackgroundColorButton->setMaximumWidth(21); @@ -47,7 +48,7 @@ void Fractorium::InitParamsUI() SetupSpinner (table, this, row, 1, m_HeightSpin, spinHeight, 10, 100000, 50, SIGNAL(valueChanged(int)), SLOT(OnHeightChanged(int))); SetupSpinner(table, this, row, 1, m_CenterXSpin, spinHeight, -10, 10, 0.05, SIGNAL(valueChanged(double)), SLOT(OnCenterXChanged(double)), true, 0, 0, 0); SetupSpinner(table, this, row, 1, m_CenterYSpin, spinHeight, -10, 10, 0.05, SIGNAL(valueChanged(double)), SLOT(OnCenterYChanged(double)), true, 0, 0, 0); - SetupSpinner(table, this, row, 1, m_ScaleSpin, spinHeight, 10, 3000, 20, SIGNAL(valueChanged(double)), SLOT(OnScaleChanged(double)), true, 240, 240, 240); + SetupSpinner(table, this, row, 1, m_ScaleSpin, spinHeight, 10, 5000, 20, SIGNAL(valueChanged(double)), SLOT(OnScaleChanged(double)), true, 240, 240, 240); SetupSpinner(table, this, row, 1, m_ZoomSpin, spinHeight, 0, 5, 0.2, SIGNAL(valueChanged(double)), SLOT(OnZoomChanged(double)), true, 0, 0, 0); SetupSpinner(table, this, row, 1, m_RotateSpin, spinHeight, -180, 180, 10, SIGNAL(valueChanged(double)), SLOT(OnRotateChanged(double)), true, 0, 0, 0); SetupSpinner(table, this, row, 1, m_ZPosSpin, spinHeight, -1000, 1000, 1, SIGNAL(valueChanged(double)), SLOT(OnZPosChanged(double)), true, 0, 1, 0); diff --git a/Source/Fractorium/FractoriumXformsVariations.cpp b/Source/Fractorium/FractoriumXformsVariations.cpp index e3c571d..331ad52 100644 --- a/Source/Fractorium/FractoriumXformsVariations.cpp +++ b/Source/Fractorium/FractoriumXformsVariations.cpp @@ -55,6 +55,7 @@ void FractoriumEmberController::SetupVariationTree() spinBox->DoubleClickZero(1); spinBox->DoubleClickNonZero(0); spinBox->SmallStep(0.001); + spinBox->setDecimals(4); tree->setItemWidget(item, 1, spinBox); m_Fractorium->connect(spinBox, SIGNAL(valueChanged(double)), SLOT(OnVariationSpinBoxValueChanged(double)), Qt::QueuedConnection); @@ -85,6 +86,10 @@ void FractoriumEmberController::SetupVariationTree() varSpinBox->Step(1); varSpinBox->SmallStep(1); } + else + { + varSpinBox->setDecimals(4); + } tree->setItemWidget(paramWidget, 1, varSpinBox); m_Fractorium->connect(varSpinBox, SIGNAL(valueChanged(double)), SLOT(OnVariationSpinBoxValueChanged(double)), Qt::QueuedConnection); @@ -138,7 +143,7 @@ void FractoriumEmberController::VariationSpinBoxValueChanged(double d) { Variation* var = sender->GetVariation();//The variation attached to the sender, for reference only. ParametricVariation* parVar = dynamic_cast*>(var);//The parametric cast of that variation. - Variation* xformVar = xform->GetVariationByName(var->Name());//The corresponding variation in the currently selected xform. + Variation* xformVar = xform->GetVariationById(var->VariationId());//The corresponding variation in the currently selected xform. QList items = tree->findItems(QString::fromStdString(var->Name()), Qt::MatchExactly); bool isParam = parVar && sender->IsParam(); @@ -222,6 +227,8 @@ void FractoriumEmberController::FillVariationTreeWithXform(Xform* xform) { QTreeWidget* tree = m_Fractorium->ui.VariationsTree; + tree->blockSignals(true); + for (unsigned int i = 0; i < tree->topLevelItemCount(); i++) { QTreeWidgetItem* item = tree->topLevelItem(i); @@ -263,6 +270,7 @@ void FractoriumEmberController::FillVariationTreeWithXform(Xform* xform) } } + tree->blockSignals(false); m_Fractorium->OnTreeHeaderSectionClicked(m_Fractorium->m_VarSortMode); } diff --git a/Source/Fractorium/Icons/cube.png b/Source/Fractorium/Icons/cube.png new file mode 100644 index 0000000..f72e939 Binary files /dev/null and b/Source/Fractorium/Icons/cube.png differ diff --git a/Source/Fractorium/Icons/square.png b/Source/Fractorium/Icons/square.png new file mode 100644 index 0000000..610c7cc Binary files /dev/null and b/Source/Fractorium/Icons/square.png differ diff --git a/Source/Fractorium/Main.cpp b/Source/Fractorium/Main.cpp index 058c023..c8f32cb 100644 --- a/Source/Fractorium/Main.cpp +++ b/Source/Fractorium/Main.cpp @@ -16,6 +16,12 @@ int main(int argc, char *argv[]) QMessageBox::critical(QApplication::desktop(), "Error", "Fractorium cannot be run in test mode, undefine TEST_CL first."); return 1; #endif + +#ifdef ISAAC_FLAM3_DEBUG + QMessageBox::critical(QApplication::desktop(), "Error", "Fractorium cannot be run in test mode, undefine ISAAC_FLAM3_DEBUG first."); + return 1; +#endif + //Required for large allocs, else GPU memory usage will be severely limited to small sizes. //This must be done in the application and not in the EmberCL DLL. _putenv_s("GPU_MAX_ALLOC_PERCENT", "100");