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;