diff --git a/Builds/MSVC/Installer/Product.wxs b/Builds/MSVC/Installer/Product.wxs
index 0176d82..910442f 100644
--- a/Builds/MSVC/Installer/Product.wxs
+++ b/Builds/MSVC/Installer/Product.wxs
@@ -170,9 +170,6 @@
-
-
-
diff --git a/Data/Version History.txt b/Data/Version History.txt
index a5046f8..28572f3 100644
--- a/Data/Version History.txt
+++ b/Data/Version History.txt
@@ -1,6 +1,38 @@
+0.9.9.5 03/04/2016
+--User changes
+ -None.
+
+--Bug fixes
+ -Fix crash when using Lanczos2 filter with color curves due to negative numbers. Fix by passing abs() of first argument to pow() in Renderer::GammaCorrection().
+ -Fix crash in hexes with SP. Rounding error caused out of bounds index.
+ -Do not reset locked affine scale on new flame or undo.
+ -Gracefully recover from reading a bad palette file.
+ -Gracefully recover from reading flame file with unknown params.
+ -Available memory size checking in the final render dialog was accidentally removed during the multi-gpu work last year. Add it back in.
+
+--Code changes
+ -Migrate to Qt 5.5.1
+ -Remove dependency projects from the solution. Move to a project design where they are built once via command line and stored in a /Deps folder.
+ --Because of this, libpng is built as a static lib instead of a dll because that's what its command line makefile supports.
+ --Remove libpng16.dll from Wix installer.
+ -Remove all configs except for debug and release.
+ -Remove all platforms except for x64.
+ -Add #define __TBB_NO_IMPLICIT_LINKAGE 1 to prevent tbb from looking for tbb_debug.lib by default on debug builds.
+ -Put Ember.rc in a filter folder in the project.
+ -Place pragma warning disable statements in PCH files rather than in projects. This makes it easier when using Qt Creator.
+ -Move all resource files to the MSVC folder.
+ -Set all targets in QtCreator project to their lowercase names to be more *nix friendly. Set -l link statements to use these new lowercase names for ember and embercl.
+ -Rework Qt projects to favor shadow builds.
+ -Remove the symlinks.sh file and all references to it. It was never needed. Instead, just specify multiple include and link paths in the .pro files.
+ -Change WIN32 to _WIN32.
+ -Fix a few code warnings.
+ -Make usage of VarFuncs more consistent by moving some global functions there.
+ -Make CircleTrans1 a little safer by calling Zeps() on m_Sc during precalc.
+ -Major work on Qt Creator builds.
+
0.9.9.4 02/21/2016
--User changes
- -Allow for stopping the renderer in the main window. This makes is more efficient when entering many parameters, such as when following a tutorial.
+ -Allow for stopping the renderer in the main window. This makes it more efficient when entering many parameters, such as when following a tutorial.
-Add support for new variations: erf, gamma, jac_cn, jac_dn, jac_sn, logDB, pressure_wave, pRose3D, splits3D, w, waves2b, x, xerf, y, z.
-Inform user of the start and stop of file parsing in EmberAnimate because the files could potentially be very large.
-Move the follwing fields to a new table called Animation: Interpolation, Affine Interpolation, Temporal Samples, Temporal Filter Width, Temporal Filter Type.
diff --git a/Source/Ember/Utils.h b/Source/Ember/Utils.h
index 5e2f0df..2e1e97f 100644
--- a/Source/Ember/Utils.h
+++ b/Source/Ember/Utils.h
@@ -442,6 +442,38 @@ static inline T Clamp(T val, T min, T max)
return val;
}
+template <>
+#ifdef _WIN32
+ static
+#endif
+float Clamp(float val, float min, float max)
+{
+ if (val < min)
+ return min;
+ else if (val > max)
+ return max;
+ else if (!std::isfinite(val))
+ return min;
+ else
+ return val;
+}
+
+template <>
+#ifdef _WIN32
+ static
+#endif
+double Clamp(double val, double min, double max)
+{
+ if (val < min)
+ return min;
+ else if (val > max)
+ return max;
+ else if (!std::isfinite(val))
+ return min;
+ else
+ return val;
+}
+
///
/// Clamp and return a value to be greater than or equal to a specified minimum and less than
/// or equal to a specified maximum. If lesser, the value is fmod(val - min, max - min). If greater,
@@ -458,6 +490,8 @@ static inline T ClampMod(T val, T min, T max)
return min + fmod(val - min, max - min);
else if (val > max)
return max - fmod(max - val, max - min);
+ else if (!std::isfinite(val))
+ return min;
else
return val;
}
@@ -477,6 +511,34 @@ static inline void ClampRef(T& val, T min, T max)
val = max;
}
+template <>
+#ifdef _WIN32
+ static
+#endif
+void ClampRef(float& val, float min, float max)
+{
+ if (val < min)
+ val = min;
+ else if (val > max)
+ val = max;
+ else if (!std::isfinite(val))
+ val = min;
+}
+
+template <>
+#ifdef _WIN32
+ static
+#endif
+void ClampRef(double& val, double min, double max)
+{
+ if (val < min)
+ val = min;
+ else if (val > max)
+ val = max;
+ else if (!std::isfinite(val))
+ val = min;
+}
+
///
/// Similar to Clamp(), but clamps a reference value in place rather than returning.
///
@@ -489,6 +551,26 @@ static inline void ClampLteRef(T& val, T lte)
val = lte;
}
+template <>
+#ifdef _WIN32
+ static
+#endif
+void ClampLteRef(float& val, float lte)
+{
+ if (val > lte || !std::isfinite(val))
+ val = lte;
+}
+
+template <>
+#ifdef _WIN32
+ static
+#endif
+void ClampLteRef(double& val, double lte)
+{
+ if (val > lte || !std::isfinite(val))
+ val = lte;
+}
+
///
/// Clamp and return a value to be greater than or equal to a specified value.
/// Useful for ensuring something is not less than zero.
@@ -502,6 +584,30 @@ static inline T ClampGte(T val, T gte)
return (val < gte) ? gte : val;
}
+template <>
+#ifdef _WIN32
+ static
+#endif
+float ClampGte(float val, float gte)
+{
+ if (val < gte || !std::isfinite(val))
+ return gte;
+ else
+ return val;
+}
+
+template <>
+#ifdef _WIN32
+ static
+#endif
+double ClampGte(double val, double gte)
+{
+ if (val < gte || !std::isfinite(val))
+ return gte;
+ else
+ return val;
+}
+
///
/// Similar to Clamp(), but clamps a reference value in place rather than returning.
///
@@ -514,6 +620,26 @@ static inline void ClampGteRef(T& val, T gte)
val = gte;
}
+template <>
+#ifdef _WIN32
+ static
+#endif
+void ClampGteRef(float& val, float gte)
+{
+ if (val < gte || !std::isfinite(val))
+ val = gte;
+}
+
+template <>
+#ifdef _WIN32
+ static
+#endif
+void ClampGteRef(double& val, double gte)
+{
+ if (val < gte || !std::isfinite(val))
+ val = gte;
+}
+
///
/// Thin wrapper around a call to ClampGte() with a gte value of zero.
///
@@ -546,28 +672,6 @@ static inline T Round(T r)
return (r > 0) ? static_cast(Floor(r + T(0.5))) : ceil(r - T(0.5));
}
-///
-/// Special rounding for certain variations, gotten from Apophysis.
-///
-/// The value to round
-/// The rounded value
-static inline float LRint(float x)
-{
- int temp = (x >= 0 ? static_cast(x + 0.5f) : static_cast(x - 0.5f));
- return static_cast(temp);
-}
-
-///
-/// Special rounding for certain variations, gotten from Apophysis.
-///
-/// The value to round
-/// The rounded value
-static inline double LRint(double x)
-{
- glm::int64_t temp = (x >= 0 ? static_cast(x + 0.5) : static_cast(x - 0.5));
- return static_cast(temp);
-}
-
///
/// Never really understood what this did.
///
@@ -584,30 +688,6 @@ static inline T Round6(T r)
return static_cast(1e-6 * static_cast(r + T(0.5)));
}
-///
-/// Return -1 if the value is less than 0, 1 if it's greater and
-/// 0 if it's equal to 0.
-///
-/// The value to inspect
-/// -1, 0 or 1
-template
-static inline T Sign(T v)
-{
- return (v < 0) ? static_cast(-1) : (v > 0) ? static_cast(1) : static_cast(0);
-}
-
-///
-/// Return -1 if the value is less than 0, 1 if it's greater.
-/// This differs from Sign() in that it doesn't return 0.
-///
-/// The value to inspect
-/// -1 or 1
-template
-static inline T SignNz(T v)
-{
- return (v < 0) ? static_cast(-1) : static_cast(1);
-}
-
///
/// Return the square of the passed in value.
/// This is useful when the value is a result of a computation
@@ -622,16 +702,16 @@ static inline T Sqr(T t)
}
///
-/// Taking the square root of numbers close to zero is dangerous. If x is negative
-/// due to floating point errors, it can return NaN results.
+/// Return the cube of the passed in value.
+/// This is useful when the value is a result of a computation
+/// rather than a fixed number. Otherwise, use the CUBE macro.
///
+/// The value to cube
+/// The cubed value
template
-static inline T SafeSqrt(T x)
+static inline T Cube(T t)
{
- if (x <= 0)
- return 0;
-
- return std::sqrt(x);
+ return t * t * t;
}
template
@@ -658,83 +738,6 @@ double SafeTan(double x)
return std::tan(x);
}
-///
-/// If r < EPS, return 1 / r.
-/// Else, return q / r.
-///
-/// The numerator
-/// The denominator
-/// The quotient
-template
-static inline T SafeDivInv(T q, T r)
-{
- if (r < EPS)
- return 1 / r;
-
- return q / r;
-}
-
-///
-/// Return the cube of the passed in value.
-/// This is useful when the value is a result of a computation
-/// rather than a fixed number. Otherwise, use the CUBE macro.
-///
-/// The value to cube
-/// The cubed value
-template
-static inline T Cube(T t)
-{
- return t * t * t;
-}
-
-///
-/// Return the hypotenuse of the passed in values.
-///
-/// The x distance
-/// The y distance
-/// The hypotenuse
-template
-static inline T Hypot(T x, T y)
-{
- return std::sqrt(SQR(x) + SQR(y));
-}
-
-///
-/// Spread the values.
-///
-/// The x distance
-/// The y distance
-/// The spread
-template
-static inline T Spread(T x, T y)
-{
- return Hypot(x, y) * ((x) > 0 ? 1 : -1);
-}
-
-///
-/// Unsure.
-///
-/// The x distance
-/// The y distance
-/// The powq4
-template
-static inline T Powq4(T x, T y)
-{
- return std::pow(std::abs(x), y) * SignNz(x);
-}
-
-///
-/// Unsure.
-///
-/// The x distance
-/// The y distance
-/// The powq4c
-template
-static inline T Powq4c(T x, T y)
-{
- return y == 1 ? x : Powq4(x, y);
-}
-
///
/// Return EPS if the passed in value was zero, else return the value.
///
@@ -760,66 +763,6 @@ static inline T Lerp(T a, T b, T p)
return a + (b - a) * p;
}
-///
-/// Thin wrapper around a call to modf that discards the integer portion
-/// and returns the signed fractional portion.
-///
-/// The value to retrieve the signed fractional portion of.
-/// The signed fractional portion of v.
-template
-static inline T Fabsmod(T v)
-{
- T dummy;
- return modf(v, &dummy);
-}
-
-///
-/// Unsure.
-///
-/// Unsure.
-/// Unsure.
-/// Unsure.
-/// Unsure.
-template
-static inline T Fosc(T p, T amp, T ph)
-{
- return T(0.5) - std::cos(p * amp + ph) * T(0.5);
-}
-
-///
-/// Unsure.
-///
-/// Unsure.
-/// Unsure.
-/// Unsure.
-template
-static inline T Foscn(T p, T ph)
-{
- return T(0.5) - std::cos(p + ph) * T(0.5);
-}
-
-///
-/// Log scale from Apophysis.
-///
-/// The value to log scale
-/// The log scaled value
-template
-static inline T LogScale(T x)
-{
- return x == 0 ? 0 : std::log((fabs(x) + 1) * T(M_E)) * SignNz(x) / T(M_E);
-}
-
-///
-/// Log map from Apophysis.
-///
-/// The value to log map
-/// The log mapped value
-template
-static inline T LogMap(T x)
-{
- return x == 0 ? 0 : (T(M_E) + std::log(x * T(M_E))) * T(0.25) * SignNz(x);
-}
-
///
/// Thin wrapper around calling xmlStrcmp() on an Xml tag to tell
/// if its name is a given value.
@@ -877,23 +820,6 @@ static inline T NormalizeDeg180(T angle)
return a;
}
-///
-/// Put an angular measurement in degrees into the range of 0 - 360.
-///
-/// The angle to normalize
-/// The normalized angle in a range of 0 - 360
-template
-static inline T NormalizeDeg360(T angle)
-{
- if (angle > 360 || angle < -360)
- angle = fmod(angle, 360);
-
- if (angle < 0)
- angle += 360;
-
- return angle;
-}
-
///
/// Return a lower case copy of a string.
///
@@ -979,7 +905,7 @@ static inline T Arg(char* name, T def)
{
char* ch;
T returnVal;
-#ifdef WIN32
+#ifdef _WIN32
size_t len;
errno_t err = _dupenv_s(&ch, &len, name);
#else
@@ -1001,7 +927,7 @@ static inline T Arg(char* name, T def)
returnVal = def;
}
-#ifdef WIN32
+#ifdef _WIN32
free(ch);
#endif
return returnVal;
@@ -1036,7 +962,7 @@ string Arg(char* name, string def)
{
char* ch;
string returnVal;
-#ifdef WIN32
+#ifdef _WIN32
size_t len;
errno_t err = _dupenv_s(&ch, &len, name);
#else
@@ -1052,7 +978,7 @@ string Arg(char* name, string def)
else
returnVal = string(ch);
-#ifdef WIN32
+#ifdef _WIN32
free(ch);
#endif
return returnVal;