--Code changes

-Convert all enums to class enum to be consistent with C++11 style.
 -Convert some if/else statements in filter classes to case statements.
 -Add overloaded stream operators to print various enums.
This commit is contained in:
mfeemster 2015-12-31 16:00:36 -08:00
parent 1dc363d190
commit c8e2355ec2
27 changed files with 1081 additions and 925 deletions

View File

@ -17,7 +17,7 @@ namespace EmberNs
/// Bit position specifying the presence of each type of 3D parameter.
/// One, none, some or all of these can be present.
/// </summary>
enum eProjBits
enum class eProjBits : size_t
{
PROJBITS_ZPOS = 1,
PROJBITS_PERSP = 2,
@ -214,22 +214,22 @@ public:
m_HighlightPower = -1;
m_Time = 0;
m_Background.Reset();
m_Interp = EMBER_INTERP_LINEAR;
m_AffineInterp = AFFINE_INTERP_LOG;
m_Interp = eInterp::EMBER_INTERP_LINEAR;
m_AffineInterp = eAffineInterp::AFFINE_INTERP_LOG;
//DE filter.
m_MinRadDE = 0;
m_MaxRadDE = 9;
m_CurveDE = T(0.4);
//Spatial filter.
m_SpatialFilterType = GAUSSIAN_SPATIAL_FILTER;
m_SpatialFilterType = eSpatialFilterType::GAUSSIAN_SPATIAL_FILTER;
m_SpatialFilterRadius = T(0.5);
//Temporal filter.
m_TemporalFilterType = BOX_TEMPORAL_FILTER;
m_TemporalFilterType = eTemporalFilterType::BOX_TEMPORAL_FILTER;
m_TemporalFilterExp = 0;
m_TemporalFilterWidth = 1;
//Palette.
m_PaletteMode = PALETTE_LINEAR;
m_PaletteInterp = INTERP_HSV;
m_PaletteMode = ePaletteMode::PALETTE_LINEAR;
m_PaletteInterp = ePaletteInterp::INTERP_HSV;
//Curves.
m_Curves.Init();
m_Name = "No name";
@ -493,16 +493,16 @@ public:
m_CamMat[1][2] = std::sin(m_CamPitch) * std::cos(-m_CamYaw);
m_CamMat[2][2] = std::cos(m_CamPitch);
if (projBits & PROJBITS_BLUR)
if (projBits & size_t(eProjBits::PROJBITS_BLUR))
{
if (projBits & PROJBITS_YAW)
if (projBits & size_t(eProjBits::PROJBITS_YAW))
m_ProjFunc = &EmberNs::Ember<T>::ProjectPitchYawDepthBlur;
else
m_ProjFunc = &EmberNs::Ember<T>::ProjectPitchDepthBlur;
}
else if ((projBits & PROJBITS_PITCH) || (projBits & PROJBITS_YAW))
else if ((projBits & size_t(eProjBits::PROJBITS_PITCH)) || (projBits & size_t(eProjBits::PROJBITS_YAW)))
{
if (projBits & PROJBITS_YAW)
if (projBits & size_t(eProjBits::PROJBITS_YAW))
m_ProjFunc = &EmberNs::Ember<T>::ProjectPitchYaw;
else
m_ProjFunc = &EmberNs::Ember<T>::ProjectPitch;
@ -548,9 +548,9 @@ public:
{
if ((onlyScaleIfNewIsSmaller && (width < m_OrigFinalRasW || height < m_OrigFinalRasH)) || !onlyScaleIfNewIsSmaller)
{
if (scaleType == SCALE_WIDTH)
if (scaleType == eScaleType::SCALE_WIDTH)
m_PixelsPerUnit = m_OrigPixPerUnit * (T(width) / T(m_OrigFinalRasW));
else if (scaleType == SCALE_HEIGHT)
else if (scaleType == eScaleType::SCALE_HEIGHT)
m_PixelsPerUnit = m_OrigPixPerUnit * (T(height) / T(m_OrigFinalRasH));
}
@ -717,7 +717,7 @@ public:
vector<Xform<T>*> xformVec;
//Palette and others
if (embers[0].m_PaletteInterp == INTERP_HSV)
if (embers[0].m_PaletteInterp == ePaletteInterp::INTERP_HSV)
{
for (glm::length_t i = 0; i < 256; i++)
{
@ -740,7 +740,7 @@ public:
Clamp<T>(m_Palette[i][j], 0, 1);
}
}
else if (embers[0].m_PaletteInterp == INTERP_SWEEP)
else if (embers[0].m_PaletteInterp == ePaletteInterp::INTERP_SWEEP)
{
//Sweep - not the best option for float indices.
for (glm::length_t i = 0; i < 256; i++)
@ -888,7 +888,7 @@ public:
ClampRef<T>(thisXform->m_ColorSpeed, -1, 1);
//Interp affine and post.
if (m_AffineInterp == AFFINE_INTERP_LOG)
if (m_AffineInterp == eAffineInterp::AFFINE_INTERP_LOG)
{
vector<v2T> cxMag(size);
vector<v2T> cxAng(size);
@ -922,7 +922,7 @@ public:
Interpolater<T>::InterpAndConvertBack(coefs, cxAng, cxMag, cxTrn, thisXform->m_Post);
}
}
else if (m_AffineInterp == AFFINE_INTERP_LINEAR)
else if (m_AffineInterp == eAffineInterp::AFFINE_INTERP_LINEAR)
{
//Interpolate pre and post affine using coefs.
allID = true;
@ -1033,7 +1033,7 @@ public:
continue;
//Assume that if there are no variations, then it's a padding xform.
if (m_Xforms[i].Empty() && m_AffineInterp != AFFINE_INTERP_LOG)
if (m_Xforms[i].Empty() && m_AffineInterp != eAffineInterp::AFFINE_INTERP_LOG)
continue;
m_Xforms[i].m_Affine.Rotate(angle);
@ -1136,15 +1136,15 @@ public:
{
size_t val = 0;
if (m_CamZPos != 0) val |= PROJBITS_ZPOS;
if (m_CamZPos != 0) val |= size_t(eProjBits::PROJBITS_ZPOS);
if (m_CamPerspective != 0) val |= PROJBITS_PERSP;
if (m_CamPerspective != 0) val |= size_t(eProjBits::PROJBITS_PERSP);
if (m_CamPitch != 0) val |= PROJBITS_PITCH;
if (m_CamPitch != 0) val |= size_t(eProjBits::PROJBITS_PITCH);
if (m_CamYaw != 0) val |= PROJBITS_YAW;
if (m_CamYaw != 0) val |= size_t(eProjBits::PROJBITS_YAW);
if (m_CamDepthBlur != 0) val |= PROJBITS_BLUR;
if (m_CamDepthBlur != 0) val |= size_t(eProjBits::PROJBITS_BLUR);
return val;
}
@ -1272,75 +1272,75 @@ public:
switch (param.first)
{
case FLAME_MOTION_ZOOM:
case eEmberMotionParam::FLAME_MOTION_ZOOM:
APP_FMP(m_Zoom);
break;
case FLAME_MOTION_ZPOS:
case eEmberMotionParam::FLAME_MOTION_ZPOS:
APP_FMP(m_CamZPos);
break;
case FLAME_MOTION_PERSPECTIVE:
case eEmberMotionParam::FLAME_MOTION_PERSPECTIVE:
APP_FMP(m_CamPerspective);
break;
case FLAME_MOTION_YAW:
case eEmberMotionParam::FLAME_MOTION_YAW:
APP_FMP(m_CamYaw);
break;
case FLAME_MOTION_PITCH:
case eEmberMotionParam::FLAME_MOTION_PITCH:
APP_FMP(m_CamPitch);
break;
case FLAME_MOTION_DEPTH_BLUR:
case eEmberMotionParam::FLAME_MOTION_DEPTH_BLUR:
APP_FMP(m_CamDepthBlur);
break;
case FLAME_MOTION_CENTER_X:
case eEmberMotionParam::FLAME_MOTION_CENTER_X:
APP_FMP(m_CenterX);
break;
case FLAME_MOTION_CENTER_Y:
case eEmberMotionParam::FLAME_MOTION_CENTER_Y:
APP_FMP(m_CenterY);
break;
case FLAME_MOTION_ROTATE:
case eEmberMotionParam::FLAME_MOTION_ROTATE:
APP_FMP(m_Rotate);
break;
case FLAME_MOTION_BRIGHTNESS:
case eEmberMotionParam::FLAME_MOTION_BRIGHTNESS:
APP_FMP(m_Brightness);
break;
case FLAME_MOTION_GAMMA:
case eEmberMotionParam::FLAME_MOTION_GAMMA:
APP_FMP(m_Gamma);
break;
case FLAME_MOTION_GAMMA_THRESH:
case eEmberMotionParam::FLAME_MOTION_GAMMA_THRESH:
APP_FMP(m_GammaThresh);
break;
case FLAME_MOTION_HIGHLIGHT_POWER:
case eEmberMotionParam::FLAME_MOTION_HIGHLIGHT_POWER:
APP_FMP(m_HighlightPower);
break;
case FLAME_MOTION_BACKGROUND_R:
case eEmberMotionParam::FLAME_MOTION_BACKGROUND_R:
APP_FMP(m_Background.r);
break;
case FLAME_MOTION_BACKGROUND_G:
case eEmberMotionParam::FLAME_MOTION_BACKGROUND_G:
APP_FMP(m_Background.g);
break;
case FLAME_MOTION_BACKGROUND_B:
case eEmberMotionParam::FLAME_MOTION_BACKGROUND_B:
APP_FMP(m_Background.b);
break;
case FLAME_MOTION_VIBRANCY:
case eEmberMotionParam::FLAME_MOTION_VIBRANCY:
APP_FMP(m_Vibrancy);
break;
case FLAME_MOTION_NONE:
case eEmberMotionParam::FLAME_MOTION_NONE:
default:
break;
}
@ -1364,8 +1364,8 @@ public:
m_Symmetry = 0;
m_Rotate = 0;
m_PixelsPerUnit = 50;
m_Interp = EMBER_INTERP_LINEAR;
m_PaletteInterp = INTERP_HSV;
m_Interp = eInterp::EMBER_INTERP_LINEAR;
m_PaletteInterp = ePaletteInterp::INTERP_HSV;
m_Index = 0;
m_ParentFilename = "";
m_ScaleType = eScaleType::SCALE_NONE;
@ -1394,12 +1394,12 @@ public:
m_CurveDE = T(0.4);
m_GammaThresh = T(0.01);
m_TemporalSamples = 100;
m_SpatialFilterType = GAUSSIAN_SPATIAL_FILTER;
m_AffineInterp = AFFINE_INTERP_LOG;
m_TemporalFilterType = BOX_TEMPORAL_FILTER;
m_SpatialFilterType = eSpatialFilterType::GAUSSIAN_SPATIAL_FILTER;
m_AffineInterp = eAffineInterp::AFFINE_INTERP_LOG;
m_TemporalFilterType = eTemporalFilterType::BOX_TEMPORAL_FILTER;
m_TemporalFilterWidth = 1;
m_TemporalFilterExp = 0;
m_PaletteMode = PALETTE_STEP;
m_PaletteMode = ePaletteMode::PALETTE_STEP;
}
else
{
@ -1425,12 +1425,12 @@ public:
m_CurveDE = -1;
m_GammaThresh = -1;
m_TemporalSamples = 0;
m_SpatialFilterType = GAUSSIAN_SPATIAL_FILTER;
m_AffineInterp = AFFINE_INTERP_LOG;
m_TemporalFilterType = BOX_TEMPORAL_FILTER;
m_SpatialFilterType = eSpatialFilterType::GAUSSIAN_SPATIAL_FILTER;
m_AffineInterp = eAffineInterp::AFFINE_INTERP_LOG;
m_TemporalFilterType = eTemporalFilterType::BOX_TEMPORAL_FILTER;
m_TemporalFilterWidth = -1;
m_TemporalFilterExp = -999;
m_PaletteMode = PALETTE_STEP;
m_PaletteMode = ePaletteMode::PALETTE_STEP;
}
m_Xforms.clear();

View File

@ -29,13 +29,13 @@
//Wrap the sincos function for Macs and PC.
#if defined(__APPLE__) || defined(_MSC_VER)
#define sincos(x, s, c) *(s)=std::sin(x); *(c)=std::cos(x);
#define sincos(x, s, c) *(s)=std::sin(x); *(c)=std::cos(x);
#else
static void sincos(float x, float* s, float* c)
{
*s = std::sin(x);
*c = std::cos(x);
}
static void sincos(float x, float* s, float* c)
{
*s = std::sin(x);
*c = std::cos(x);
}
#endif
namespace EmberNs
@ -92,9 +92,9 @@ static inline size_t NowMs()
//These two must always match.
#ifdef WIN32
#define ALIGN __declspec(align(16))
#define ALIGN __declspec(align(16))
#else
#define ALIGN __attribute__ ((aligned (16)))
#define ALIGN __attribute__ ((aligned (16)))
#endif
#define ALIGN_CL "((aligned (16)))"//The extra parens are necessary.
@ -119,35 +119,211 @@ static inline size_t NowMs()
#define m23T glm::detail::tmat2x3<T, glm::defaultp>
#endif
enum eInterp : uint { EMBER_INTERP_LINEAR = 0, EMBER_INTERP_SMOOTH = 1 };
enum eAffineInterp : uint { AFFINE_INTERP_LINEAR = 0, AFFINE_INTERP_LOG = 1, AFFINE_INTERP_COMPAT = 2, AFFINE_INTERP_OLDER = 3 };
enum ePaletteMode : uint { PALETTE_STEP = 0, PALETTE_LINEAR = 1 };
enum ePaletteInterp : uint { INTERP_HSV = 0, INTERP_SWEEP = 1 };
enum eMotion : uint { MOTION_SIN = 1, MOTION_TRIANGLE = 2, MOTION_HILL = 3, MOTION_SAW = 4 };
enum eProcessAction : uint { NOTHING = 0, ACCUM_ONLY = 1, FILTER_AND_ACCUM = 2, KEEP_ITERATING = 3, FULL_RENDER = 4 };
enum eProcessState : uint { NONE = 0, ITER_STARTED = 1, ITER_DONE = 2, FILTER_DONE = 3, ACCUM_DONE = 4 };
enum eInteractiveFilter : uint { FILTER_LOG = 0, FILTER_DE = 1 };
enum eScaleType : uint { SCALE_NONE = 0, SCALE_WIDTH = 1, SCALE_HEIGHT = 2 };
enum eRenderStatus : uint { RENDER_OK = 0, RENDER_ERROR = 1, RENDER_ABORT = 2 };
enum eEmberMotionParam : uint
enum class eInterp : uint { EMBER_INTERP_LINEAR = 0, EMBER_INTERP_SMOOTH = 1 };
enum class eAffineInterp : uint { AFFINE_INTERP_LINEAR = 0, AFFINE_INTERP_LOG = 1, AFFINE_INTERP_COMPAT = 2, AFFINE_INTERP_OLDER = 3 };
enum class ePaletteMode : uint { PALETTE_STEP = 0, PALETTE_LINEAR = 1 };
enum class ePaletteInterp : uint { INTERP_HSV = 0, INTERP_SWEEP = 1 };
enum class eMotion : uint { MOTION_SIN = 1, MOTION_TRIANGLE = 2, MOTION_HILL = 3, MOTION_SAW = 4 };
enum class eProcessAction : uint { NOTHING = 0, ACCUM_ONLY = 1, FILTER_AND_ACCUM = 2, KEEP_ITERATING = 3, FULL_RENDER = 4 };
enum class eProcessState : uint { NONE = 0, ITER_STARTED = 1, ITER_DONE = 2, FILTER_DONE = 3, ACCUM_DONE = 4 };
enum class eInteractiveFilter : uint { FILTER_LOG = 0, FILTER_DE = 1 };
enum class eScaleType : uint { SCALE_NONE = 0, SCALE_WIDTH = 1, SCALE_HEIGHT = 2 };
enum class eRenderStatus : uint { RENDER_OK = 0, RENDER_ERROR = 1, RENDER_ABORT = 2 };
enum class eEmberMotionParam : uint//These must remain in this order forever.
{
FLAME_MOTION_NONE = 0,
FLAME_MOTION_ZOOM = 1,
FLAME_MOTION_ZPOS = 2,
FLAME_MOTION_PERSPECTIVE = 3,
FLAME_MOTION_YAW = 4,
FLAME_MOTION_PITCH = 5,
FLAME_MOTION_DEPTH_BLUR = 6,
FLAME_MOTION_CENTER_X = 7,
FLAME_MOTION_CENTER_Y = 8,
FLAME_MOTION_ROTATE = 9,
FLAME_MOTION_BRIGHTNESS = 10,
FLAME_MOTION_GAMMA = 11,
FLAME_MOTION_GAMMA_THRESH = 12,
FLAME_MOTION_HIGHLIGHT_POWER = 13,
FLAME_MOTION_BACKGROUND_R = 14,
FLAME_MOTION_BACKGROUND_G = 15,
FLAME_MOTION_BACKGROUND_B = 16,
FLAME_MOTION_VIBRANCY = 17
FLAME_MOTION_NONE,
FLAME_MOTION_ZOOM,
FLAME_MOTION_ZPOS,
FLAME_MOTION_PERSPECTIVE,
FLAME_MOTION_YAW,
FLAME_MOTION_PITCH,
FLAME_MOTION_DEPTH_BLUR,
FLAME_MOTION_CENTER_X,
FLAME_MOTION_CENTER_Y,
FLAME_MOTION_ROTATE,
FLAME_MOTION_BRIGHTNESS,
FLAME_MOTION_GAMMA,
FLAME_MOTION_GAMMA_THRESH,
FLAME_MOTION_HIGHLIGHT_POWER,
FLAME_MOTION_BACKGROUND_R,
FLAME_MOTION_BACKGROUND_G,
FLAME_MOTION_BACKGROUND_B,
FLAME_MOTION_VIBRANCY
};
/// <summary>
/// Thin wrapper to allow << operator on interp type.
/// </summary>
/// <param name="stream">The stream to insert into</param>
/// <param name="t">The type whose string representation will be inserted into the stream</param>
/// <returns></returns>
static std::ostream& operator<<(std::ostream& stream, const eInterp& t)
{
switch (t)
{
case EmberNs::eInterp::EMBER_INTERP_LINEAR:
stream << "linear";
break;
case EmberNs::eInterp::EMBER_INTERP_SMOOTH:
stream << "smooth";
break;
default:
stream << "error";
break;
}
return stream;
}
/// <summary>
/// Thin wrapper to allow << operator on affine interp type.
/// </summary>
/// <param name="stream">The stream to insert into</param>
/// <param name="t">The type whose string representation will be inserted into the stream</param>
/// <returns></returns>
static std::ostream& operator<<(std::ostream& stream, const eAffineInterp& t)
{
switch (t)
{
case EmberNs::eAffineInterp::AFFINE_INTERP_LINEAR:
stream << "linear";
break;
case EmberNs::eAffineInterp::AFFINE_INTERP_LOG:
stream << "log";
break;
case EmberNs::eAffineInterp::AFFINE_INTERP_COMPAT:
stream << "compat";
break;
case EmberNs::eAffineInterp::AFFINE_INTERP_OLDER:
stream << "older";
break;
default:
stream << "error";
break;
}
return stream;
}
/// <summary>
/// Thin wrapper to allow << operator on palette mode type.
/// </summary>
/// <param name="stream">The stream to insert into</param>
/// <param name="t">The type whose string representation will be inserted into the stream</param>
/// <returns></returns>
static std::ostream& operator<<(std::ostream& stream, const ePaletteMode& t)
{
switch (t)
{
case EmberNs::ePaletteMode::PALETTE_STEP:
stream << "step";
break;
case EmberNs::ePaletteMode::PALETTE_LINEAR:
stream << "linear";
break;
default:
stream << "error";
break;
}
return stream;
}
/// <summary>
/// Thin wrapper to allow << operator on palette interp type.
/// </summary>
/// <param name="stream">The stream to insert into</param>
/// <param name="t">The type whose string representation will be inserted into the stream</param>
/// <returns></returns>
static std::ostream& operator<<(std::ostream& stream, const ePaletteInterp& t)
{
switch (t)
{
case EmberNs::ePaletteInterp::INTERP_HSV:
stream << "hsv";
break;
case EmberNs::ePaletteInterp::INTERP_SWEEP:
stream << "sweep";
break;
default:
stream << "error";
break;
}
return stream;
}
/// <summary>
/// Thin wrapper to allow << operator on scale type.
/// </summary>
/// <param name="stream">The stream to insert into</param>
/// <param name="t">The type whose string representation will be inserted into the stream</param>
/// <returns></returns>
static std::ostream& operator<<(std::ostream& stream, const eScaleType& t)
{
switch (t)
{
case EmberNs::eScaleType::SCALE_NONE:
stream << "none";
break;
case EmberNs::eScaleType::SCALE_WIDTH:
stream << "width";
break;
case EmberNs::eScaleType::SCALE_HEIGHT:
stream << "height";
break;
default:
stream << "error";
break;
}
return stream;
}
/// <summary>
/// Thin wrapper to allow << operator on motion type.
/// </summary>
/// <param name="stream">The stream to insert into</param>
/// <param name="t">The type whose string representation will be inserted into the stream</param>
/// <returns></returns>
static std::ostream& operator<<(std::ostream& stream, const eMotion& t)
{
switch (t)
{
case EmberNs::eMotion::MOTION_SIN:
stream << "sin";
break;
case EmberNs::eMotion::MOTION_TRIANGLE:
stream << "triangle";
break;
case EmberNs::eMotion::MOTION_HILL:
stream << "hill";
break;
case EmberNs::eMotion::MOTION_SAW:
stream << "saw";
break;
default:
stream << "error";
break;
}
return stream;
}
}

View File

@ -69,11 +69,10 @@ public:
/// <param name="other">The MotionParam object to copy.</param>
/// <returns>Reference to updated self</returns>
template <typename U>
MotionParam &operator = (const MotionParam<U>& other)
MotionParam& operator = (const MotionParam<U>& other)
{
this->first = other.first;
this->second = T(other.second);
return *this;
}
};
@ -94,7 +93,7 @@ public:
EmberMotion()
{
m_MotionFreq = 0;
m_MotionFunc = MOTION_SIN;
m_MotionFunc = eMotion::MOTION_SIN;
m_MotionOffset = 0;
}
@ -135,7 +134,7 @@ public:
/// <param name="other">The EmberMotion object to copy.</param>
/// <returns>Reference to updated self</returns>
template <typename U>
EmberMotion &operator = (const EmberMotion<U>& other)
EmberMotion& operator = (const EmberMotion<U>& other)
{
CopyVec(m_MotionParams, other.m_MotionParams);
m_MotionFunc = other.m_MotionFunc;

View File

@ -43,7 +43,6 @@ public:
bool Save(const string& filename, Ember<T>& ember, size_t printEditDepth, bool doEdits, bool intPalette, bool hexPalette, bool append = false, bool start = false, bool finish = false)
{
vector<Ember<T>> vec;
vec.push_back(ember);
return Save(filename, vec, printEditDepth, doEdits, intPalette, hexPalette, append, start, finish);
}
@ -154,7 +153,6 @@ public:
string s;
ostringstream os;
vector<Variation<T>*> variations;
os << "<flame version=\"EMBER-" << EmberVersion() << "\" time=\"" << ember.m_Time << "\"";
if (!ember.m_Name.empty())
@ -170,11 +168,10 @@ public:
os << " rotate=\"" << ember.m_Rotate << "\"";
os << " supersample=\"" << std::max<size_t>(1, ember.m_Supersample) << "\"";
os << " filter=\"" << ember.m_SpatialFilterRadius << "\"";
os << " filter_shape=\"" << ToLower(SpatialFilterCreator<T>::ToString(ember.m_SpatialFilterType)) << "\"";
os << " temporal_filter_type=\"" << ToLower(TemporalFilterCreator<T>::ToString(ember.m_TemporalFilterType)) << "\"";
if (ember.m_TemporalFilterType == EXP_TEMPORAL_FILTER)
if (ember.m_TemporalFilterType == eTemporalFilterType::EXP_TEMPORAL_FILTER)
os << " temporal_filter_exp=\"" << ember.m_TemporalFilterExp << "\"";
os << " temporal_filter_width=\"" << ember.m_TemporalFilterWidth << "\"";
@ -197,26 +194,26 @@ public:
os << " cam_pitch=\"" << ember.m_CamPitch << "\"";
os << " cam_dof=\"" << ember.m_CamDepthBlur << "\"";
if (ember.m_PaletteMode == PALETTE_STEP)
if (ember.m_PaletteMode == ePaletteMode::PALETTE_STEP)
os << " palette_mode=\"step\"";
else if (ember.m_PaletteMode == PALETTE_LINEAR)
else if (ember.m_PaletteMode == ePaletteMode::PALETTE_LINEAR)
os << " palette_mode=\"linear\"";
if (ember.m_Interp == EMBER_INTERP_LINEAR)
if (ember.m_Interp == eInterp::EMBER_INTERP_LINEAR)
os << " interpolation=\"linear\"";
else if (ember.m_Interp == EMBER_INTERP_SMOOTH)
else if (ember.m_Interp == eInterp::EMBER_INTERP_SMOOTH)
os << " interpolation=\"smooth\"";
if (ember.m_AffineInterp == AFFINE_INTERP_LINEAR)
if (ember.m_AffineInterp == eAffineInterp::AFFINE_INTERP_LINEAR)
os << " interpolation_type=\"linear\"";
else if (ember.m_AffineInterp == AFFINE_INTERP_LOG)
else if (ember.m_AffineInterp == eAffineInterp::AFFINE_INTERP_LOG)
os << " interpolation_type=\"log\"";
else if (ember.m_AffineInterp == AFFINE_INTERP_COMPAT)
else if (ember.m_AffineInterp == eAffineInterp::AFFINE_INTERP_COMPAT)
os << " interpolation_type=\"old\"";
else if (ember.m_AffineInterp == AFFINE_INTERP_OLDER)
else if (ember.m_AffineInterp == eAffineInterp::AFFINE_INTERP_OLDER)
os << " interpolation_type=\"older\"";
if (ember.m_PaletteInterp == INTERP_SWEEP)
if (ember.m_PaletteInterp == ePaletteInterp::INTERP_SWEEP)
os << " palette_interpolation=\"sweep\"";
if (!extraAttributes.empty())
@ -273,7 +270,6 @@ public:
for (j = 0; j < 8; j++)
{
size_t idx = 8 * i + j;
os << hex << setw(2) << setfill('0') << int(Rint(ember.m_Palette[idx][0] * 255));
os << hex << setw(2) << setfill('0') << int(Rint(ember.m_Palette[idx][1] * 255));
os << hex << setw(2) << setfill('0') << int(Rint(ember.m_Palette[idx][2] * 255));
@ -292,8 +288,8 @@ public:
double g = ember.m_Palette[i][1] * 255;
double b = ember.m_Palette[i][2] * 255;
double a = ember.m_Palette[i][3] * 255;
os << " ";
//The original used a precision of 6 which is totally unnecessary, use 2.
if (IsClose(a, 255.0))
{
@ -318,7 +314,6 @@ public:
os << ToString(xmlDocGetRootElement(ember.m_Edits), 1, true, printEditDepth);
os << "</flame>\n";
return os.str();
}
@ -347,11 +342,9 @@ public:
xmlNodePtr rootNode = nullptr, node = nullptr, nodeCopy = nullptr;
xmlNodePtr rootComment = nullptr;
ostringstream os;
//Create the root node, called "edit".
rootNode = xmlNewNode(nullptr, XC("edit"));
xmlDocSetRootElement(doc, rootNode);
//Add the edit attributes.
//Date.
myTime = time(nullptr);
@ -385,13 +378,11 @@ public:
{
//Create a child node of the root node called sheep.
node = xmlNewChild(rootNode, nullptr, XC("sheep"), nullptr);
//Create the sheep attributes.
os << sheepGen;
s = os.str();
xmlNewProp(node, XC("generation"), XC(s.c_str()));
os.str("");
os << sheepId;
s = os.str();
xmlNewProp(node, XC("id"), XC(s.c_str()));
@ -411,7 +402,6 @@ public:
node = xmlDocGetRootElement(parent0->m_Edits);
nodeCopy = xmlCopyNode(node, 1);
AddFilenameWithoutAmpersand(nodeCopy, parent0->m_ParentFilename);
xmlNewProp(nodeCopy, XC("index"), XC(s.c_str()));
xmlAddChild(rootNode, nodeCopy);
}
@ -443,7 +433,7 @@ public:
else
{
//Insert a (parent has no edit) message.
nodeCopy = xmlNewChild(rootNode, nullptr, XC("edit"),nullptr);
nodeCopy = xmlNewChild(rootNode, nullptr, XC("edit"), nullptr);
AddFilenameWithoutAmpersand(nodeCopy, parent1->m_ParentFilename);
xmlNewProp(nodeCopy, XC("index"), XC(s.c_str()));
}
@ -468,7 +458,6 @@ public:
//Check for errors.
if (commentDoc)
{
//Loop through the children of the new document and copy them into the rootNode.
rootComment = xmlDocGetRootElement(commentDoc);
@ -509,13 +498,13 @@ private:
{
os << " <motion motion_frequency=\"" << xform.m_MotionFreq << "\" ";
if (xform.m_MotionFunc == MOTION_SIN)
if (xform.m_MotionFunc == eMotion::MOTION_SIN)
os << "motion_function=\"sin\" ";
else if (xform.m_MotionFunc == MOTION_TRIANGLE)
else if (xform.m_MotionFunc == eMotion::MOTION_TRIANGLE)
os << "motion_function=\"triangle\" ";
else if (xform.m_MotionFunc== MOTION_HILL)
else if (xform.m_MotionFunc == eMotion::MOTION_HILL)
os << "motion_function=\"hill\" ";
else if (xform.m_MotionFunc== MOTION_SAW)
else if (xform.m_MotionFunc == eMotion::MOTION_SAW)
os << "motion_function=\"saw\" ";
if (xform.m_MotionOffset != 0)
@ -530,15 +519,17 @@ private:
}
if (!doMotion || xform.m_ColorX != EMPTYFIELD) os << "color=\"" << xform.m_ColorX << "\" ";
//if (!doMotion || xform.m_ColorY != EMPTYFIELD) os << "color=\"" << xform.m_ColorX << " " << xform.m_ColorY << "\" ";
if (!doMotion || xform.m_DirectColor != EMPTYFIELD) os << "var_color=\"" << xform.m_DirectColor << "\" ";
if (!doMotion || xform.m_ColorSpeed != EMPTYFIELD) os << "color_speed=\"" << xform.m_ColorSpeed << "\" ";
//os << "symmetry=\"" << fabs(xform.m_ColorSpeed - 1) * 2 << "\" ";//Legacy support.
if (!doMotion)
{
string s = xform.m_Name;
std::replace(s.begin(), s.end(), ' ', '_');
os << "name=\"" << s << "\" ";//Flam3 didn't do this, but Apo does.
@ -575,13 +566,13 @@ private:
if (!doMotion || (doMotion && !xform.m_Affine.IsZero() && !xform.m_Affine.IsEmpty()))
{
os << "coefs=\"" << xform.m_Affine.A() << " " << xform.m_Affine.D() << " " << xform.m_Affine.B() << " "
<< xform.m_Affine.E() << " " << xform.m_Affine.C() << " " << xform.m_Affine.F() << "\"";
<< xform.m_Affine.E() << " " << xform.m_Affine.C() << " " << xform.m_Affine.F() << "\"";
}
if ((!doMotion && !xform.m_Post.IsID()) || (doMotion && !xform.m_Post.IsZero() && !xform.m_Post.IsEmpty()))
{
os << " post=\"" << xform.m_Post.A() << " " << xform.m_Post.D() << " " << xform.m_Post.B() << " "
<< xform.m_Post.E() << " " << xform.m_Post.C() << " " << xform.m_Post.F() << "\"";
<< xform.m_Post.E() << " " << xform.m_Post.C() << " " << xform.m_Post.F() << "\"";
}
//Original only printed xaos values that were not 1. Here, print them all out if any are present.
@ -655,10 +646,10 @@ private:
tabs++;
}
else if (!Compare(editNode->name, sheepString)) { }
//editOrSheep = 2;
//editOrSheep = 2;
else { }
//editOrSheep = 0;
//editOrSheep = 0;
//Print the attributes.
attPtr = editNode->properties;
@ -696,7 +687,7 @@ private:
{
//If child is an element, indent first and then print it.
if (curChild->type == XML_ELEMENT_NODE &&
(!Compare(curChild->name, editString) || !Compare(curChild->name, sheepString)))
(!Compare(curChild->name, editString) || !Compare(curChild->name, sheepString)))
{
if (indentPrinted)
{
@ -765,19 +756,22 @@ private:
switch (motion.m_MotionFunc)
{
case MOTION_SIN:
os << "\"sin\"";
break;
case MOTION_HILL:
os << "\"hill\"";
break;
case MOTION_TRIANGLE:
os << "\"triangle\"";
break;
default:
case MOTION_SAW:
os << "\"saw\"";
break;
case eMotion::MOTION_SIN:
os << "\"sin\"";
break;
case eMotion::MOTION_HILL:
os << "\"hill\"";
break;
case eMotion::MOTION_TRIANGLE:
os << "\"triangle\"";
break;
case eMotion::MOTION_SAW:
default:
os << "\"saw\"";
break;
}
T r = 0.0;
@ -788,62 +782,79 @@ private:
for (size_t i = 0; i < motion.m_MotionParams.size(); ++i)
{
switch(motion.m_MotionParams[i].first)
switch (motion.m_MotionParams[i].first)
{
case FLAME_MOTION_ZOOM:
os << " zoom=\"" << motion.m_MotionParams[i].second << "\"";
break;
case FLAME_MOTION_ZPOS:
os << " cam_zpos=\"" << motion.m_MotionParams[i].second << "\"";
break;
case FLAME_MOTION_PERSPECTIVE:
os << " cam_persp=\"" << motion.m_MotionParams[i].second << "\"";
break;
case FLAME_MOTION_YAW:
os << " cam_yaw=\"" << motion.m_MotionParams[i].second << "\"";
break;
case FLAME_MOTION_PITCH:
os << " cam_pitch=\"" << motion.m_MotionParams[i].second << "\"";
break;
case FLAME_MOTION_DEPTH_BLUR:
os << " cam_dof=\"" << motion.m_MotionParams[i].second << "\"";
break;
case FLAME_MOTION_CENTER_X:
cx = motion.m_MotionParams[i].second;
break;
case FLAME_MOTION_CENTER_Y:
cy = motion.m_MotionParams[i].second;
break;
case FLAME_MOTION_ROTATE:
os << " rotate=\"" << motion.m_MotionParams[i].second << "\"";
break;
case FLAME_MOTION_BRIGHTNESS:
os << " brightness=\"" << motion.m_MotionParams[i].second << "\"";
break;
case FLAME_MOTION_GAMMA:
os << " gamma=\"" << motion.m_MotionParams[i].second << "\"";
break;
case FLAME_MOTION_GAMMA_THRESH:
os << " gamma_threshold=\"" << motion.m_MotionParams[i].second << "\"";
break;
case FLAME_MOTION_HIGHLIGHT_POWER:
os << " highlight_power=\"" << motion.m_MotionParams[i].second << "\"";
break;
case FLAME_MOTION_BACKGROUND_R:
r = motion.m_MotionParams[i].second;
break;
case FLAME_MOTION_BACKGROUND_G:
g = motion.m_MotionParams[i].second;
break;
case FLAME_MOTION_BACKGROUND_B:
b = motion.m_MotionParams[i].second;
break;
case FLAME_MOTION_VIBRANCY:
os << " vibrancy=\"" << motion.m_MotionParams[i].second << "\"";
break;
case FLAME_MOTION_NONE:
default:
break;
case eEmberMotionParam::FLAME_MOTION_ZOOM:
os << " zoom=\"" << motion.m_MotionParams[i].second << "\"";
break;
case eEmberMotionParam::FLAME_MOTION_ZPOS:
os << " cam_zpos=\"" << motion.m_MotionParams[i].second << "\"";
break;
case eEmberMotionParam::FLAME_MOTION_PERSPECTIVE:
os << " cam_persp=\"" << motion.m_MotionParams[i].second << "\"";
break;
case eEmberMotionParam::FLAME_MOTION_YAW:
os << " cam_yaw=\"" << motion.m_MotionParams[i].second << "\"";
break;
case eEmberMotionParam::FLAME_MOTION_PITCH:
os << " cam_pitch=\"" << motion.m_MotionParams[i].second << "\"";
break;
case eEmberMotionParam::FLAME_MOTION_DEPTH_BLUR:
os << " cam_dof=\"" << motion.m_MotionParams[i].second << "\"";
break;
case eEmberMotionParam::FLAME_MOTION_CENTER_X:
cx = motion.m_MotionParams[i].second;
break;
case eEmberMotionParam::FLAME_MOTION_CENTER_Y:
cy = motion.m_MotionParams[i].second;
break;
case eEmberMotionParam::FLAME_MOTION_ROTATE:
os << " rotate=\"" << motion.m_MotionParams[i].second << "\"";
break;
case eEmberMotionParam::FLAME_MOTION_BRIGHTNESS:
os << " brightness=\"" << motion.m_MotionParams[i].second << "\"";
break;
case eEmberMotionParam::FLAME_MOTION_GAMMA:
os << " gamma=\"" << motion.m_MotionParams[i].second << "\"";
break;
case eEmberMotionParam::FLAME_MOTION_GAMMA_THRESH:
os << " gamma_threshold=\"" << motion.m_MotionParams[i].second << "\"";
break;
case eEmberMotionParam::FLAME_MOTION_HIGHLIGHT_POWER:
os << " highlight_power=\"" << motion.m_MotionParams[i].second << "\"";
break;
case eEmberMotionParam::FLAME_MOTION_BACKGROUND_R:
r = motion.m_MotionParams[i].second;
break;
case eEmberMotionParam::FLAME_MOTION_BACKGROUND_G:
g = motion.m_MotionParams[i].second;
break;
case eEmberMotionParam::FLAME_MOTION_BACKGROUND_B:
b = motion.m_MotionParams[i].second;
break;
case eEmberMotionParam::FLAME_MOTION_VIBRANCY:
os << " vibrancy=\"" << motion.m_MotionParams[i].second << "\"";
break;
case eEmberMotionParam::FLAME_MOTION_NONE:
default:
break;
}
}
@ -854,7 +865,6 @@ private:
os << " center=\"" << cx << " " << cy << "\"";
os << "/>\n";
return os.str();
}
@ -863,7 +873,6 @@ private:
if (filename.find_first_of('&') != std::string::npos)
{
string filenameWithoutAmpersands = filename;
FindAndReplace<string>(filenameWithoutAmpersands, "&", "&amp;");
xmlNewProp(node, XC("filename"), XC(filenameWithoutAmpersands.c_str()));
}

View File

@ -105,13 +105,12 @@ public:
if (xf >= sourceEmbers[i].TotalXformCount() && !aligned)
{
size_t found = 0;
//Remove linear.
destXform->DeleteVariationById(VAR_LINEAR);
//Only do the next substitution for log interpolation.
if ((i == 0 && destEmbers[i].m_AffineInterp == AFFINE_INTERP_LOG) ||
(i > 0 && destEmbers[i - 1].m_AffineInterp == AFFINE_INTERP_LOG))
if ((i == 0 && destEmbers[i].m_AffineInterp == eAffineInterp::AFFINE_INTERP_LOG) ||
(i > 0 && destEmbers[i - 1].m_AffineInterp == eAffineInterp::AFFINE_INTERP_LOG))
{
for (ii = -1; ii <= 1; ii += 2)
{
@ -130,15 +129,14 @@ public:
//with weight -1.
//Added JULIAN/JULIASCOPE to get rid of black wedges.
if (destOtherXform->GetVariationById(VAR_SPHERICAL) ||
destOtherXform->GetVariationById(VAR_NGON) ||
destOtherXform->GetVariationById(VAR_JULIAN) ||
destOtherXform->GetVariationById(VAR_JULIASCOPE) ||
destOtherXform->GetVariationById(VAR_POLAR) ||
destOtherXform->GetVariationById(VAR_WEDGE_SPH) ||
destOtherXform->GetVariationById(VAR_WEDGE_JULIA))
destOtherXform->GetVariationById(VAR_NGON) ||
destOtherXform->GetVariationById(VAR_JULIAN) ||
destOtherXform->GetVariationById(VAR_JULIASCOPE) ||
destOtherXform->GetVariationById(VAR_POLAR) ||
destOtherXform->GetVariationById(VAR_WEDGE_SPH) ||
destOtherXform->GetVariationById(VAR_WEDGE_JULIA))
{
destXform->AddVariation(new LinearVariation<T>(-1));
//Set the coefs appropriately.
destXform->m_Affine.A(-1);
destXform->m_Affine.D(0);
@ -168,7 +166,6 @@ public:
if (destOtherXform->GetVariationById(VAR_RECTANGLES))
{
RectanglesVariation<T>* var = new RectanglesVariation<T>();
var->SetParamVal("rectangles_x", 0);
var->SetParamVal("rectangles_y", 0);
destXform->AddVariation(var);
@ -178,7 +175,6 @@ public:
if (destOtherXform->GetVariationById(VAR_RINGS2))
{
Rings2Variation<T>* var = new Rings2Variation<T>();
var->SetParamVal("rings2_val", 0);
destXform->AddVariation(var);
found++;
@ -187,7 +183,6 @@ public:
if (destOtherXform->GetVariationById(VAR_FAN2))
{
Fan2Variation<T>* var = new Fan2Variation<T>();
destXform->AddVariation(var);
found++;
}
@ -195,7 +190,6 @@ public:
if (destOtherXform->GetVariationById(VAR_BLOB))
{
BlobVariation<T>* var = new BlobVariation<T>();
var->SetParamVal("blob_low", 1);
destXform->AddVariation(var);
found++;
@ -204,7 +198,6 @@ public:
if (destOtherXform->GetVariationById(VAR_PERSPECTIVE))
{
PerspectiveVariation<T>* var = new PerspectiveVariation<T>();
destXform->AddVariation(var);
found++;
}
@ -212,7 +205,6 @@ public:
if (destOtherXform->GetVariationById(VAR_CURL))
{
CurlVariation<T>* var = new CurlVariation<T>();
var->SetParamVal("curl_c1", 0);
destXform->AddVariation(var);
found++;
@ -221,7 +213,6 @@ public:
if (destOtherXform->GetVariationById(VAR_SUPER_SHAPE))
{
SuperShapeVariation<T>* var = new SuperShapeVariation<T>();
var->SetParamVal("super_shape_n1", 2);
var->SetParamVal("super_shape_n2", 2);
var->SetParamVal("super_shape_n3", 2);
@ -422,7 +413,7 @@ public:
//To interpolate the xforms, make copies of the source embers
//and ensure that they both have the same number of xforms before progressing.
if (embers[i1].m_Interp == EMBER_INTERP_LINEAR)
if (embers[i1].m_Interp == eInterp::EMBER_INTERP_LINEAR)
{
Align(&embers[i1], &localEmbers[0], 2);
smoothFlag = false;
@ -450,9 +441,9 @@ public:
}
result.m_Time = time;
result.m_Interp = EMBER_INTERP_LINEAR;
result.m_Interp = eInterp::EMBER_INTERP_LINEAR;
result.m_AffineInterp = embers[0].m_AffineInterp;
result.m_PaletteInterp = INTERP_HSV;
result.m_PaletteInterp = ePaletteInterp::INTERP_HSV;
if (!smoothFlag)
result.Interpolate(&localEmbers[0], 2, c, stagger);
@ -602,8 +593,8 @@ public:
static void ConvertLinearToPolar(Ember<T>* embers, size_t size, size_t xfi, size_t cflag, vector<v2T>& cxAng, vector<v2T>& cxMag, vector<v2T>& cxTrn)
{
if (size == cxAng.size() &&
size == cxMag.size() &&
size == cxTrn.size())
size == cxMag.size() &&
size == cxTrn.size())
{
T c1[2], d, t, refang;
glm::length_t col, k;
@ -668,16 +659,16 @@ public:
refang = xform->m_Wind[col] - M_2PI;
//Make sure both angles are within [refang refang + 2 * pi].
while(cxAng[k - 1][col] < refang)
while (cxAng[k - 1][col] < refang)
cxAng[k - 1][col] += M_2PI;
while(cxAng[k - 1][col] > refang + M_2PI)
while (cxAng[k - 1][col] > refang + M_2PI)
cxAng[k - 1][col] -= M_2PI;
while(cxAng[k][col] < refang)
while (cxAng[k][col] < refang)
cxAng[k][col] += M_2PI;
while(cxAng[k][col] > refang + M_2PI)
while (cxAng[k][col] > refang + M_2PI)
cxAng[k][col] -= M_2PI;
}
else
@ -721,7 +712,6 @@ public:
{
c1[0] = embers[k].GetXform(xfi)->m_Affine.m_Mat[0][col];//A,D then B,E.
c1[1] = embers[k].GetXform(xfi)->m_Affine.m_Mat[1][col];
cxang[k][col] = atan2(c1[1], c1[0]);
}
}
@ -732,8 +722,7 @@ public:
{
int sym0, sym1;
int padSymFlag;
d = cxang[k][col] - cxang[k-1][col];
d = cxang[k][col] - cxang[k - 1][col];
//Adjust to avoid the -pi/pi discontinuity.
if (d > T(M_PI + EPS))
@ -745,12 +734,11 @@ public:
//Check them pairwise and store the reference angle in the second
//to avoid overwriting if asymmetric on both sides.
padSymFlag = 0;
sym0 = (embers[k - 1].GetXform(xfi)->m_Animate == 0 || (embers[k - 1].GetXform(xfi)->Empty() && padSymFlag));
sym1 = (embers[k ].GetXform(xfi)->m_Animate == 0 || (embers[k ].GetXform(xfi)->Empty() && padSymFlag));
if (sym1 && !sym0)
embers[k].GetXform(xfi)->m_Wind[col] = cxang[k-1][col] + 2 * T(M_PI);
embers[k].GetXform(xfi)->m_Wind[col] = cxang[k - 1][col] + 2 * T(M_PI);
else if (sym0 && !sym1)
embers[k].GetXform(xfi)->m_Wind[col] = cxang[k][col] + 2 * T(M_PI);
}
@ -835,10 +823,8 @@ public:
{
//maxStag is the spacing between xform start times if staggerPercent = 1.0.
T maxStag = T(numXforms - 1) / numXforms;
//Scale the spacing by staggerPercent.
T stagScaled = staggerPercent * maxStag;
//t ranges from 1 to 0 (the contribution of cp[0] to the blend).
//The first line below makes the first xform interpolate first.
//The second line makes the last xform interpolate first.
@ -856,47 +842,61 @@ public:
/// <summary>
/// Apply the specified motion function to a value.
/// </summary>
/// <param name="funcNum">The function type to apply, sin, triangle or hill.</param>
/// <param name="funcNum">The function type to apply, sin, triangle, hill or saw.</param>
/// <param name="timeVal">The time value to apply the motion function to</param>
/// <returns>The new time value computed by applying the specified motion function to the time value</returns>
static T MotionFuncs(int funcNum, T timeVal)
static T MotionFuncs(eMotion funcNum, T timeVal)
{
//Motion funcs should be cyclic, and equal to 0 at integral time values
//abs peak values should be not be greater than 1.
if (funcNum == MOTION_SIN)
switch (funcNum)
{
return std::sin(T(2.0) * T(M_PI) * timeVal);
}
else if (funcNum == MOTION_TRIANGLE)
{
T fr = fmod(timeVal, T(1.0));
case EmberNs::eMotion::MOTION_SIN:
{
return std::sin(T(2.0) * T(M_PI) * timeVal);
}
break;
if (fr < 0)
fr += 1;
case EmberNs::eMotion::MOTION_TRIANGLE:
{
T fr = fmod(timeVal, T(1.0));
if (fr <= T(0.25))
fr *= 4;
else if (fr <= T(0.75))
fr = -4 * fr + 2;
else
fr = 4 * fr - 4;
if (fr < 0)
fr += 1;
return fr;
}
else if (funcNum == MOTION_HILL)
{
return ((1 - std::cos(T(2.0) * T(M_PI) * timeVal)) * T(0.5));
}
else //MOTION_SAW
{
return (T(2.0) * fmod(timeVal - T(0.5), T(1.0)) - T(1.0));
if (fr <= T(0.25))
fr *= 4;
else if (fr <= T(0.75))
fr = -4 * fr + 2;
else
fr = 4 * fr - 4;
return fr;
}
break;
case EmberNs::eMotion::MOTION_HILL:
{
return ((1 - std::cos(T(2.0) * T(M_PI) * timeVal)) * T(0.5));
}
break;
case EmberNs::eMotion::MOTION_SAW:
{
return (T(2.0) * fmod(timeVal - T(0.5), T(1.0)) - T(1.0));
}
break;
default:
return timeVal;
break;
}
}
/*
//Will need to alter this to handle 2D palettes.
static bool InterpMissingColors(vector<glm::detail::tvec4<T>>& palette)
{
//Will need to alter this to handle 2D palettes.
static bool InterpMissingColors(vector<glm::detail::tvec4<T>>& palette)
{
//Check for a non-full palette.
int minIndex, maxIndex;
int colorli, colorri;
@ -989,7 +989,7 @@ public:
}
return true;
}
}
*/
/// <summary>
@ -1002,18 +1002,19 @@ public:
static inline bool CompareXforms(const Xform<T>& a, const Xform<T>& b)
{
if (a.m_ColorSpeed > b.m_ColorSpeed) return true;
if (a.m_ColorSpeed < b.m_ColorSpeed) return false;
//Original did this every time, even though it's only needed if the color speeds are equal.
m2T aMat2 = a.m_Affine.ToMat2ColMajor();
m2T bMat2 = b.m_Affine.ToMat2ColMajor();
T ad = glm::determinant(aMat2);
T bd = glm::determinant(bMat2);
if (a.m_ColorSpeed > 0)
{
if (ad < 0) return false;
if (bd < 0) return true;
ad = atan2(a.m_Affine.A(), a.m_Affine.D());

View File

@ -42,7 +42,7 @@ void Renderer<T, bucketT>::AddEmber(Ember<T>& ember)
if (m_Embers.size() == 1)
m_Ember = m_Embers[0];
}, FULL_RENDER);
}, eProcessAction::FULL_RENDER);
}
/// <summary>
@ -82,7 +82,6 @@ template <typename T, typename bucketT>
void Renderer<T, bucketT>::ComputeBounds()
{
size_t maxDEFilterWidth = 0;
m_GutterWidth = ClampGte((m_SpatialFilter->FinalFilterWidth() - Supersample()) / 2, size_t(0));
//Check the size of the density estimation filter.
@ -99,7 +98,6 @@ void Renderer<T, bucketT>::ComputeBounds()
//add the DE filter width to the spatial filter width.//SMOULDER
m_DensityFilterOffset = maxDEFilterWidth;
m_GutterWidth += m_DensityFilterOffset;
m_SuperRasW = (Supersample() * FinalRasW()) + (2 * m_GutterWidth);
m_SuperRasH = (Supersample() * FinalRasH()) + (2 * m_GutterWidth);
m_SuperSize = m_SuperRasW * m_SuperRasH;
@ -128,22 +126,18 @@ void Renderer<T, bucketT>::ComputeCamera()
m_PixelsPerUnitX = PixelsPerUnit() * m_Scale;
m_PixelsPerUnitY = m_PixelsPerUnitX;
m_PixelsPerUnitX /= PixelAspectRatio();
T shift = 0;
T t0 = T(m_GutterWidth) / (Supersample() * m_PixelsPerUnitX);
T t1 = T(m_GutterWidth) / (Supersample() * m_PixelsPerUnitY);
//These go from ll to ur, moving from negative to positive.
m_LowerLeftX = CenterX() - FinalRasW() / m_PixelsPerUnitX / T(2.0);
m_LowerLeftY = CenterY() - FinalRasH() / m_PixelsPerUnitY / T(2.0);
m_UpperRightX = m_LowerLeftX + FinalRasW() / m_PixelsPerUnitX;
m_UpperRightY = m_LowerLeftY + FinalRasH() / m_PixelsPerUnitY;
T carLlX = m_LowerLeftX - t0;
T carLlY = m_LowerLeftY - t1 + shift;
T carUrX = m_UpperRightX + t0;
T carUrY = m_UpperRightY + t1 + shift;
m_RotMat.MakeID();
m_RotMat.Rotate(-Rotate());
m_CarToRas.Init(carLlX, carLlY, carUrX, carUrY, m_SuperRasW, m_SuperRasH, PixelAspectRatio());
@ -157,7 +151,7 @@ void Renderer<T, bucketT>::ComputeCamera()
/// </summary>
/// <param name="ember">The ember to assign</param>
/// <param name="action">The requested process action. Note that it's critical the user supply the proper value here.
/// For example: Changing dimensions without setting action to FULL_RENDER will crash the program.
/// For example: Changing dimensions without setting action to eProcessAction::FULL_RENDER will crash the program.
/// However, changing only the brightness and setting action to ACCUM_ONLY is perfectly fine.
/// </param>
template <typename T, typename bucketT>
@ -186,7 +180,7 @@ void Renderer<T, bucketT>::SetEmber(vector<Ember<T>>& embers)
if (!m_Embers.empty())
m_Ember = m_Embers[0];
}, FULL_RENDER);
}, eProcessAction::FULL_RENDER);
}
/// <summary>
@ -207,10 +201,10 @@ bool Renderer<T, bucketT>::CreateDEFilter(bool& newAlloc)
{
//Use intelligent testing so it isn't created every time a new ember is passed in.
if ((!m_DensityFilter.get()) ||
(m_Ember.m_MinRadDE != m_DensityFilter->MinRad()) ||
(m_Ember.m_MaxRadDE != m_DensityFilter->MaxRad()) ||
(m_Ember.m_CurveDE != m_DensityFilter->Curve()) ||
(m_Ember.m_Supersample != m_DensityFilter->Supersample()))
(m_Ember.m_MinRadDE != m_DensityFilter->MinRad()) ||
(m_Ember.m_MaxRadDE != m_DensityFilter->MaxRad()) ||
(m_Ember.m_CurveDE != m_DensityFilter->Curve()) ||
(m_Ember.m_Supersample != m_DensityFilter->Supersample()))
{
m_DensityFilter = unique_ptr<DensityFilter<bucketT>>(new DensityFilter<bucketT>(bucketT(m_Ember.m_MinRadDE), bucketT(m_Ember.m_MaxRadDE), bucketT(m_Ember.m_CurveDE), m_Ember.m_Supersample));
newAlloc = true;
@ -219,11 +213,12 @@ bool Renderer<T, bucketT>::CreateDEFilter(bool& newAlloc)
if (newAlloc)
{
if (!m_DensityFilter.get()) { return false; }//Did object creation succeed?
if (!m_DensityFilter->Create()) { return false; }//Object creation succeeded, did filter creation succeed?
//cout << m_DensityFilter->ToString() << endl;
}
else
if (!m_DensityFilter->Valid()) { return false; }//Previously created, are values ok?
else if (!m_DensityFilter->Valid()) { return false; } //Previously created, are values ok?
}
else
{
@ -246,14 +241,13 @@ bool Renderer<T, bucketT>::CreateSpatialFilter(bool& newAlloc)
//Use intelligent testing so it isn't created every time a new ember is passed in.
if ((!m_SpatialFilter.get()) ||
(m_Ember.m_SpatialFilterType != m_SpatialFilter->FilterType()) ||
(m_Ember.m_SpatialFilterRadius != m_SpatialFilter->FilterRadius()) ||
(m_Ember.m_Supersample != m_SpatialFilter->Supersample()) ||
(m_PixelAspectRatio != m_SpatialFilter->PixelAspectRatio()))
(m_Ember.m_SpatialFilterType != m_SpatialFilter->FilterType()) ||
(m_Ember.m_SpatialFilterRadius != m_SpatialFilter->FilterRadius()) ||
(m_Ember.m_Supersample != m_SpatialFilter->Supersample()) ||
(m_PixelAspectRatio != m_SpatialFilter->PixelAspectRatio()))
{
m_SpatialFilter = unique_ptr<SpatialFilter<bucketT>>(
SpatialFilterCreator<bucketT>::Create(m_Ember.m_SpatialFilterType, bucketT(m_Ember.m_SpatialFilterRadius), m_Ember.m_Supersample, bucketT(m_PixelAspectRatio)));
SpatialFilterCreator<bucketT>::Create(m_Ember.m_SpatialFilterType, bucketT(m_Ember.m_SpatialFilterRadius), m_Ember.m_Supersample, bucketT(m_PixelAspectRatio)));
m_Ember.m_SpatialFilterRadius = m_SpatialFilter->FilterRadius();//It may have been changed internally if it was too small, so ensure they're synced.
newAlloc = true;
}
@ -274,13 +268,13 @@ bool Renderer<T, bucketT>::CreateTemporalFilter(bool& newAlloc)
//Use intelligent testing so it isn't created every time a new ember is passed in.
if ((!m_TemporalFilter.get()) ||
(m_Ember.m_TemporalSamples != m_TemporalFilter->TemporalSamples()) ||
(m_Ember.m_TemporalFilterType != m_TemporalFilter->FilterType()) ||
(m_Ember.m_TemporalFilterWidth != m_TemporalFilter->FilterWidth()) ||
(m_Ember.m_TemporalFilterExp != m_TemporalFilter->FilterExp()))
(m_Ember.m_TemporalSamples != m_TemporalFilter->TemporalSamples()) ||
(m_Ember.m_TemporalFilterType != m_TemporalFilter->FilterType()) ||
(m_Ember.m_TemporalFilterWidth != m_TemporalFilter->FilterWidth()) ||
(m_Ember.m_TemporalFilterExp != m_TemporalFilter->FilterExp()))
{
m_TemporalFilter = unique_ptr<TemporalFilter<T>>(
TemporalFilterCreator<T>::Create(m_Ember.m_TemporalFilterType, m_Ember.m_TemporalSamples, m_Ember.m_TemporalFilterWidth, m_Ember.m_TemporalFilterExp));
TemporalFilterCreator<T>::Create(m_Ember.m_TemporalFilterType, m_Ember.m_TemporalSamples, m_Ember.m_TemporalFilterWidth, m_Ember.m_TemporalFilterExp));
newAlloc = true;
}
@ -332,13 +326,13 @@ eRenderStatus Renderer<T, bucketT>::Run(vector<byte>& finalImage, double time, s
m_InRender = true;
EnterRender();
m_Abort = false;
bool filterAndAccumOnly = m_ProcessAction == FILTER_AND_ACCUM;
bool accumOnly = m_ProcessAction == ACCUM_ONLY;
bool resume = m_ProcessState != NONE;
bool filterAndAccumOnly = m_ProcessAction == eProcessAction::FILTER_AND_ACCUM;
bool accumOnly = m_ProcessAction == eProcessAction::ACCUM_ONLY;
bool resume = m_ProcessState != eProcessState::NONE;
bool newFilterAlloc;
size_t i, temporalSample = 0;
T deTime;
eRenderStatus success = RENDER_OK;
auto success = eRenderStatus::RENDER_OK;
//double iterationTime = 0;
//double accumulationTime = 0;
//Timing it;
@ -347,7 +341,7 @@ eRenderStatus Renderer<T, bucketT>::Run(vector<byte>& finalImage, double time, s
if (!resume || accumOnly || filterAndAccumOnly)
{
if (!resume)//Only set this if it's the first run through.
m_ProcessState = ITER_STARTED;
m_ProcessState = eProcessState::ITER_STARTED;
m_RenderTimer.Tic();
m_ProgressTimer.Tic();
@ -366,7 +360,7 @@ eRenderStatus Renderer<T, bucketT>::Run(vector<byte>& finalImage, double time, s
m_Background.Clear();
}
//User requested an increase in quality after finishing.
else if (m_ProcessState == ITER_STARTED && m_ProcessAction == KEEP_ITERATING && TemporalSamples() == 1)
else if (m_ProcessState == eProcessState::ITER_STARTED && m_ProcessAction == eProcessAction::KEEP_ITERATING && TemporalSamples() == 1)
{
m_LastTemporalSample = 0;
m_LastIter = m_Stats.m_Iters;
@ -401,6 +395,7 @@ eRenderStatus Renderer<T, bucketT>::Run(vector<byte>& finalImage, double time, s
//Interpolate.
if (m_Embers.size() > 1)
Interpolater<T>::Interpolate(m_Embers, T(time), 0, m_Ember);
//it.Toc("Interp 1");
//Save only for palette insertion.
@ -415,14 +410,14 @@ eRenderStatus Renderer<T, bucketT>::Run(vector<byte>& finalImage, double time, s
if (m_SpatialFilter.get() == nullptr || m_TemporalFilter.get() == nullptr)
{
AddToReport("Spatial and temporal filter allocations failed, aborting.\n");
success = RENDER_ERROR;
success = eRenderStatus::RENDER_ERROR;
goto Finish;
}
if (!resume && !Alloc())
{
AddToReport("Histogram, accumulator and samples buffer allocations failed, aborting.\n");
success = RENDER_ERROR;
success = eRenderStatus::RENDER_ERROR;
goto Finish;
}
@ -436,8 +431,8 @@ eRenderStatus Renderer<T, bucketT>::Run(vector<byte>& finalImage, double time, s
//it.Tic();
if (m_Embers.size() > 1)
Interpolater<T>::Interpolate(m_Embers, deTime, 0, m_Ember);
//it.Toc("Interp 2");
//it.Toc("Interp 2");
ClampGteRef<T>(m_Ember.m_MinRadDE, 0);
ClampGteRef<T>(m_Ember.m_MaxRadDE, 0);
ClampGteRef<T>(m_Ember.m_MaxRadDE, m_Ember.m_MinRadDE);
@ -445,12 +440,13 @@ eRenderStatus Renderer<T, bucketT>::Run(vector<byte>& finalImage, double time, s
if (!CreateDEFilter(newFilterAlloc))
{
AddToReport("Density filter creation failed, aborting.\n");
success = RENDER_ERROR;
success = eRenderStatus::RENDER_ERROR;
goto Finish;
}
//Temporal samples, loop 1.
temporalSample = resume ? m_LastTemporalSample : 0;
for (; (temporalSample < TemporalSamples()) && !m_Abort;)
{
T colorScalar = m_TemporalFilter->Filter()[temporalSample];
@ -466,7 +462,7 @@ eRenderStatus Renderer<T, bucketT>::Run(vector<byte>& finalImage, double time, s
if (!resume && !AssignIterator())
{
AddToReport("Iterator assignment failed, aborting.\n");
success = RENDER_ERROR;
success = eRenderStatus::RENDER_ERROR;
goto Finish;
}
@ -496,14 +492,14 @@ eRenderStatus Renderer<T, bucketT>::Run(vector<byte>& finalImage, double time, s
if (stats.m_Iters == 0)
{
AddToReport("Zero iterations ran, rendering failed, aborting.\n");
success = RENDER_ERROR;
success = eRenderStatus::RENDER_ERROR;
Abort();
goto Finish;
}
if (m_Abort)
{
success = RENDER_ABORT;
success = eRenderStatus::RENDER_ABORT;
goto Finish;
}
@ -536,23 +532,23 @@ eRenderStatus Renderer<T, bucketT>::Run(vector<byte>& finalImage, double time, s
//If we've completed all temporal samples, then it was a complete render, so report progress.
if (temporalSample >= TemporalSamples())
{
m_ProcessState = ITER_DONE;
m_ProcessState = eProcessState::ITER_DONE;
if (m_Callback && !m_Callback->ProgressFunc(m_Ember, m_ProgressParameter, 100.0, 0, 0))
{
Abort();
success = RENDER_ABORT;
success = eRenderStatus::RENDER_ABORT;
goto Finish;
}
}
FilterAndAccum:
if (filterAndAccumOnly || temporalSample >= TemporalSamples() || forceOutput)
{
//t.Toc("Iterating and accumulating");
//Compute k1 and k2.
eRenderStatus fullRun = RENDER_OK;//Whether density filtering was run to completion without aborting prematurely or triggering an error.
auto fullRun = eRenderStatus::RENDER_OK;//Whether density filtering was run to completion without aborting prematurely or triggering an error.
T area = FinalRasW() * FinalRasH() / (m_PixelsPerUnitX * m_PixelsPerUnitY);//Need to use temps from field if ever implemented.
m_K1 = bucketT((Brightness() * 268) / 256);
@ -578,18 +574,18 @@ FilterAndAccum:
else
{
//Apply requested filter for a forced output during interactive rendering.
if (m_DensityFilter.get() && m_InteractiveFilter == FILTER_DE)
if (m_DensityFilter.get() && m_InteractiveFilter == eInteractiveFilter::FILTER_DE)
fullRun = GaussianDensityFilter();
else if (!m_DensityFilter.get() || m_InteractiveFilter == FILTER_LOG)
else if (!m_DensityFilter.get() || m_InteractiveFilter == eInteractiveFilter::FILTER_LOG)
fullRun = LogScaleDensityFilter(forceOutput);
}
//Only update state if iterating and filtering finished completely (didn't arrive here via forceOutput).
if (fullRun == RENDER_OK && m_ProcessState == ITER_DONE)
m_ProcessState = FILTER_DONE;
if (fullRun == eRenderStatus::RENDER_OK && m_ProcessState == eProcessState::ITER_DONE)
m_ProcessState = eProcessState::FILTER_DONE;
//Take special action if filtering exited prematurely.
if (fullRun != RENDER_OK)
if (fullRun != eRenderStatus::RENDER_OK)
{
ResetBuckets(false, true);//Reset the accumulator, come back and try again on the next call.
success = fullRun;
@ -598,27 +594,28 @@ FilterAndAccum:
if (m_Abort)
{
success = RENDER_ABORT;
success = eRenderStatus::RENDER_ABORT;
goto Finish;
}
//t.Toc("Density estimation filtering time: ", true);
}
AccumOnly:
if (m_ProcessState == FILTER_DONE || forceOutput)
if (m_ProcessState == eProcessState::FILTER_DONE || forceOutput)
{
//Original only allowed stages 0 and 1. Add 2 to mean final accum.
//Do not update state/progress on forced output because it will be immediately overwritten.
if (m_Callback && !forceOutput && !m_Callback->ProgressFunc(m_Ember, m_ProgressParameter, 0, 2, 0))
{
Abort();
success = RENDER_ABORT;
success = eRenderStatus::RENDER_ABORT;
goto Finish;
}
//Make sure a filter has been created.
CreateSpatialFilter(newFilterAlloc);
m_CurvesSet = m_Ember.m_Curves.CurvesSet();
//Color curves must be re-calculated as well.
@ -626,35 +623,36 @@ AccumOnly:
for (i = 0; i < COLORMAP_LENGTH; i++)
m_Csa[i] = m_Ember.m_Curves.BezierFunc(i / T(COLORMAP_LENGTH_MINUS_1)) * T(COLORMAP_LENGTH_MINUS_1);
if (AccumulatorToFinalImage(finalImage, finalOffset) == RENDER_OK)
if (AccumulatorToFinalImage(finalImage, finalOffset) == eRenderStatus::RENDER_OK)
{
m_Stats.m_RenderMs = m_RenderTimer.Toc();//Record total time from the very beginning to the very end, including all intermediate calls.
//Even though the ember changes throughought the inner loops because of interpolation, it's probably ok to assign here.
//This will hold the last interpolated value (even though spatial and temporal filters were created based off of one of the first interpolated values).
m_LastEmber = m_Ember;
if (m_ProcessState == FILTER_DONE)//Only update state if gotten here legitimately, and not via forceOutput.
if (m_ProcessState == eProcessState::FILTER_DONE)//Only update state if gotten here legitimately, and not via forceOutput.
{
m_ProcessState = ACCUM_DONE;
m_ProcessState = eProcessState::ACCUM_DONE;
if (m_Callback && !m_Callback->ProgressFunc(m_Ember, m_ProgressParameter, 100.0, 2, 0))//Finished.
{
Abort();
success = RENDER_ABORT;
success = eRenderStatus::RENDER_ABORT;
goto Finish;
}
}
}
else
{
success = RENDER_ERROR;
success = eRenderStatus::RENDER_ERROR;
}
}
Finish:
if (success == RENDER_OK && m_Abort)//If everything ran ok, but they've aborted, record abort as the status.
success = RENDER_ABORT;
else if (success != RENDER_OK)//Regardless of abort status, if there was an error, leave that as the return status.
if (success == eRenderStatus::RENDER_OK && m_Abort)//If everything ran ok, but they've aborted, record abort as the status.
success = eRenderStatus::RENDER_ABORT;
else if (success != eRenderStatus::RENDER_OK)//Regardless of abort status, if there was an error, leave that as the return status.
Abort();
LeaveRender();
@ -675,7 +673,6 @@ EmberImageComments Renderer<T, bucketT>::ImageComments(const EmberStats& stats,
{
ostringstream ss;
EmberImageComments comments;
ss.imbue(std::locale(""));
comments.m_Genome = m_EmberToXml.ToString(m_Ember, "", printEditDepth, false, intPalette, hexPalette);
ss << (double(stats.m_Badvals) / double(stats.m_Iters));//Percentage of bad values to iters.
@ -684,7 +681,6 @@ EmberImageComments Renderer<T, bucketT>::ImageComments(const EmberStats& stats,
comments.m_NumIters = ss.str(); ss.str("");//Total iters.
ss << (stats.m_RenderMs / 1000.0);
comments.m_Runtime = ss.str();//Number of seconds for iterating, accumulating and filtering.
return comments;
}
@ -791,13 +787,14 @@ bool Renderer<T, bucketT>::ResetBuckets(bool resetHist, bool resetAccum)
//{
if (resetHist && !m_HistBuckets.empty())
Memset(m_HistBuckets);
//},
//[&]
//{
if (resetAccum && !m_AccumulatorBuckets.empty())
Memset(m_AccumulatorBuckets);
//});
//});
return resetHist || resetAccum;
}
@ -820,7 +817,6 @@ void Renderer<T, bucketT>::VectorizedLogScale(size_t row, size_t rowEnd)
for (size_t i = row; i < rowEnd; i++)
{
float logScale = (k1 * std::log(1.0f + hist[i].a * k2)) / (hist[i].a + std::numeric_limits<float>::epsilon());
acc[i].r = hist[i].r * logScale;//Must break these out individually. Vectorizer can't reason about vec4's overloaded * operator.
acc[i].g = hist[i].g * logScale;
acc[i].b = hist[i].b * logScale;
@ -842,7 +838,6 @@ eRenderStatus Renderer<T, bucketT>::LogScaleDensityFilter(bool forceOutput)
size_t endRow = m_SuperRasH;
size_t endCol = m_SuperRasW;
//Timing t(4);
//if (forceOutput)//Assume interactive render, so speed up at the expense of slight quality.
//{
// parallel_for(startRow, endRow, [&](size_t j)
@ -851,7 +846,6 @@ eRenderStatus Renderer<T, bucketT>::LogScaleDensityFilter(bool forceOutput)
// {
// size_t row = j * m_SuperRasW;
// size_t rowEnd = row + endCol;
// VectorizedLogScale(row, rowEnd);
// }
// });
@ -873,7 +867,6 @@ eRenderStatus Renderer<T, bucketT>::LogScaleDensityFilter(bool forceOutput)
if (m_HistBuckets[i].a != 0)
{
bucketT logScale = (m_K1 * std::log(1 + m_HistBuckets[i].a * m_K2)) / m_HistBuckets[i].a;
//Original did a temporary assignment, then *= logScale, then passed the result to bump_no_overflow().
//Combine here into one operation for a slight speedup.
m_AccumulatorBuckets[i] = m_HistBuckets[i] * logScale;
@ -882,10 +875,8 @@ eRenderStatus Renderer<T, bucketT>::LogScaleDensityFilter(bool forceOutput)
}
});
}
//t.Toc(__FUNCTION__);
return m_Abort ? RENDER_ABORT : RENDER_OK;
return m_Abort ? eRenderStatus::RENDER_ABORT : eRenderStatus::RENDER_OK;
}
/// <summary>
@ -902,14 +893,12 @@ eRenderStatus Renderer<T, bucketT>::GaussianDensityFilter()
bool scf = !(Supersample() & 1);
intmax_t ss = Floor<T>(Supersample() / T(2));
T scfact = std::pow(Supersample() / (Supersample() + T(1)), T(2));
size_t threads = m_ThreadsToUse;
size_t startRow = Supersample() - 1;
size_t endRow = m_SuperRasH - (Supersample() - 1);//Original did + which is most likely wrong.
intmax_t startCol = Supersample() - 1;
intmax_t endCol = m_SuperRasW - (Supersample() - 1);
size_t chunkSize = size_t(ceil(double(endRow - startRow) / double(threads)));
//parallel_for scales very well, dividing the work almost perfectly among all processors.
parallel_for(size_t(0), threads, [&] (size_t threadIndex)
{
@ -990,7 +979,6 @@ eRenderStatus Renderer<T, bucketT>::GaussianDensityFilter()
continue;
bucketT logScale = filterCoefs[filterCoefIndex] * cacheLog;
//Original first assigned the fields, then scaled them. Combine into a single step for a 1% optimization.
logScaleBucket = (*bucket * logScale);
@ -1053,7 +1041,7 @@ eRenderStatus Renderer<T, bucketT>::GaussianDensityFilter()
m_Callback->ProgressFunc(m_Ember, m_ProgressParameter, 100.0, 1, 0);
//totalTime.Toc(__FUNCTION__);
return m_Abort ? RENDER_ABORT : RENDER_OK;
return m_Abort ? eRenderStatus::RENDER_ABORT : eRenderStatus::RENDER_OK;
}
/// <summary>
@ -1068,7 +1056,7 @@ eRenderStatus Renderer<T, bucketT>::AccumulatorToFinalImage(vector<byte>& pixels
if (PrepFinalAccumVector(pixels))
return AccumulatorToFinalImage(pixels.data(), finalOffset);
return RENDER_ERROR;
return eRenderStatus::RENDER_ERROR;
}
/// <summary>
@ -1082,14 +1070,13 @@ template <typename T, typename bucketT>
eRenderStatus Renderer<T, bucketT>::AccumulatorToFinalImage(byte* pixels, size_t finalOffset)
{
if (!pixels)
return RENDER_ERROR;
return eRenderStatus::RENDER_ERROR;
EnterFinalAccum();
//Timing t(4);
size_t filterWidth = m_SpatialFilter->FinalFilterWidth();
bucketT g, linRange, vibrancy;
Color<bucketT> background;
pixels += finalOffset;
PrepFinalAccumVals(background, g, linRange, vibrancy);
@ -1111,7 +1098,7 @@ eRenderStatus Renderer<T, bucketT>::AccumulatorToFinalImage(byte* pixels, size_t
if (m_Abort)
{
LeaveFinalAccum();
return RENDER_ABORT;
return eRenderStatus::RENDER_ABORT;
}
//Note that abort is not checked here. The final accumulation must run to completion
@ -1142,7 +1129,6 @@ eRenderStatus Renderer<T, bucketT>::AccumulatorToFinalImage(byte* pixels, size_t
{
//Need to dereference the spatial filter pointer object to use the [] operator. Makes no speed difference.
bucketT k = ((*m_SpatialFilter)[ii + filterKRowIndex]);
newBucket += (m_AccumulatorBuckets[(x + ii) + accumRowIndex] * k);
}
}
@ -1221,17 +1207,16 @@ eRenderStatus Renderer<T, bucketT>::AccumulatorToFinalImage(byte* pixels, size_t
for (i = 0; i < FinalRasW(); i++)
{
byte* p = pixels + (NumChannels() * (i + j * FinalRasW()));
p[0] = byte(m_TempEmber.m_Palette[i * 256 / FinalRasW()][0] * WHITE);//The palette is [0..1], output image is [0..255].
p[1] = byte(m_TempEmber.m_Palette[i * 256 / FinalRasW()][1] * WHITE);
p[2] = byte(m_TempEmber.m_Palette[i * 256 / FinalRasW()][2] * WHITE);
}
}
}
//t.Toc(__FUNCTION__);
//t.Toc(__FUNCTION__);
LeaveFinalAccum();
return m_Abort ? RENDER_ABORT : RENDER_OK;
return m_Abort ? eRenderStatus::RENDER_ABORT : eRenderStatus::RENDER_OK;
}
//#define TG 1
@ -1263,99 +1248,98 @@ EmberStats Renderer<T, bucketT>::Iterate(size_t iterCount, size_t temporalSample
m_ThreadEmbers.clear();
m_ThreadEmbers.insert(m_ThreadEmbers.begin(), m_ThreadsToUse, m_Ember);
}
#ifdef TG
size_t threadIndex;
for (size_t i = 0; i < m_ThreadsToUse; i++)
{
threadIndex = i;
m_TaskGroup.run([&, threadIndex] () {
m_TaskGroup.run([&, threadIndex] ()
{
#else
parallel_for(size_t(0), m_ThreadsToUse, [&] (size_t threadIndex)
{
#endif
#if defined(WIN32)
SetThreadPriority(GetCurrentThread(), m_Priority);
SetThreadPriority(GetCurrentThread(), m_Priority);
#elif defined(__APPLE__)
sched_param sp = {0};
sp.sched_priority = m_Priority;
pthread_setschedparam(pthread_self(), SCHED_RR, &sp);
sched_param sp = {0};
sp.sched_priority = m_Priority;
pthread_setschedparam(pthread_self(), SCHED_RR, &sp);
#else
pthread_setschedprio(pthread_self(), int(m_Priority));
pthread_setschedprio(pthread_self(), int(m_Priority));
#endif
//Timing t;
IterParams<T> params;
//Timing t;
IterParams<T> params;
m_BadVals[threadIndex] = 0;
params.m_Count = std::min(totalItersPerThread, SubBatchSize());
params.m_Skip = FuseCount();
//params.m_OneColDiv2 = m_CarToRas.OneCol() / 2;
//params.m_OneRowDiv2 = m_CarToRas.OneRow() / 2;
m_BadVals[threadIndex] = 0;
params.m_Count = std::min(totalItersPerThread, SubBatchSize());
params.m_Skip = FuseCount();
//params.m_OneColDiv2 = m_CarToRas.OneCol() / 2;
//params.m_OneRowDiv2 = m_CarToRas.OneRow() / 2;
//Sub batch iterations, loop 2.
for (m_SubBatch[threadIndex] = 0; (m_SubBatch[threadIndex] < totalItersPerThread) && !m_Abort; m_SubBatch[threadIndex] += params.m_Count)
{
//Must recalculate the number of iters to run on each sub batch because the last batch will most likely have less than SubBatchSize iters.
//For example, if 51,000 are requested, and the sbs is 10,000, it should run 5 sub batches of 10,000 iters, and one final sub batch of 1,000 iters.
params.m_Count = std::min(params.m_Count, totalItersPerThread - m_SubBatch[threadIndex]);
//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 = m_Rand[threadIndex].template Frand11<T>();
m_Samples[threadIndex][0].m_Y = m_Rand[threadIndex].template Frand11<T>();
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 = m_Rand[threadIndex].template Frand01<T>();
//Finally, iterate.
//t.Tic();
//Iterating, loop 3.
m_BadVals[threadIndex] += m_Iterator->Iterate(m_ThreadEmbers[threadIndex], params, m_Samples[threadIndex].data(), m_Rand[threadIndex]);
//m_BadVals[threadIndex] += m_Iterator->Iterate(m_Ember, params, m_Samples[threadIndex].data(), m_Rand[threadIndex]);
//iterationTime += t.Toc();
if (m_LockAccum)
m_AccumCs.Enter();
//t.Tic();
//Map temp buffer samples into the histogram using the palette for color.
Accumulate(m_Rand[threadIndex], m_Samples[threadIndex].data(), params.m_Count, &m_Dmap);
//accumulationTime += t.Toc();
if (m_LockAccum)
m_AccumCs.Leave();
if (m_Callback && threadIndex == 0)
//Sub batch iterations, loop 2.
for (m_SubBatch[threadIndex] = 0; (m_SubBatch[threadIndex] < totalItersPerThread) && !m_Abort; m_SubBatch[threadIndex] += params.m_Count)
{
percent = 100.0 *
double
(
double
(
double
(
//Takes progress of current thread and multiplies by thread count.
//This assumes the threads progress at roughly the same speed.
double(m_LastIter + (m_SubBatch[threadIndex] * m_ThreadsToUse)) / double(ItersPerTemporalSample())
) + temporalSample
) / double(TemporalSamples())
);
//Must recalculate the number of iters to run on each sub batch because the last batch will most likely have less than SubBatchSize iters.
//For example, if 51,000 are requested, and the sbs is 10,000, it should run 5 sub batches of 10,000 iters, and one final sub batch of 1,000 iters.
params.m_Count = std::min(params.m_Count, totalItersPerThread - m_SubBatch[threadIndex]);
//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 = m_Rand[threadIndex].template Frand11<T>();
m_Samples[threadIndex][0].m_Y = m_Rand[threadIndex].template Frand11<T>();
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 = m_Rand[threadIndex].template Frand01<T>();
//Finally, iterate.
//t.Tic();
//Iterating, loop 3.
m_BadVals[threadIndex] += m_Iterator->Iterate(m_ThreadEmbers[threadIndex], params, m_Samples[threadIndex].data(), m_Rand[threadIndex]);
//m_BadVals[threadIndex] += m_Iterator->Iterate(m_Ember, params, m_Samples[threadIndex].data(), m_Rand[threadIndex]);
//iterationTime += t.Toc();
double percentDiff = percent - m_LastIterPercent;
double toc = m_ProgressTimer.Toc();
if (m_LockAccum)
m_AccumCs.Enter();
if (percentDiff >= 10 || (toc > 1000 && percentDiff >= 1))//Call callback function if either 10% has passed, or one second (and 1%).
//t.Tic();
//Map temp buffer samples into the histogram using the palette for color.
Accumulate(m_Rand[threadIndex], m_Samples[threadIndex].data(), params.m_Count, &m_Dmap);
//accumulationTime += t.Toc();
if (m_LockAccum)
m_AccumCs.Leave();
if (m_Callback && threadIndex == 0)
{
etaMs = ((100.0 - percent) / percent) * m_RenderTimer.Toc();
percent = 100.0 *
double
(
double
(
double
(
//Takes progress of current thread and multiplies by thread count.
//This assumes the threads progress at roughly the same speed.
double(m_LastIter + (m_SubBatch[threadIndex] * m_ThreadsToUse)) / double(ItersPerTemporalSample())
) + temporalSample
) / double(TemporalSamples())
);
double percentDiff = percent - m_LastIterPercent;
double toc = m_ProgressTimer.Toc();
if (!m_Callback->ProgressFunc(m_Ember, m_ProgressParameter, percent, 0, etaMs))
Abort();
if (percentDiff >= 10 || (toc > 1000 && percentDiff >= 1))//Call callback function if either 10% has passed, or one second (and 1%).
{
etaMs = ((100.0 - percent) / percent) * m_RenderTimer.Toc();
m_LastIterPercent = percent;
m_ProgressTimer.Tic();
if (!m_Callback->ProgressFunc(m_Ember, m_ProgressParameter, percent, 0, etaMs))
Abort();
m_LastIterPercent = percent;
m_ProgressTimer.Tic();
}
}
}
}
});
});
#ifdef TG
}
@ -1388,7 +1372,7 @@ template <typename T, typename bucketT> T Renderer<T, bucketT>::PixelAspectRatio
template <typename T, typename bucketT>
void Renderer<T, bucketT>::PixelAspectRatio(T pixelAspectRatio)
{
ChangeVal([&] { m_PixelAspectRatio = pixelAspectRatio; }, FULL_RENDER);
ChangeVal([&] { m_PixelAspectRatio = pixelAspectRatio; }, eProcessAction::FULL_RENDER);
}
/// <summary>
@ -1487,7 +1471,6 @@ void Renderer<T, bucketT>::PrepFinalAccumVals(Color<bucketT>& background, bucket
g = 1 / ClampGte<bucketT>(gamma / vibGamCount, bucketT(0.01));//Ensure a divide by zero doesn't occur.
linRange = GammaThresh();
vibrancy /= vibGamCount;
background.x = (IsNearZero(m_Background.r) ? bucketT(m_Ember.m_Background.r) : m_Background.r) / (vibGamCount / bucketT(256.0));//Background is [0, 1].
background.y = (IsNearZero(m_Background.g) ? bucketT(m_Ember.m_Background.g) : m_Background.g) / (vibGamCount / bucketT(256.0));
background.z = (IsNearZero(m_Background.b) ? bucketT(m_Ember.m_Background.b) : m_Background.b) / (vibGamCount / bucketT(256.0));
@ -1510,7 +1493,7 @@ void Renderer<T, bucketT>::Accumulate(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand, Poin
size_t histIndex, intColorIndex, histSize = m_HistBuckets.size();
bucketT colorIndex, colorIndexFrac;
auto dmap = palette->m_Entries.data();
//It's critical to understand what's going on here as it's one of the most important parts of the algorithm.
//A color value gets retrieved from the palette and
//its RGB values are added to the existing RGB values in the histogram bucket.
@ -1528,7 +1511,6 @@ void Renderer<T, bucketT>::Accumulate(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand, Poin
{
T p00 = p.m_X - CenterX();
T p11 = p.m_Y - m_Ember.m_RotCenterY;
p.m_X = (p00 * m_RotMat.A()) + (p11 * m_RotMat.B()) + CenterX();
p.m_Y = (p00 * m_RotMat.D()) + (p11 * m_RotMat.E()) + m_Ember.m_RotCenterY;
}
@ -1554,7 +1536,7 @@ void Renderer<T, bucketT>::Accumulate(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand, Poin
//Fraction = 0.7
//Color = (dmap[25] * 0.3) + (dmap[26] * 0.7)
//Use overloaded addition and multiplication operators in vec4 to perform the accumulation.
if (PaletteMode() == PALETTE_LINEAR)
if (PaletteMode() == ePaletteMode::PALETTE_LINEAR)
{
colorIndex = bucketT(p.m_ColorX) * COLORMAP_LENGTH;
intColorIndex = size_t(colorIndex);
@ -1579,7 +1561,7 @@ void Renderer<T, bucketT>::Accumulate(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand, Poin
else
m_HistBuckets[histIndex] += (((dmap[intColorIndex] * (1 - colorIndexFrac)) + (dmap[intColorIndex + 1] * colorIndexFrac)) * bucketT(p.m_VizAdjusted));
}
else if (PaletteMode() == PALETTE_STEP)
else if (PaletteMode() == ePaletteMode::PALETTE_STEP)
{
intColorIndex = Clamp<size_t>(size_t(p.m_ColorX * COLORMAP_LENGTH), 0, COLORMAP_LENGTH_MINUS_1);
@ -1691,7 +1673,6 @@ void Renderer<T, bucketT>::CurveAdjust(bucketT& a, const glm::length_t& index)
{
size_t tempIndex = size_t(Clamp<bucketT>(a, 0, COLORMAP_LENGTH_MINUS_1));
size_t tempIndex2 = size_t(Clamp<bucketT>(m_Csa[tempIndex].x, 0, COLORMAP_LENGTH_MINUS_1));
a = std::round(m_Csa[tempIndex2][index]);
}

View File

@ -56,7 +56,7 @@ public:
virtual void ComputeBounds() override;
virtual void ComputeQuality() override;
virtual void ComputeCamera() override;
virtual void SetEmber(Ember<T>& ember, eProcessAction action = FULL_RENDER) override;
virtual void SetEmber(Ember<T>& ember, eProcessAction action = eProcessAction::FULL_RENDER) override;
virtual void SetEmber(vector<Ember<T>>& embers) override;
virtual bool CreateDEFilter(bool& newAlloc) override;
virtual bool CreateSpatialFilter(bool& newAlloc) override;
@ -146,7 +146,7 @@ protected:
//Non-virtual functions that might be needed by a derived class.
void PrepFinalAccumVals(Color<bucketT>& background, bucketT& g, bucketT& linRange, bucketT& vibrancy);
private:
private:
//Miscellaneous non-virtual functions used only in this class.
void Accumulate(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand, Point<T>* samples, size_t sampleCount, const Palette<bucketT>* palette);
/*inline*/ void AddToAccum(const tvec4<bucketT, glm::defaultp>& bucket, intmax_t i, intmax_t ii, intmax_t j, intmax_t jj);

View File

@ -8,7 +8,7 @@ namespace EmberNs
/// The thread count is set to the number of cores detected on the system.
/// </summary>
RendererBase::RendererBase()
:m_TaskGroup(new tbb::task_group)
: m_TaskGroup(new tbb::task_group)
{
m_Abort = false;
m_LockAccum = false;
@ -27,10 +27,10 @@ RendererBase::RendererBase()
m_LastTemporalSample = 0;
m_LastIter = 0;
m_LastIterPercent = 0;
m_InteractiveFilter = FILTER_LOG;
m_InteractiveFilter = eInteractiveFilter::FILTER_LOG;
m_Priority = eThreadPriority::NORMAL;
m_ProcessState = NONE;
m_ProcessAction = FULL_RENDER;
m_ProcessState = eProcessState::NONE;
m_ProcessAction = eProcessAction::FULL_RENDER;
m_InRender = false;
m_InFinalAccum = false;
}
@ -56,62 +56,62 @@ void RendererBase::ChangeVal(std::function<void(void)> func, eProcessAction acti
func();
//If they want a full render, don't bother inspecting process state, just start over.
if (action == FULL_RENDER)
if (action == eProcessAction::FULL_RENDER)
{
m_ProcessState = NONE;
m_ProcessAction = FULL_RENDER;
m_ProcessState = eProcessState::NONE;
m_ProcessAction = eProcessAction::FULL_RENDER;
}
//Keep iterating is when rendering has completed and the user increases the quality.
//Rendering can be started where it left off by adding just the difference between the
//new and old quality values.
else if (action == KEEP_ITERATING)
else if (action == eProcessAction::KEEP_ITERATING)
{
if (m_ProcessState == ACCUM_DONE && TemporalSamples() == 1)
if (m_ProcessState == eProcessState::ACCUM_DONE && TemporalSamples() == 1)
{
m_ProcessState = ITER_STARTED;
m_ProcessAction = KEEP_ITERATING;
m_ProcessState = eProcessState::ITER_STARTED;
m_ProcessAction = eProcessAction::KEEP_ITERATING;
}
else//Invaid process state to handle KEEP_ITERATING, so just start over.
{
m_ProcessState = NONE;
m_ProcessAction = FULL_RENDER;
m_ProcessState = eProcessState::NONE;
m_ProcessAction = eProcessAction::FULL_RENDER;
}
}
else if (action == FILTER_AND_ACCUM)
else if (action == eProcessAction::FILTER_AND_ACCUM)
{
//If in the middle of a render, cannot skip to filtering or accum, so just start over.
if (m_ProcessState == NONE || m_ProcessState == ITER_STARTED)
if (m_ProcessState == eProcessState::NONE || m_ProcessState == eProcessState::ITER_STARTED)
{
m_ProcessState = NONE;
m_ProcessAction = FULL_RENDER;
m_ProcessState = eProcessState::NONE;
m_ProcessAction = eProcessAction::FULL_RENDER;
}
//Set the state to ITER_DONE and the next process action to FILTER_AND_ACCUM.
else
{
m_ProcessState = ITER_DONE;
m_ProcessAction = FILTER_AND_ACCUM;
m_ProcessState = eProcessState::ITER_DONE;
m_ProcessAction = eProcessAction::FILTER_AND_ACCUM;
}
}
//Run accum only.
else if (action == ACCUM_ONLY)
else if (action == eProcessAction::ACCUM_ONLY)
{
//Doesn't make sense if in the middle of iterating, so just start over.
if (m_ProcessState == NONE || m_ProcessState == ITER_STARTED)
if (m_ProcessState == eProcessState::NONE || m_ProcessState == eProcessState::ITER_STARTED)
{
m_ProcessAction = FULL_RENDER;
m_ProcessAction = eProcessAction::FULL_RENDER;
}
else if (m_ProcessState == ITER_DONE)//If iterating is done, can start at density filtering and proceed.
else if (m_ProcessState == eProcessState::ITER_DONE)//If iterating is done, can start at density filtering and proceed.
{
m_ProcessAction = FILTER_AND_ACCUM;
m_ProcessAction = eProcessAction::FILTER_AND_ACCUM;
}
else if (m_ProcessState == FILTER_DONE)//Density filtering is done, so the process action is assigned as desired.
else if (m_ProcessState == eProcessState::FILTER_DONE)//Density filtering is done, so the process action is assigned as desired.
{
m_ProcessAction = ACCUM_ONLY;
m_ProcessAction = eProcessAction::ACCUM_ONLY;
}
else if (m_ProcessState == ACCUM_DONE)//Final accum is done, so back up and run final accum again.
else if (m_ProcessState == eProcessState::ACCUM_DONE)//Final accum is done, so back up and run final accum again.
{
m_ProcessState = FILTER_DONE;
m_ProcessAction = ACCUM_ONLY;
m_ProcessState = eProcessState::FILTER_DONE;
m_ProcessAction = eProcessAction::ACCUM_ONLY;
}
}
@ -125,11 +125,9 @@ void RendererBase::ChangeVal(std::function<void(void)> func, eProcessAction acti
size_t RendererBase::HistMemoryRequired(size_t strips)
{
bool newFilterAlloc = false;
CreateSpatialFilter(newFilterAlloc);
CreateTemporalFilter(newFilterAlloc);
ComputeBounds();
//Because ComputeBounds() was called, this includes gutter.
return (SuperSize() * HistBucketSize()) / strips;
}
@ -149,11 +147,9 @@ pair<size_t, size_t> RendererBase::MemoryRequired(size_t strips, bool includeFin
{
pair<size_t, size_t> p;
size_t outSize = includeFinal ? FinalBufferSize() : 0;
outSize *= (threadedWrite ? 2 : 1);
p.first = HistMemoryRequired(strips);
p.second = (p.first * 2) + outSize;//Multiply hist by 2 to account for the density filtering buffer which is the same size as the histogram.
return p;
}
@ -183,7 +179,7 @@ bool RendererBase::RandVec(vector<QTIsaac<ISAAC_SIZE, ISAAC_INT>>& randVec)
{
m_Rand = randVec;
b = true;
}, FULL_RENDER);
}, eProcessAction::FULL_RENDER);
}
return b;
@ -218,7 +214,6 @@ bool RendererBase::PrepFinalAccumVector(vector<byte>& pixels)
}
LeaveResize();
return pixels.size() >= size;//Ensure allocation went ok.
}
@ -244,21 +239,14 @@ bool RendererBase::Ok() const
size_t RendererBase::MemoryAvailable()
{
size_t memAvailable = 0;
#ifdef WIN32
MEMORYSTATUSEX stat;
stat.dwLength = sizeof(stat);
GlobalMemoryStatusEx(&stat);
memAvailable = stat.ullTotalPhys;
#elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE)
memAvailable = sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE);
#elif defined __APPLE__
#ifdef __LP64__
long physmem;
size_t len = sizeof(physmem);
@ -280,12 +268,9 @@ size_t RendererBase::MemoryAvailable()
}
#else
cout << "Warning: unable to determine physical memory." << endl;
memAvailable = 4e9;
#endif
return memAvailable;
}
@ -336,7 +321,7 @@ bool RendererBase::LockAccum() const { return m_LockAccum; }
/// <param name="lockAccum">True if the histogram should be locked when accumulating, else false</param>
void RendererBase::LockAccum(bool lockAccum)
{
ChangeVal([&] { m_LockAccum = lockAccum; }, FULL_RENDER);
ChangeVal([&] { m_LockAccum = lockAccum; }, eProcessAction::FULL_RENDER);
}
/// <summary>
@ -355,7 +340,7 @@ bool RendererBase::EarlyClip() const { return m_EarlyClip; }
/// <param name="earlyClip">True if early clip, else false.</param>
void RendererBase::EarlyClip(bool earlyClip)
{
ChangeVal([&] { m_EarlyClip = earlyClip; }, FILTER_AND_ACCUM);
ChangeVal([&] { m_EarlyClip = earlyClip; }, eProcessAction::FILTER_AND_ACCUM);
}
/// <summary>
@ -371,7 +356,7 @@ bool RendererBase::YAxisUp() const { return m_YAxisUp; }
/// <param name="yup">True if the positive y axis is up, else false.</param>
void RendererBase::YAxisUp(bool yup)
{
ChangeVal([&] { m_YAxisUp = yup; }, ACCUM_ONLY);
ChangeVal([&] { m_YAxisUp = yup; }, eProcessAction::ACCUM_ONLY);
}
/// <summary>
@ -390,7 +375,7 @@ bool RendererBase::InsertPalette() const { return m_InsertPalette; }
/// <param name="insertPalette">True if inserting the palette, else false.</param>
void RendererBase::InsertPalette(bool insertPalette)
{
ChangeVal([&] { m_InsertPalette = insertPalette; }, ACCUM_ONLY);
ChangeVal([&] { m_InsertPalette = insertPalette; }, eProcessAction::ACCUM_ONLY);
}
/// <summary>
@ -409,7 +394,7 @@ bool RendererBase::ReclaimOnResize() const { return m_ReclaimOnResize; }
/// <param name="reclaimOnResize">True if reclaim, else false.</param>
void RendererBase::ReclaimOnResize(bool reclaimOnResize)
{
ChangeVal([&] { m_ReclaimOnResize = reclaimOnResize; }, FULL_RENDER);
ChangeVal([&] { m_ReclaimOnResize = reclaimOnResize; }, eProcessAction::FULL_RENDER);
}
/// <summary>
@ -430,7 +415,7 @@ bool RendererBase::Transparency() const { return m_Transparency; }
/// <param name="transparency">True if using transparency, else false.</param>
void RendererBase::Transparency(bool transparency)
{
ChangeVal([&] { m_Transparency = transparency; }, ACCUM_ONLY);
ChangeVal([&] { m_Transparency = transparency; }, eProcessAction::ACCUM_ONLY);
}
/// <summary>
@ -483,7 +468,6 @@ void RendererBase::ThreadCount(size_t threads, const char* seedString)
if (seedString)
{
ISAAC_INT newSize = ISAAC_INT(size + 5 + (t.Toc() + t.EndTime()));
#ifdef ISAAC_FLAM3_DEBUG
QTIsaac<ISAAC_SIZE, ISAAC_INT> isaac(0, 0, 0, seeds);
#else
@ -505,11 +489,10 @@ void RendererBase::ThreadCount(size_t threads, const char* seedString)
t.Toc();
ISAAC_INT r = ISAAC_INT((size * i) + i + t.EndTime());
QTIsaac<ISAAC_SIZE, ISAAC_INT> isaac(r, r * 2, r * 3, seeds);
m_Rand.push_back(isaac);
}
}
}, FULL_RENDER);
}, eProcessAction::FULL_RENDER);
}
/// <summary>
@ -536,7 +519,7 @@ void RendererBase::BytesPerChannel(size_t bytesPerChannel)
m_BytesPerChannel = 1;
else
m_BytesPerChannel = bytesPerChannel;
}, ACCUM_ONLY);
}, eProcessAction::ACCUM_ONLY);
}
/// <summary>
@ -576,7 +559,7 @@ eInteractiveFilter RendererBase::InteractiveFilter() const { return m_Interactiv
/// <param name="filter">The filter.</param>
void RendererBase::InteractiveFilter(eInteractiveFilter filter)
{
ChangeVal([&] { m_InteractiveFilter = filter; }, FULL_RENDER);
ChangeVal([&] { m_InteractiveFilter = filter; }, eProcessAction::FULL_RENDER);
}
/// <summary>
@ -592,7 +575,7 @@ void RendererBase::InteractiveFilter(eInteractiveFilter filter)
/// <param name="numChannels">The number of channels per pixel in the output image</param>
void RendererBase::NumChannels(size_t numChannels)
{
ChangeVal([&] { m_NumChannels = numChannels; }, ACCUM_ONLY);
ChangeVal([&] { m_NumChannels = numChannels; }, eProcessAction::ACCUM_ONLY);
}
/// <summary>
@ -623,8 +606,8 @@ void RendererBase::Reset()
EnterFinalAccum();
LeaveFinalAccum();
LeaveRender();
m_ProcessState = NONE;
m_ProcessAction = FULL_RENDER;
m_ProcessState = eProcessState::NONE;
m_ProcessAction = eProcessAction::FULL_RENDER;
}
void RendererBase::EnterRender() { m_RenderingCs.Enter(); }

View File

@ -106,9 +106,9 @@ public:
//Virtual processing functions.
virtual bool Ok() const;
virtual size_t MemoryAvailable();
virtual void SetEmber(Ember<float>& ember, eProcessAction action = FULL_RENDER) { }
virtual void SetEmber(Ember<float>& ember, eProcessAction action = eProcessAction::FULL_RENDER) { }
virtual void SetEmber(vector<Ember<float>>& embers) { }
virtual void SetEmber(Ember<double>& ember, eProcessAction action = FULL_RENDER) { }
virtual void SetEmber(Ember<double>& ember, eProcessAction action = eProcessAction::FULL_RENDER) { }
virtual void SetEmber(vector<Ember<double>>& embers) { }
virtual bool RandVec(vector<QTIsaac<ISAAC_SIZE, ISAAC_INT>>& randVec);

View File

@ -64,14 +64,12 @@ public:
SheepTools(const string& palettePath, Renderer<T, bucketT>* renderer)
{
Timing t;
m_Smooth = true;
m_SheepGen = -1;
m_SheepId = -1;
m_Stagger = 0;
m_OffsetX = 0;
m_OffsetY = 0;
m_PaletteList.Add(palettePath);
m_StandardIterator = unique_ptr<StandardIterator<T>>(new StandardIterator<T>());
m_XaosIterator = unique_ptr<XaosIterator<T>>(new XaosIterator<T>());
@ -86,15 +84,12 @@ public:
Ember<T> CreateLinearDefault()
{
Ember<T> ember;
Xform<T> xform1(T(0.25), T(1), T(0.5), T(1), T(0.5), T(0), T(0), T(0.5), T(0.5), T(0.25));
Xform<T> xform2(T(0.25), T(0.66), T(0.5), T(1), T(0.5), T(0), T(0), T(0.5), T(-0.5), T(0.25));
Xform<T> xform3(T(0.25), T(0.33), T(0.5), T(1), T(0.5), T(0), T(0), T(0.5), T(0.0), T(-0.5));
xform1.AddVariation(new LinearVariation<T>());
xform2.AddVariation(new LinearVariation<T>());
xform3.AddVariation(new LinearVariation<T>());
ember.AddXform(xform1);
ember.AddXform(xform2);
ember.AddXform(xform3);
@ -142,7 +137,6 @@ public:
{
Variation<T>* var = nullptr;
Variation<T>* smallestVar = nullptr;
numVars = 0;
smallest = -1;
@ -171,7 +165,8 @@ public:
if (smallestVar)
xform->DeleteVariationById(smallestVar->VariationId());
}
} while (numVars > maxVars);
}
while (numVars > maxVars);
}
return os.str();
@ -194,7 +189,6 @@ public:
T randSelect;
ostringstream os;
Ember<T> mutation;
mutation.Clear();
//If mutate_mode = -1, choose a random mutation mode.
@ -251,13 +245,13 @@ public:
}
}
}
} while (!done);
}
while (!done);
}
else if (mode == MUTATE_ONE_XFORM_COEFS)
{
//Generate a 2-xform random.
Random(mutation, useVars, sym, 2, maxVars);
//Which xform to mutate?
modXform = m_Rand.Rand() % ember.TotalXformCount();
Xform<T>* xform1 = ember.GetTotalXform(modXform);
@ -286,7 +280,6 @@ public:
{
bool same = (m_Rand.Rand() & 3) > 0;//25% chance of using the same post for all of them.
size_t b = 1 + m_Rand.Rand() % 6;
os << "mutate post xforms " << b << (same ? " same" : "");
for (size_t i = 0; i < ember.TotalXformCount(); i++)
@ -305,24 +298,19 @@ public:
{
T f = T(M_PI) * m_Rand.Frand11<T>();
T ra, rb, rd, re;
ra = (xform->m_Affine.A() * std::cos(f) + xform->m_Affine.B() * -std::sin(f));
rd = (xform->m_Affine.A() * std::sin(f) + xform->m_Affine.D() * std::cos(f));
rb = (xform->m_Affine.B() * std::cos(f) + xform->m_Affine.E() * -std::sin(f));
re = (xform->m_Affine.B() * std::sin(f) + xform->m_Affine.E() * std::cos(f));
xform->m_Affine.A(ra);
xform->m_Affine.B(rb);
xform->m_Affine.D(rd);
xform->m_Affine.E(re);
f *= -1;
ra = (xform->m_Post.A() * std::cos(f) + xform->m_Post.B() * -std::sin(f));
rd = (xform->m_Post.A() * std::sin(f) + xform->m_Post.D() * std::cos(f));
rb = (xform->m_Post.B() * std::cos(f) + xform->m_Post.E() * -std::sin(f));
re = (xform->m_Post.B() * std::sin(f) + xform->m_Post.E() * std::cos(f));
xform->m_Post.A(ra);
xform->m_Post.B(rb);
xform->m_Post.D(rd);
@ -340,9 +328,8 @@ public:
if (m_Rand.RandBit())
g = f;
else
if (m_Rand.RandBit())
g = 1 / g;
else if (m_Rand.RandBit())
g = 1 / g;
xform->m_Affine.A(xform->m_Affine.A() / f);
xform->m_Affine.D(xform->m_Affine.D() / f);
@ -358,7 +345,6 @@ public:
{
T f = m_Rand.Frand11<T>();
T g = m_Rand.Frand11<T>();
xform->m_Affine.C(xform->m_Affine.C() - f);
xform->m_Affine.F(xform->m_Affine.F() - g);
xform->m_Post.C(xform->m_Post.C() + f);
@ -473,7 +459,6 @@ public:
Ember<T> parents[2];
//t = 0.5;//If you ever need to test.
t = m_Rand.Frand01<T>();
parents[0] = ember0;
parents[1] = ember1;
parents[0].m_Time = T(0);
@ -497,7 +482,6 @@ public:
got0 = got1 = 0;
rb = m_Rand.RandBit();
os << rb << ":";
//Copy the parent, sorting the final xform to the end if it's present.
emberOut = rb ? ember1 : ember0;
usedParent = rb;
@ -556,8 +540,8 @@ public:
got0 = 1;
else if (usedParent == 1 && ember1.UseFinalXform())
got1 = 1;
} while ((i > 1) && !(got0 && got1));
}
while ((i > 1) && !(got0 && got1));
os << "cross alternate ";
os << trystr;
@ -577,7 +561,6 @@ public:
//Select the starting parent.
size_t ci;
uint startParent = m_Rand.RandBit();
os << " cmap_cross " << startParent << ":";
//Loop over the entries, switching to the other parent 1% of the time.
@ -604,7 +587,6 @@ public:
void Random(Ember<T>& ember, size_t maxVars)
{
vector<eVariationId> useVars;
Random(ember, useVars, static_cast<intmax_t>(m_Rand.Frand<T>(-2, 2)), 0, maxVars);
}
@ -623,7 +605,6 @@ public:
glm::length_t i, j, k, n;
size_t varCount = m_VariationList.Size();
Palette<T> palette;
static size_t xformDistrib[] =
{
2, 2, 2, 2,
@ -632,15 +613,14 @@ public:
5, 5,
6
};
ember.Clear();
if (m_PaletteList.Size())
ember.m_Palette = *m_PaletteList.GetRandomPalette();
ember.m_Time = 0;
ember.m_Interp = EMBER_INTERP_LINEAR;
ember.m_PaletteInterp = INTERP_HSV;
ember.m_Interp = eInterp::EMBER_INTERP_LINEAR;
ember.m_PaletteInterp = ePaletteInterp::INTERP_HSV;
//Choose the number of xforms.
if (specXforms > 0)
@ -655,7 +635,6 @@ public:
if (addfinal)
{
Xform<T> xform;
xform.m_Affine.A(T(1.1));//Just put something in there so it doesn't show up as being an empty final xform.
ember.SetFinalXform(xform);
}
@ -676,7 +655,6 @@ public:
for (i = 0; i < ember.TotalXformCount(); i++)
{
Xform<T>* xform = ember.GetTotalXform(i);
xform->m_Weight = T(1) / ember.TotalXformCount();
xform->m_ColorX = m_Rand.Frand01<T>();//Original pingponged between 0 and 1, which gives bad coloring. Ember does random instead.
xform->m_ColorY = m_Rand.Frand01<T>();//Will need to update this if 2D coordinates are ever supported.
@ -733,6 +711,7 @@ public:
//but less than varCount. Probability leans
//towards fewer variations.
n = 2;
while (m_Rand.RandBit() && (n < varCount))
n++;
@ -821,7 +800,6 @@ public:
size_t i;
T best, b;
Ember<T> bestEmber = ember;
best = TryColors(ember, colorResolution);
if (best < 0)
@ -864,11 +842,9 @@ public:
size_t pixTotal, res3 = res * res * res;
T scalar;
Ember<T> adjustedEmber = ember;
adjustedEmber.m_Quality = 1;
adjustedEmber.m_Supersample = 1;
adjustedEmber.m_MaxRadDE = 0;
//Scale the image so that the total number of pixels is ~10,000.
pixTotal = ember.m_FinalRasW * ember.m_FinalRasH;
scalar = std::sqrt(T(10000) / pixTotal);
@ -876,7 +852,6 @@ public:
adjustedEmber.m_FinalRasH = static_cast<size_t>(ember.m_FinalRasH * scalar);
adjustedEmber.m_PixelsPerUnit *= scalar;
adjustedEmber.m_TemporalSamples = 1;
m_Renderer->SetEmber(adjustedEmber);
m_Renderer->BytesPerChannel(1);
m_Renderer->EarlyClip(true);
@ -884,7 +859,7 @@ public:
m_Renderer->ThreadCount(Timing::ProcessorCount());
m_Renderer->Callback(nullptr);
if (m_Renderer->Run(m_FinalImage) != RENDER_OK)
if (m_Renderer->Run(m_FinalImage) != eRenderStatus::RENDER_OK)
{
cout << "Error rendering test image for TryColors(). Aborting." << endl;
return -1;
@ -892,7 +867,6 @@ public:
m_Hist.resize(res3);
memset(m_Hist.data(), 0, res3);
p = m_FinalImage.data();
for (i = 0; i < m_Renderer->FinalDimensions(); i++)
@ -1052,17 +1026,13 @@ public:
{
//Align what's going to be interpolated.
Interpolater<T>::Align(prealign, spun, 2);
spun[0].m_Time = 0;
spun[1].m_Time = 1;
//Call this first to establish the asymmetric reference angles.
Interpolater<T>::AsymmetricRefAngles(spun, 2);
//Rotate the aligned xforms.
spun[0].RotateAffines(-blend * 360);
spun[1].RotateAffines(-blend * 360);
Interpolater<T>::Interpolate(spun, 2, m_Smooth ? Interpolater<T>::Smoother(blend) : blend, m_Stagger, result);
}
@ -1084,7 +1054,6 @@ public:
void Spin(Ember<T>& parent, Ember<T>* templ, Ember<T>& result, size_t frame, T blend)
{
char temp[50];
//Spin the parent blend degrees.
Loop(parent, result, blend);
@ -1094,17 +1063,14 @@ public:
//Set ember parameters accordingly.
result.m_Time = T(frame);
result.m_Interp = EMBER_INTERP_LINEAR;
result.m_PaletteInterp = INTERP_HSV;
result.m_Interp = eInterp::EMBER_INTERP_LINEAR;
result.m_PaletteInterp = ePaletteInterp::INTERP_HSV;
//Create the edit doc xml.
sprintf_s(temp, 50, "rotate %g", blend * 360.0);
result.ClearEdit();
result.m_Edits = m_EmberToXml.CreateNewEditdoc(&parent, nullptr, temp, m_Nick, m_Url, m_Id, m_Comment, m_SheepGen, m_SheepId);
//Subpixel jitter.
Offset(result, m_OffsetX, m_OffsetY);
//Make the name of the flame the time.
sprintf_s(temp, 50, "%f", result.m_Time);
result.m_Name = string(temp);
@ -1125,7 +1091,6 @@ public:
void SpinInter(Ember<T>* parents, Ember<T>* templ, Ember<T>& result, size_t frame, bool seqFlag, T blend)
{
char temp[50];
//Interpolate between spun parents.
Edge(parents, result, blend, seqFlag);
@ -1137,15 +1102,12 @@ public:
//Set ember parameters accordingly.
result.m_Time = T(frame);
//Create the edit doc xml.
sprintf_s(temp, 50, "interpolate %g", blend * 360.0);
result.ClearEdit();
result.m_Edits = m_EmberToXml.CreateNewEditdoc(&parents[0], &parents[1], temp, m_Nick, m_Url, m_Id, m_Comment, m_SheepGen, m_SheepId);
//Subpixel jitter.
Offset(result, m_OffsetX, m_OffsetY);
//Make the name of the flame the time.
sprintf_s(temp, 50, "%f", result.m_Time);
result.m_Name = string(temp);
@ -1200,16 +1162,16 @@ public:
if (templ.m_GammaThresh >= 0)
ember.m_GammaThresh = templ.m_GammaThresh;
if (templ.m_SpatialFilterType > 0)
if (templ.m_SpatialFilterType > eSpatialFilterType::GAUSSIAN_SPATIAL_FILTER)
ember.m_SpatialFilterType = templ.m_SpatialFilterType;
if (templ.m_Interp >= 0)
if (templ.m_Interp >= eInterp::EMBER_INTERP_LINEAR)
ember.m_Interp = templ.m_Interp;
if (templ.m_AffineInterp >= 0)
if (templ.m_AffineInterp >= eAffineInterp::AFFINE_INTERP_LINEAR)
ember.m_AffineInterp = templ.m_AffineInterp;
if (templ.m_TemporalFilterType >= 0)
if (templ.m_TemporalFilterType >= eTemporalFilterType::BOX_TEMPORAL_FILTER)
ember.m_TemporalFilterType = templ.m_TemporalFilterType;
if (templ.m_TemporalFilterWidth > 0)
@ -1221,7 +1183,7 @@ public:
if (templ.m_HighlightPower >= 0)
ember.m_HighlightPower = templ.m_HighlightPower;
if (templ.m_PaletteMode >= 0)
if (templ.m_PaletteMode >= ePaletteMode::PALETTE_STEP)
ember.m_PaletteMode = templ.m_PaletteMode;
}
@ -1254,7 +1216,6 @@ public:
T th = by * 2 * T(M_PI) / 360;
T c = std::cos(th);
T s = -std::sin(th);
newCenterX -= oldCenterX;
newCenterY -= oldCenterY;
r[0] = c * newCenterX - s * newCenterY;
@ -1279,7 +1240,6 @@ public:
size_t i, lowTarget, highTarget;
T min[2], max[2];
IterParams<T> params;
m_Renderer->SetEmber(ember);
m_Renderer->CreateSpatialFilter(newAlloc);
m_Renderer->CreateDEFilter(newAlloc);
@ -1298,7 +1258,6 @@ public:
params.m_Skip = 20;
//params.m_OneColDiv2 = m_Renderer->CoordMap().OneCol() / 2;
//params.m_OneRowDiv2 = m_Renderer->CoordMap().OneRow() / 2;
size_t bv = m_Iterator->Iterate(ember, params, m_Samples.data(), m_Rand);//Use a special fuse of 20, all other calls to this will use 15, or 100.
if (bv / T(samples) > eps)
@ -1309,15 +1268,17 @@ public:
lowTarget = static_cast<size_t>(samples * eps);
highTarget = samples - lowTarget;
min[0] = min[1] = 1e10;
max[0] = max[1] = -1e10;
for (i = 0; i < samples; i++)
{
if (m_Samples[i].m_X < min[0]) min[0] = m_Samples[i].m_X;
if (m_Samples[i].m_Y < min[1]) min[1] = m_Samples[i].m_Y;
if (m_Samples[i].m_X > max[0]) max[0] = m_Samples[i].m_X;
if (m_Samples[i].m_Y > max[1]) max[1] = m_Samples[i].m_Y;
}
@ -1327,18 +1288,15 @@ public:
bmin[1] = min[1];
bmax[0] = max[0];
bmax[1] = max[1];
return bv;
}
std::sort(m_Samples.begin(), m_Samples.end(), &SortPointByX<T>);
bmin[0] = m_Samples[lowTarget].m_X;
bmax[0] = m_Samples[highTarget].m_X;
std::sort(m_Samples.begin(), m_Samples.end(), &SortPointByY<T>);
bmin[1] = m_Samples[lowTarget + 1].m_Y;
bmax[1] = m_Samples[highTarget + 1].m_Y;
return bv;
}

View File

@ -11,22 +11,22 @@ namespace EmberNs
/// <summary>
/// The types of spatial filters available.
/// </summary>
enum eSpatialFilterType
enum class eSpatialFilterType : size_t
{
GAUSSIAN_SPATIAL_FILTER = 0,
HERMITE_SPATIAL_FILTER = 1,
BOX_SPATIAL_FILTER = 2,
TRIANGLE_SPATIAL_FILTER = 3,
BELL_SPATIAL_FILTER = 4,
BSPLINE_SPATIAL_FILTER = 5,
LANCZOS3_SPATIAL_FILTER = 6,
LANCZOS2_SPATIAL_FILTER = 7,
MITCHELL_SPATIAL_FILTER = 8,
BLACKMAN_SPATIAL_FILTER = 9,
CATROM_SPATIAL_FILTER = 10,
HAMMING_SPATIAL_FILTER = 11,
HANNING_SPATIAL_FILTER = 12,
QUADRATIC_SPATIAL_FILTER = 13
GAUSSIAN_SPATIAL_FILTER,
HERMITE_SPATIAL_FILTER,
BOX_SPATIAL_FILTER,
TRIANGLE_SPATIAL_FILTER,
BELL_SPATIAL_FILTER,
BSPLINE_SPATIAL_FILTER,
LANCZOS3_SPATIAL_FILTER,
LANCZOS2_SPATIAL_FILTER,
MITCHELL_SPATIAL_FILTER,
BLACKMAN_SPATIAL_FILTER,
CATROM_SPATIAL_FILTER,
HAMMING_SPATIAL_FILTER,
HANNING_SPATIAL_FILTER,
QUADRATIC_SPATIAL_FILTER
};
/// <summary>
@ -109,7 +109,6 @@ public:
{
T fw = T(2.0) * m_Support * m_Supersample * m_FilterRadius / m_PixelAspectRatio;
T adjust, ii, jj;
int fwidth = int(fw) + 1;
int i, j;
@ -133,10 +132,8 @@ public:
//Calculate the function inputs for the kernel function.
ii = ((T(2.0) * i + T(1.0)) / T(fwidth) - T(1.0)) * adjust;
jj = ((T(2.0) * j + T(1.0)) / T(fwidth) - T(1.0)) * adjust;
//Adjust for aspect ratio.
jj /= m_PixelAspectRatio;
m_Filter[i + j * fwidth] = Filter(ii) * Filter(jj);//Call virtual Filter(), implemented in specific derived filter classes.
}
}
@ -149,7 +146,8 @@ public:
}
m_FilterRadius += T(0.01);//Values were too small.
} while (1);
}
while (1);
}
/// <summary>
@ -160,16 +158,14 @@ public:
{
size_t i;
stringstream ss;
ss
<< "Spatial Filter:" << endl
<< " Support: " << m_Support << endl
<< " Filter radius: " << m_FilterRadius << endl
<< " Supersample: " << m_Supersample << endl
<< "Pixel aspect ratio: " << m_PixelAspectRatio << endl
<< "Final filter width: " << m_FinalFilterWidth << endl
<< "Filter buffer size: " << m_Filter.size() << endl;
<< "Spatial Filter:" << endl
<< " Support: " << m_Support << endl
<< " Filter radius: " << m_FilterRadius << endl
<< " Supersample: " << m_Supersample << endl
<< "Pixel aspect ratio: " << m_PixelAspectRatio << endl
<< "Final filter width: " << m_FinalFilterWidth << endl
<< "Filter buffer size: " << m_Filter.size() << endl;
ss << "Filter: " << endl;
for (i = 0; i < m_Filter.size(); i++)
@ -260,7 +256,7 @@ public:
/// <param name="superSample">The supersample of the ember being rendered</param>
/// <param name="pixelAspectRatio">The pixel aspect ratio being used to render. Default: 1.</param>
GaussianFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0))
: SpatialFilter<T>(GAUSSIAN_SPATIAL_FILTER, T(1.5), filterRadius, superSample, pixelAspectRatio) { }
: SpatialFilter<T>(eSpatialFilterType::GAUSSIAN_SPATIAL_FILTER, T(1.5), filterRadius, superSample, pixelAspectRatio) { }
/// <summary>
/// Apply Gaussian filter to t parameter and return.
@ -288,7 +284,7 @@ public:
/// <param name="superSample">The supersample of the ember being rendered</param>
/// <param name="pixelAspectRatio">The pixel aspect ratio being used to render. Default: 1.</param>
HermiteFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0))
: SpatialFilter<T>(HERMITE_SPATIAL_FILTER, T(1.0), filterRadius, superSample, pixelAspectRatio) { }
: SpatialFilter<T>(eSpatialFilterType::HERMITE_SPATIAL_FILTER, T(1.0), filterRadius, superSample, pixelAspectRatio) { }
/// <summary>
/// Apply Hermite filter to t parameter and return.
@ -323,7 +319,7 @@ public:
/// <param name="superSample">The supersample of the ember being rendered</param>
/// <param name="pixelAspectRatio">The pixel aspect ratio being used to render. Default: 1.</param>
BoxFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0))
: SpatialFilter<T>(BOX_SPATIAL_FILTER, T(0.5), filterRadius, superSample, pixelAspectRatio) { }
: SpatialFilter<T>(eSpatialFilterType::BOX_SPATIAL_FILTER, T(0.5), filterRadius, superSample, pixelAspectRatio) { }
/// <summary>
/// Apply Box filter to t parameter and return.
@ -354,7 +350,7 @@ public:
/// <param name="superSample">The supersample of the ember being rendered</param>
/// <param name="pixelAspectRatio">The pixel aspect ratio being used to render. Default: 1.</param>
TriangleFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0))
: SpatialFilter<T>(TRIANGLE_SPATIAL_FILTER, T(1.0), filterRadius, superSample, pixelAspectRatio) { }
: SpatialFilter<T>(eSpatialFilterType::TRIANGLE_SPATIAL_FILTER, T(1.0), filterRadius, superSample, pixelAspectRatio) { }
/// <summary>
/// Apply Triangle filter to t parameter and return.
@ -388,7 +384,7 @@ public:
/// <param name="superSample">The supersample of the ember being rendered</param>
/// <param name="pixelAspectRatio">The pixel aspect ratio being used to render. Default: 1.</param>
BellFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0))
: SpatialFilter<T>(BELL_SPATIAL_FILTER, T(1.5), filterRadius, superSample, pixelAspectRatio) { }
: SpatialFilter<T>(eSpatialFilterType::BELL_SPATIAL_FILTER, T(1.5), filterRadius, superSample, pixelAspectRatio) { }
/// <summary>
/// Apply Bell filter to t parameter and return.
@ -429,7 +425,7 @@ public:
/// <param name="superSample">The supersample of the ember being rendered</param>
/// <param name="pixelAspectRatio">The pixel aspect ratio being used to render. Default: 1.</param>
BsplineFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0))
: SpatialFilter<T>(BSPLINE_SPATIAL_FILTER, T(2.0), filterRadius, superSample, pixelAspectRatio) { }
: SpatialFilter<T>(eSpatialFilterType::BSPLINE_SPATIAL_FILTER, T(2.0), filterRadius, superSample, pixelAspectRatio) { }
/// <summary>
/// Apply B Spline filter to t parameter and return.
@ -474,7 +470,7 @@ public:
/// <param name="superSample">The supersample of the ember being rendered</param>
/// <param name="pixelAspectRatio">The pixel aspect ratio being used to render. Default: 1.</param>
Lanczos3Filter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0))
: SpatialFilter<T>(LANCZOS3_SPATIAL_FILTER, T(3.0), filterRadius, superSample, pixelAspectRatio) { }
: SpatialFilter<T>(eSpatialFilterType::LANCZOS3_SPATIAL_FILTER, T(3.0), filterRadius, superSample, pixelAspectRatio) { }
/// <summary>
/// Apply Lanczos 3 filter to t parameter and return.
@ -508,7 +504,7 @@ public:
/// <param name="superSample">The supersample of the ember being rendered</param>
/// <param name="pixelAspectRatio">The pixel aspect ratio being used to render. Default: 1.</param>
Lanczos2Filter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0))
: SpatialFilter<T>(LANCZOS2_SPATIAL_FILTER, T(2.0), filterRadius, superSample, pixelAspectRatio) { }
: SpatialFilter<T>(eSpatialFilterType::LANCZOS2_SPATIAL_FILTER, T(2.0), filterRadius, superSample, pixelAspectRatio) { }
/// <summary>
/// Apply Lanczos 2 filter to t parameter and return.
@ -542,7 +538,7 @@ public:
/// <param name="superSample">The supersample of the ember being rendered</param>
/// <param name="pixelAspectRatio">The pixel aspect ratio being used to render. Default: 1.</param>
MitchellFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0))
: SpatialFilter<T>(MITCHELL_SPATIAL_FILTER, T(2.0), filterRadius, superSample, pixelAspectRatio) { }
: SpatialFilter<T>(eSpatialFilterType::MITCHELL_SPATIAL_FILTER, T(2.0), filterRadius, superSample, pixelAspectRatio) { }
/// <summary>
/// Apply Mitchell filter to t parameter and return.
@ -561,18 +557,16 @@ public:
if (t < 1)
{
t = (((T(12.0) - T(9.0) * b - T(6.0) * c) * (t * tt))
+ ((T(-18.0) + T(12.0) * b + T(6.0) * c) * tt)
+ (T(6.0) - 2 * b));
+ ((T(-18.0) + T(12.0) * b + T(6.0) * c) * tt)
+ (T(6.0) - 2 * b));
return t / 6;
}
else if (t < 2)
{
t = (((T(-1.0) * b - T(6.0) * c) * (t * tt))
+ ((T(6.0) * b + T(30.0) * c) * tt)
+ ((T(-12.0) * b - T(48.0) * c) * t)
+ (T(8.0) * b + 24 * c));
+ ((T(6.0) * b + T(30.0) * c) * tt)
+ ((T(-12.0) * b - T(48.0) * c) * t)
+ (T(8.0) * b + 24 * c));
return t / 6;
}
@ -595,7 +589,7 @@ public:
/// <param name="superSample">The supersample of the ember being rendered</param>
/// <param name="pixelAspectRatio">The pixel aspect ratio being used to render. Default: 1.</param>
BlackmanFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0))
: SpatialFilter<T>(BLACKMAN_SPATIAL_FILTER, T(1.0), filterRadius, superSample, pixelAspectRatio) { }
: SpatialFilter<T>(eSpatialFilterType::BLACKMAN_SPATIAL_FILTER, T(1.0), filterRadius, superSample, pixelAspectRatio) { }
/// <summary>
/// Apply Blackman filter to t parameter and return.
@ -623,7 +617,7 @@ public:
/// <param name="superSample">The supersample of the ember being rendered</param>
/// <param name="pixelAspectRatio">The pixel aspect ratio being used to render. Default: 1.</param>
CatromFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0))
: SpatialFilter<T>(CATROM_SPATIAL_FILTER, T(2.0), filterRadius, superSample, pixelAspectRatio) { }
: SpatialFilter<T>(eSpatialFilterType::CATROM_SPATIAL_FILTER, T(2.0), filterRadius, superSample, pixelAspectRatio) { }
/// <summary>
/// Apply Catmull-Rom filter to t parameter and return.
@ -666,7 +660,7 @@ public:
/// <param name="superSample">The supersample of the ember being rendered</param>
/// <param name="pixelAspectRatio">The pixel aspect ratio being used to render. Default: 1.</param>
HammingFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0))
: SpatialFilter<T>(HAMMING_SPATIAL_FILTER, T(1.0), filterRadius, superSample, pixelAspectRatio) { }
: SpatialFilter<T>(eSpatialFilterType::HAMMING_SPATIAL_FILTER, T(1.0), filterRadius, superSample, pixelAspectRatio) { }
/// <summary>
/// Apply Hamming filter to t parameter and return.
@ -694,7 +688,7 @@ public:
/// <param name="superSample">The supersample of the ember being rendered</param>
/// <param name="pixelAspectRatio">The pixel aspect ratio being used to render. Default: 1.</param>
HanningFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0))
: SpatialFilter<T>(HANNING_SPATIAL_FILTER, T(1.0), filterRadius, superSample, pixelAspectRatio) { }
: SpatialFilter<T>(eSpatialFilterType::HANNING_SPATIAL_FILTER, T(1.0), filterRadius, superSample, pixelAspectRatio) { }
/// <summary>
/// Apply Hanning filter to t parameter and return.
@ -722,7 +716,7 @@ public:
/// <param name="superSample">The supersample of the ember being rendered</param>
/// <param name="pixelAspectRatio">The pixel aspect ratio being used to render. Default: 1.</param>
QuadraticFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0))
: SpatialFilter<T>(QUADRATIC_SPATIAL_FILTER, T(1.5), filterRadius, superSample, pixelAspectRatio) { }
: SpatialFilter<T>(eSpatialFilterType::QUADRATIC_SPATIAL_FILTER, T(1.5), filterRadius, superSample, pixelAspectRatio) { }
/// <summary>
/// Apply Quadratic filter to t parameter and return.
@ -766,36 +760,68 @@ public:
{
SpatialFilter<T>* filter = nullptr;
if (filterType == GAUSSIAN_SPATIAL_FILTER)
filter = new GaussianFilter<T>(filterRadius, superSample, pixelAspectRatio);
else if (filterType == HERMITE_SPATIAL_FILTER)
filter = new HermiteFilter<T>(filterRadius, superSample, pixelAspectRatio);
else if (filterType == BOX_SPATIAL_FILTER)
filter = new BoxFilter<T>(filterRadius, superSample, pixelAspectRatio);
else if (filterType == TRIANGLE_SPATIAL_FILTER)
filter = new TriangleFilter<T>(filterRadius, superSample, pixelAspectRatio);
else if (filterType == BELL_SPATIAL_FILTER)
filter = new BellFilter<T>(filterRadius, superSample, pixelAspectRatio);
else if (filterType == BSPLINE_SPATIAL_FILTER)
filter = new BsplineFilter<T>(filterRadius, superSample, pixelAspectRatio);
else if (filterType == LANCZOS3_SPATIAL_FILTER)
filter = new Lanczos3Filter<T>(filterRadius, superSample, pixelAspectRatio);
else if (filterType == LANCZOS2_SPATIAL_FILTER)
filter = new Lanczos2Filter<T>(filterRadius, superSample, pixelAspectRatio);
else if (filterType == MITCHELL_SPATIAL_FILTER)
filter = new MitchellFilter<T>(filterRadius, superSample, pixelAspectRatio);
else if (filterType == BLACKMAN_SPATIAL_FILTER)
filter = new BlackmanFilter<T>(filterRadius, superSample, pixelAspectRatio);
else if (filterType == CATROM_SPATIAL_FILTER)
filter = new CatromFilter<T>(filterRadius, superSample, pixelAspectRatio);
else if (filterType == HAMMING_SPATIAL_FILTER)
filter = new HammingFilter<T>(filterRadius, superSample, pixelAspectRatio);
else if (filterType == HANNING_SPATIAL_FILTER)
filter = new HanningFilter<T>(filterRadius, superSample, pixelAspectRatio);
else if (filterType == QUADRATIC_SPATIAL_FILTER)
filter = new QuadraticFilter<T>(filterRadius, superSample, pixelAspectRatio);
else
filter = new GaussianFilter<T>(filterRadius, superSample, pixelAspectRatio);
switch (filterType)
{
case EmberNs::eSpatialFilterType::GAUSSIAN_SPATIAL_FILTER:
filter = new GaussianFilter<T>(filterRadius, superSample, pixelAspectRatio);
break;
case EmberNs::eSpatialFilterType::HERMITE_SPATIAL_FILTER:
filter = new HermiteFilter<T>(filterRadius, superSample, pixelAspectRatio);
break;
case EmberNs::eSpatialFilterType::BOX_SPATIAL_FILTER:
filter = new BoxFilter<T>(filterRadius, superSample, pixelAspectRatio);
break;
case EmberNs::eSpatialFilterType::TRIANGLE_SPATIAL_FILTER:
filter = new TriangleFilter<T>(filterRadius, superSample, pixelAspectRatio);
break;
case EmberNs::eSpatialFilterType::BELL_SPATIAL_FILTER:
filter = new BellFilter<T>(filterRadius, superSample, pixelAspectRatio);
break;
case EmberNs::eSpatialFilterType::BSPLINE_SPATIAL_FILTER:
filter = new BsplineFilter<T>(filterRadius, superSample, pixelAspectRatio);
break;
case EmberNs::eSpatialFilterType::LANCZOS3_SPATIAL_FILTER:
filter = new Lanczos3Filter<T>(filterRadius, superSample, pixelAspectRatio);
break;
case EmberNs::eSpatialFilterType::LANCZOS2_SPATIAL_FILTER:
filter = new Lanczos2Filter<T>(filterRadius, superSample, pixelAspectRatio);
break;
case EmberNs::eSpatialFilterType::MITCHELL_SPATIAL_FILTER:
filter = new MitchellFilter<T>(filterRadius, superSample, pixelAspectRatio);
break;
case EmberNs::eSpatialFilterType::BLACKMAN_SPATIAL_FILTER:
filter = new BlackmanFilter<T>(filterRadius, superSample, pixelAspectRatio);
break;
case EmberNs::eSpatialFilterType::CATROM_SPATIAL_FILTER:
filter = new CatromFilter<T>(filterRadius, superSample, pixelAspectRatio);
break;
case EmberNs::eSpatialFilterType::HAMMING_SPATIAL_FILTER:
filter = new HammingFilter<T>(filterRadius, superSample, pixelAspectRatio);
break;
case EmberNs::eSpatialFilterType::HANNING_SPATIAL_FILTER:
filter = new HanningFilter<T>(filterRadius, superSample, pixelAspectRatio);
break;
case EmberNs::eSpatialFilterType::QUADRATIC_SPATIAL_FILTER:
filter = new QuadraticFilter<T>(filterRadius, superSample, pixelAspectRatio);
break;
default:
filter = new GaussianFilter<T>(filterRadius, superSample, pixelAspectRatio);
break;
}
if (filter)
filter->Create();
@ -810,7 +836,6 @@ public:
static vector<string> FilterTypes()
{
vector<string> v;
v.reserve(14);
v.push_back("Gaussian");
v.push_back("Hermite");
@ -826,7 +851,6 @@ public:
v.push_back("Hamming");
v.push_back("Hanning");
v.push_back("Quadratic");
return v;
}
@ -838,35 +862,35 @@ public:
static eSpatialFilterType FromString(const string& filterType)
{
if (!_stricmp(filterType.c_str(), "Gaussian"))
return GAUSSIAN_SPATIAL_FILTER;
return eSpatialFilterType::GAUSSIAN_SPATIAL_FILTER;
else if (!_stricmp(filterType.c_str(), "Hermite"))
return HERMITE_SPATIAL_FILTER;
return eSpatialFilterType::HERMITE_SPATIAL_FILTER;
else if (!_stricmp(filterType.c_str(), "Box"))
return BOX_SPATIAL_FILTER;
return eSpatialFilterType::BOX_SPATIAL_FILTER;
else if (!_stricmp(filterType.c_str(), "Triangle"))
return TRIANGLE_SPATIAL_FILTER;
return eSpatialFilterType::TRIANGLE_SPATIAL_FILTER;
else if (!_stricmp(filterType.c_str(), "Bell"))
return BELL_SPATIAL_FILTER;
return eSpatialFilterType::BELL_SPATIAL_FILTER;
else if (!_stricmp(filterType.c_str(), "Bspline"))
return BSPLINE_SPATIAL_FILTER;
return eSpatialFilterType::BSPLINE_SPATIAL_FILTER;
else if (!_stricmp(filterType.c_str(), "Lanczos3"))
return LANCZOS3_SPATIAL_FILTER;
return eSpatialFilterType::LANCZOS3_SPATIAL_FILTER;
else if (!_stricmp(filterType.c_str(), "Lanczos2"))
return LANCZOS2_SPATIAL_FILTER;
return eSpatialFilterType::LANCZOS2_SPATIAL_FILTER;
else if (!_stricmp(filterType.c_str(), "Mitchell"))
return MITCHELL_SPATIAL_FILTER;
return eSpatialFilterType::MITCHELL_SPATIAL_FILTER;
else if (!_stricmp(filterType.c_str(), "Blackman"))
return BLACKMAN_SPATIAL_FILTER;
return eSpatialFilterType::BLACKMAN_SPATIAL_FILTER;
else if (!_stricmp(filterType.c_str(), "Catrom"))
return CATROM_SPATIAL_FILTER;
return eSpatialFilterType::CATROM_SPATIAL_FILTER;
else if (!_stricmp(filterType.c_str(), "Hamming"))
return HAMMING_SPATIAL_FILTER;
return eSpatialFilterType::HAMMING_SPATIAL_FILTER;
else if (!_stricmp(filterType.c_str(), "Hanning"))
return HANNING_SPATIAL_FILTER;
return eSpatialFilterType::HANNING_SPATIAL_FILTER;
else if (!_stricmp(filterType.c_str(), "Quadratic"))
return QUADRATIC_SPATIAL_FILTER;
return eSpatialFilterType::QUADRATIC_SPATIAL_FILTER;
else
return GAUSSIAN_SPATIAL_FILTER;
return eSpatialFilterType::GAUSSIAN_SPATIAL_FILTER;
}
/// <summary>
@ -878,38 +902,82 @@ public:
{
string filter;
if (filterType == GAUSSIAN_SPATIAL_FILTER)
filter = "Gaussian";
else if (filterType == HERMITE_SPATIAL_FILTER)
filter = "Hermite";
else if (filterType == BOX_SPATIAL_FILTER)
filter = "Box";
else if (filterType == TRIANGLE_SPATIAL_FILTER)
filter = "Triangle";
else if (filterType == BELL_SPATIAL_FILTER)
filter = "Bell";
else if (filterType == BSPLINE_SPATIAL_FILTER)
filter = "Bspline";
else if (filterType == LANCZOS3_SPATIAL_FILTER)
filter = "Lanczos3";
else if (filterType == LANCZOS2_SPATIAL_FILTER)
filter = "Lanczos2";
else if (filterType == MITCHELL_SPATIAL_FILTER)
filter = "Mitchell";
else if (filterType == BLACKMAN_SPATIAL_FILTER)
filter = "Blackman";
else if (filterType == CATROM_SPATIAL_FILTER)
filter = "Catrom";
else if (filterType == HAMMING_SPATIAL_FILTER)
filter = "Hamming";
else if (filterType == HANNING_SPATIAL_FILTER)
filter = "Hanning";
else if (filterType == QUADRATIC_SPATIAL_FILTER)
filter = "Quadratic";
else
filter = "Gaussian";
switch (filterType)
{
case EmberNs::eSpatialFilterType::GAUSSIAN_SPATIAL_FILTER:
filter = "Gaussian";
break;
case EmberNs::eSpatialFilterType::HERMITE_SPATIAL_FILTER:
filter = "Hermite";
break;
case EmberNs::eSpatialFilterType::BOX_SPATIAL_FILTER:
filter = "Box";
break;
case EmberNs::eSpatialFilterType::TRIANGLE_SPATIAL_FILTER:
filter = "Triangle";
break;
case EmberNs::eSpatialFilterType::BELL_SPATIAL_FILTER:
filter = "Bell";
break;
case EmberNs::eSpatialFilterType::BSPLINE_SPATIAL_FILTER:
filter = "Bspline";
break;
case EmberNs::eSpatialFilterType::LANCZOS3_SPATIAL_FILTER:
filter = "Lanczos3";
break;
case EmberNs::eSpatialFilterType::LANCZOS2_SPATIAL_FILTER:
filter = "Lanczos2";
break;
case EmberNs::eSpatialFilterType::MITCHELL_SPATIAL_FILTER:
filter = "Mitchell";
break;
case EmberNs::eSpatialFilterType::BLACKMAN_SPATIAL_FILTER:
filter = "Blackman";
break;
case EmberNs::eSpatialFilterType::CATROM_SPATIAL_FILTER:
filter = "Catrom";
break;
case EmberNs::eSpatialFilterType::HAMMING_SPATIAL_FILTER:
filter = "Hamming";
break;
case EmberNs::eSpatialFilterType::HANNING_SPATIAL_FILTER:
filter = "Hanning";
break;
case EmberNs::eSpatialFilterType::QUADRATIC_SPATIAL_FILTER:
filter = "Quadratic";
break;
default:
filter = "Gaussian";
break;
}
return filter;
}
};
/// <summary>
/// Thin wrapper around SpatialFilterCreator::ToString() to allow << operator on spatial filter type.
/// </summary>
/// <param name="stream">The stream to insert into</param>
/// <param name="t">The type whose string representation will be inserted into the stream</param>
/// <returns></returns>
static std::ostream& operator<<(std::ostream& stream, const eSpatialFilterType& t)
{
stream << SpatialFilterCreator<float>::ToString(t);
return stream;
}
}

View File

@ -11,11 +11,11 @@ namespace EmberNs
/// <summary>
/// The types of temporal filters available.
/// </summary>
enum eTemporalFilterType
enum class eTemporalFilterType : size_t
{
BOX_TEMPORAL_FILTER = 0,
GAUSSIAN_TEMPORAL_FILTER = 1,
EXP_TEMPORAL_FILTER = 2
BOX_TEMPORAL_FILTER,
GAUSSIAN_TEMPORAL_FILTER,
EXP_TEMPORAL_FILTER
};
/// <summary>
@ -49,7 +49,6 @@ public:
TemporalFilter(eTemporalFilterType filterType, size_t temporalSamples, T filterWidth)
{
size_t i, steps = temporalSamples;
m_TemporalSamples = temporalSamples;
m_FilterWidth = filterWidth;
m_Deltas.resize(steps);
@ -116,12 +115,10 @@ public:
{
size_t i;
stringstream ss;
ss << "Temporal Filter:" << endl
<< " Size: " << Size() << endl
<< " Type: " << TemporalFilterCreator<T>::ToString(m_FilterType) << endl
<< " Sum Filt: " << SumFilt() << endl;
ss << "Deltas: " << endl;
for (i = 0; i < m_Deltas.size(); i++)
@ -184,7 +181,7 @@ protected:
template <typename T>
class EMBER_API ExpTemporalFilter : public TemporalFilter<T>
{
TEMPORALFILTERUSINGS
TEMPORALFILTERUSINGS
public:
/// <summary>
/// Constructor to create an Exp filter.
@ -193,7 +190,7 @@ public:
/// <param name="filterWidth">The width of the filter.</param>
/// <param name="filterExp">The filter exp.</param>
ExpTemporalFilter(size_t temporalSamples, T filterWidth, T filterExp)
: TemporalFilter<T>(BOX_TEMPORAL_FILTER, temporalSamples, filterWidth)
: TemporalFilter<T>(eTemporalFilterType::BOX_TEMPORAL_FILTER, temporalSamples, filterWidth)
{
if (Size() > 1)
{
@ -226,7 +223,7 @@ public:
template <typename T>
class EMBER_API GaussianTemporalFilter : public TemporalFilter<T>
{
TEMPORALFILTERUSINGS
TEMPORALFILTERUSINGS
public:
/// <summary>
/// Constructor to create a Gaussian filter.
@ -234,7 +231,7 @@ public:
/// <param name="temporalSamples">The number of temporal samples in the ember being rendered</param>
/// <param name="filterWidth">The width of the filter.</param>
GaussianTemporalFilter(size_t temporalSamples, T filterWidth)
: TemporalFilter<T>(GAUSSIAN_TEMPORAL_FILTER, temporalSamples, filterWidth)
: TemporalFilter<T>(eTemporalFilterType::GAUSSIAN_TEMPORAL_FILTER, temporalSamples, filterWidth)
{
if (Size() > 1)
{
@ -261,7 +258,7 @@ public:
template <typename T>
class EMBER_API BoxTemporalFilter : public TemporalFilter<T>
{
TEMPORALFILTERUSINGS
TEMPORALFILTERUSINGS
public:
/// <summary>
/// Constructor to create a Box filter.
@ -269,7 +266,7 @@ public:
/// <param name="temporalSamples">The number of temporal samples in the ember being rendered</param>
/// <param name="filterWidth">The width of the filter.</param>
BoxTemporalFilter(size_t temporalSamples, T filterWidth)
: TemporalFilter<T>(BOX_TEMPORAL_FILTER, temporalSamples, filterWidth)
: TemporalFilter<T>(eTemporalFilterType::BOX_TEMPORAL_FILTER, temporalSamples, filterWidth)
{
if (Size() > 1)
{
@ -300,14 +297,24 @@ public:
{
TemporalFilter<T>* filter = nullptr;
if (filterType == BOX_TEMPORAL_FILTER)
filter = new BoxTemporalFilter<T>(temporalSamples, filterWidth);
else if (filterType == GAUSSIAN_TEMPORAL_FILTER)
filter = new GaussianTemporalFilter<T>(temporalSamples, filterWidth);
else if (filterType == EXP_TEMPORAL_FILTER)
filter = new ExpTemporalFilter<T>(temporalSamples, filterWidth, filterExp);
else
filter = new BoxTemporalFilter<T>(temporalSamples, filterWidth);//Default to box if bad enum passed in.
switch (filterType)
{
case EmberNs::eTemporalFilterType::BOX_TEMPORAL_FILTER:
filter = new BoxTemporalFilter<T>(temporalSamples, filterWidth);
break;
case EmberNs::eTemporalFilterType::GAUSSIAN_TEMPORAL_FILTER:
filter = new GaussianTemporalFilter<T>(temporalSamples, filterWidth);
break;
case EmberNs::eTemporalFilterType::EXP_TEMPORAL_FILTER:
filter = new ExpTemporalFilter<T>(temporalSamples, filterWidth, filterExp);
break;
default:
filter = new BoxTemporalFilter<T>(temporalSamples, filterWidth);//Default to box if bad enum passed in.
break;
}
return filter;
}
@ -319,12 +326,10 @@ public:
static vector<string> FilterTypes()
{
vector<string> v;
v.reserve(3);
v.push_back("Box");
v.push_back("Gaussian");
v.push_back("Exp");
return v;
}
@ -336,13 +341,13 @@ public:
static eTemporalFilterType FromString(const string& filterType)
{
if (!_stricmp(filterType.c_str(), "box"))
return BOX_TEMPORAL_FILTER;
return eTemporalFilterType::BOX_TEMPORAL_FILTER;
else if (!_stricmp(filterType.c_str(), "gaussian"))
return GAUSSIAN_TEMPORAL_FILTER;
return eTemporalFilterType::GAUSSIAN_TEMPORAL_FILTER;
else if (!_stricmp(filterType.c_str(), "exp"))
return EXP_TEMPORAL_FILTER;
return eTemporalFilterType::EXP_TEMPORAL_FILTER;
else
return BOX_TEMPORAL_FILTER;
return eTemporalFilterType::BOX_TEMPORAL_FILTER;
}
/// <summary>
@ -354,16 +359,38 @@ public:
{
string filter;
if (filterType == BOX_TEMPORAL_FILTER)
filter = "Box";
else if (filterType == GAUSSIAN_TEMPORAL_FILTER)
filter = "Gaussian";
else if (filterType == EXP_TEMPORAL_FILTER)
filter = "Exp";
else
filter = "Box";
switch (filterType)
{
case EmberNs::eTemporalFilterType::BOX_TEMPORAL_FILTER:
filter = "Box";
break;
case EmberNs::eTemporalFilterType::GAUSSIAN_TEMPORAL_FILTER:
filter = "Gaussian";
break;
case EmberNs::eTemporalFilterType::EXP_TEMPORAL_FILTER:
filter = "Exp";
break;
default:
filter = "Box";
break;
}
return filter;
}
};
/// <summary>
/// Thin wrapper around TemporalFilterCreator::ToString() to allow << operator on temporal filter type.
/// </summary>
/// <param name="stream">The stream to insert into</param>
/// <param name="t">The type whose string representation will be inserted into the stream</param>
/// <returns></returns>
static std::ostream& operator<<(std::ostream& stream, const eTemporalFilterType& t)
{
stream << TemporalFilterCreator<float>::ToString(t);
return stream;
}
}

View File

@ -255,7 +255,7 @@ public:
m_MotionOffset = EMPTYFIELD;
}
m_MotionFunc = MOTION_SIN;
m_MotionFunc = eMotion::MOTION_SIN;
m_Motion.clear();
m_NeedPrecalcSumSquares = false;
m_NeedPrecalcSqrtSumSquares = false;

View File

@ -5,7 +5,7 @@
#include "VariationList.h"
#ifdef __APPLE__
#include <libgen.h>
#include <libgen.h>
#endif
/// <summary>
@ -174,14 +174,12 @@ public:
m_BadParamNames["exponentZ"] = "bubbleT3D_exponentZ";
m_BadParamNames["_symmetryZ"] = "bubbleT3D_symmetryZ";
m_BadParamNames["_modusBlur"] = "bubbleT3D_modusBlur";
m_FlattenNames.reserve(24);
m_FlattenNames.push_back("pre_crop");
m_FlattenNames.push_back("pre_falloff2");
m_FlattenNames.push_back("pre_rotate_x");
m_FlattenNames.push_back("pre_rotate_y");
m_FlattenNames.push_back("pre_ztranslate");
m_FlattenNames.push_back("blur3D");
m_FlattenNames.push_back("bubble");
m_FlattenNames.push_back("bwraps");
@ -196,19 +194,14 @@ public:
m_FlattenNames.push_back("zblur");
m_FlattenNames.push_back("zcone");
m_FlattenNames.push_back("ztranslate");
m_FlattenNames.push_back("post_crop");
m_FlattenNames.push_back("post_falloff2");
m_FlattenNames.push_back("post_rotate_x");
m_FlattenNames.push_back("post_rotate_y");
m_FlattenNames.push_back("curl3D_cz");
//This is a vector of the param names as they are in the legacy, badly named flam3/Apophysis code.
vector<string> badParams;
badParams.reserve(6);
badParams.push_back("bwraps7_cellsize");
badParams.push_back("bwraps7_space");
badParams.push_back("bwraps7_gain");
@ -216,7 +209,6 @@ public:
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");
@ -224,7 +216,6 @@ public:
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");
@ -232,7 +223,6 @@ public:
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");
@ -240,7 +230,6 @@ public:
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");
@ -249,7 +238,6 @@ public:
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");
@ -257,11 +245,9 @@ public:
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));//No other special params for these.
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_Init = true;
}
}
@ -286,7 +272,6 @@ public:
Locale locale;//Sets and restores on exit.
//Timing t;
ClearErrorReport();
//Parse XML string into internal document.
xmlPtr = CX(&buf[0]);
bufSize = strlen(xmlPtr);
@ -302,7 +287,6 @@ public:
//What is the root node of the document?
rootnode = xmlDocGetRootElement(doc);
//Scan for <flame> nodes, starting with this node.
//t.Tic();
bn = basename(const_cast<char*>(filename));
@ -316,16 +300,16 @@ public:
//and should be reset to linear (with a warning).
if (emberSize > 0)
{
if (embers[0].m_Interp == EMBER_INTERP_SMOOTH)
if (embers[0].m_Interp == eInterp::EMBER_INTERP_SMOOTH)
{
cout << "Warning: smooth interpolation cannot be used for first segment.\n switching to linear.\n" << endl;
embers[0].m_Interp = EMBER_INTERP_LINEAR;
embers[0].m_Interp = eInterp::EMBER_INTERP_LINEAR;
}
if (emberSize >= 2 && embers[emberSize - 2].m_Interp == EMBER_INTERP_SMOOTH)
if (emberSize >= 2 && embers[emberSize - 2].m_Interp == eInterp::EMBER_INTERP_SMOOTH)
{
cout << "Warning: smooth interpolation cannot be used for last segment.\n switching to linear.\n" << endl;
embers[emberSize - 2].m_Interp = EMBER_INTERP_LINEAR;
embers[emberSize - 2].m_Interp = eInterp::EMBER_INTERP_LINEAR;
}
}
@ -336,8 +320,8 @@ public:
{
for (size_t i = 1; i < emberSize; i++)
{
//Only do this adjustment if not in compat mode..
if (embers[i - 1].m_AffineInterp != AFFINE_INTERP_COMPAT && embers[i - 1].m_AffineInterp != AFFINE_INTERP_OLDER)
//Only do this adjustment if not in compat mode.
if (embers[i - 1].m_AffineInterp != eAffineInterp::AFFINE_INTERP_COMPAT && embers[i - 1].m_AffineInterp != eAffineInterp::AFFINE_INTERP_OLDER)
{
while (embers[i].m_Rotate < embers[i - 1].m_Rotate - 180)
embers[i].m_Rotate += 360;
@ -393,7 +377,6 @@ public:
bool b = true;
const char* loc = __FUNCTION__;
std::istringstream istr(str);
istr >> val;
if (istr.bad() || istr.fail())
@ -405,7 +388,7 @@ public:
return b;
}
/// <summary>
/// Convert an integer to a string.
/// Just a wrapper around _itoa_s() which wraps the result in a std::string.
@ -416,7 +399,6 @@ public:
static string Itos(int i, int radix = 10)
{
char ch[16];
#ifdef WIN32
_itoa_s(i, ch, 16, radix);
#else
@ -435,7 +417,6 @@ public:
static string Itos64(size_t i, int radix = 10)
{
char ch[64];
#ifdef WIN32
_ui64toa_s(i, ch, 64, radix);
#else
@ -493,7 +474,6 @@ private:
//if (!Interpolater<T>::InterpMissingColors(currentEmber.m_Palette.m_Entries))
// AddToReport(string(loc) + " : Error interpolating missing palette colors");
currentEmber.CacheXforms();
currentEmber.m_Index = embers.size();
currentEmber.m_ParentFilename = parentFileString;
@ -525,7 +505,6 @@ private:
double vals[16];
xmlAttrPtr att, curAtt;
xmlNodePtr editNode, childNode, motionNode;
currentEmber.m_Palette.Clear();//Wipe out the current palette.
att = emberNode->properties;//The top level element is a ember element, read the attributes of it and store them.
@ -562,7 +541,6 @@ private:
else if (ParseAndAssign(curAtt->name, attStr, "cam_yaw", currentEmber.m_CamYaw, ret)) { }
else if (ParseAndAssign(curAtt->name, attStr, "cam_pitch", currentEmber.m_CamPitch, ret)) { }
else if (ParseAndAssign(curAtt->name, attStr, "cam_dof", currentEmber.m_CamDepthBlur, ret)) { }
//Parse simple int reads.
else if (ParseAndAssign(curAtt->name, attStr, "palette", currentEmber.m_Palette.m_Index, ret)) { }
else if (ParseAndAssign(curAtt->name, attStr, "oversample", currentEmber.m_Supersample , ret)) { }
@ -572,36 +550,35 @@ private:
else if (ParseAndAssign(curAtt->name, attStr, "fuse", currentEmber.m_FuseCount , ret)) { }
else if (ParseAndAssign(curAtt->name, attStr, "soloxform", soloXform , ret)) { }
else if (ParseAndAssign(curAtt->name, attStr, "new_linear", newLinear , ret)) { }
//Parse more complicated reads that have multiple possible values.
else if (!Compare(curAtt->name, "interpolation"))
{
if (!_stricmp("linear", attStr))
currentEmber.m_Interp = EMBER_INTERP_LINEAR;
currentEmber.m_Interp = eInterp::EMBER_INTERP_LINEAR;
else if (!_stricmp("smooth", attStr))
currentEmber.m_Interp = EMBER_INTERP_SMOOTH;
currentEmber.m_Interp = eInterp::EMBER_INTERP_SMOOTH;
else
AddToReport(string(loc) + " : Unrecognized interpolation type " + string(attStr));
}
else if (!Compare(curAtt->name, "palette_interpolation"))
{
if (!_stricmp("hsv", attStr))
currentEmber.m_PaletteInterp = INTERP_HSV;
currentEmber.m_PaletteInterp = ePaletteInterp::INTERP_HSV;
else if (!_stricmp("sweep", attStr))
currentEmber.m_PaletteInterp = INTERP_SWEEP;
currentEmber.m_PaletteInterp = ePaletteInterp::INTERP_SWEEP;
else
AddToReport(string(loc) + " : Unrecognized palette interpolation type " + string(attStr));
}
else if (!Compare(curAtt->name, "interpolation_space") || !Compare(curAtt->name, "interpolation_type"))
{
if (!_stricmp("linear", attStr))
currentEmber.m_AffineInterp = AFFINE_INTERP_LINEAR;
currentEmber.m_AffineInterp = eAffineInterp::AFFINE_INTERP_LINEAR;
else if (!_stricmp("log", attStr))
currentEmber.m_AffineInterp = AFFINE_INTERP_LOG;
currentEmber.m_AffineInterp = eAffineInterp::AFFINE_INTERP_LOG;
else if (!_stricmp("old", attStr))
currentEmber.m_AffineInterp = AFFINE_INTERP_COMPAT;
currentEmber.m_AffineInterp = eAffineInterp::AFFINE_INTERP_COMPAT;
else if (!_stricmp("older", attStr))
currentEmber.m_AffineInterp = AFFINE_INTERP_OLDER;
currentEmber.m_AffineInterp = eAffineInterp::AFFINE_INTERP_OLDER;
else
AddToReport(string(loc) + " : Unrecognized interpolation type " + string(attStr));
}
@ -621,7 +598,6 @@ private:
{
AddToReport(string(loc) + " : Invalid size attribute " + string(attStr));
xmlFree(attStr);
//These return statements are bad. One because they are inconsistent with others that just assign defaults.
//Two, because assigning easily guessable defaults is easy and less drastic.
return false;
@ -653,12 +629,12 @@ private:
else if (!Compare(curAtt->name, "palette_mode"))
{
if (!_stricmp("step", attStr))
currentEmber.m_PaletteMode = PALETTE_STEP;
currentEmber.m_PaletteMode = ePaletteMode::PALETTE_STEP;
else if (!_stricmp("linear", attStr))
currentEmber.m_PaletteMode = PALETTE_LINEAR;
currentEmber.m_PaletteMode = ePaletteMode::PALETTE_LINEAR;
else
{
currentEmber.m_PaletteMode = PALETTE_STEP;
currentEmber.m_PaletteMode = ePaletteMode::PALETTE_STEP;
AddToReport(string(loc) + " : Unrecognized palette mode " + string(attStr) + ", using step");
}
}
@ -700,7 +676,6 @@ private:
{
index = -1;
double r = 0, g = 0, b = 0, a = 0;
//Loop through the attributes of the color element.
att = childNode->properties;
@ -714,7 +689,6 @@ private:
{
attStr = reinterpret_cast<char*>(xmlGetProp(childNode, curAtt->name));
a = 255;
//This signifies that a palette is not being retrieved from the palette file, rather it's being parsed directly out of the ember xml.
//This also means the palette has already been hue adjusted and it doesn't need to be done again, which would be necessary if it were
//coming from the palette file.
@ -724,17 +698,17 @@ private:
{
Aton(attStr, index);
}
else if(!Compare(curAtt->name, "rgb"))
else if (!Compare(curAtt->name, "rgb"))
{
if (sscanf_s(attStr, "%lf %lf %lf", &r, &g, &b) != 3)
AddToReport(string(loc) + " : Invalid rgb attribute " + string(attStr));
}
else if(!Compare(curAtt->name, "rgba"))
else if (!Compare(curAtt->name, "rgba"))
{
if (sscanf_s(attStr, "%lf %lf %lf %lf", &r, &g, &b, &a) != 4)
AddToReport(string(loc) + " : Invalid rgba attribute " + string(attStr));
}
else if(!Compare(curAtt->name, "a"))
else if (!Compare(curAtt->name, "a"))
{
if (sscanf_s(attStr, "%lf", &a) != 1)
AddToReport(string(loc) + " : Invalid a attribute " + string(attStr));
@ -751,7 +725,6 @@ private:
if (index >= 0 && index <= 255)
{
T alphaPercent = T(a) / T(255);//Aplha percentage in the range of 0 to 1.
//Premultiply the palette.
currentEmber.m_Palette.m_Entries[index].r = alphaPercent * (T(r) / T(255));
currentEmber.m_Palette.m_Entries[index].g = alphaPercent * (T(g) / T(255));
@ -805,7 +778,6 @@ private:
//Make sure BOTH are not specified, otherwise either are ok.
int numColors = 0;
int numBytes = 0;
//Loop through the attributes of the palette element.
att = childNode->properties;
@ -857,7 +829,6 @@ private:
else if (!Compare(childNode->name, "symmetry"))
{
int symKind = INT_MAX;
//Loop through the attributes of the palette element.
att = childNode->properties;
@ -961,7 +932,6 @@ private:
else if (!Compare(childNode->name, "flame_motion"))
{
EmberMotion<T> motion;
att = childNode->properties;
if (att == nullptr)
@ -981,13 +951,13 @@ private:
string func(attStr);
if (func == "sin")
motion.m_MotionFunc = MOTION_SIN;
motion.m_MotionFunc = eMotion::MOTION_SIN;
else if (func == "triangle")
motion.m_MotionFunc = MOTION_TRIANGLE;
motion.m_MotionFunc = eMotion::MOTION_TRIANGLE;
else if (func == "hill")
motion.m_MotionFunc = MOTION_HILL;
motion.m_MotionFunc = eMotion::MOTION_HILL;
else if (func == "saw")
motion.m_MotionFunc = MOTION_SAW;
motion.m_MotionFunc = eMotion::MOTION_SAW;
else
{
AddToReport(string(loc) + " : invalid flame motion function " + func);
@ -995,29 +965,29 @@ private:
}
}
else if (!Compare(curAtt->name, "zoom"))
ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_ZOOM, motion);
ret = ret && AttToEmberMotionFloat(att, attStr, eEmberMotionParam::FLAME_MOTION_ZOOM, motion);
else if (!Compare(curAtt->name, "cam_zpos"))
ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_ZPOS, motion);
ret = ret && AttToEmberMotionFloat(att, attStr, eEmberMotionParam::FLAME_MOTION_ZPOS, motion);
else if (!Compare(curAtt->name, "cam_persp"))
ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_PERSPECTIVE, motion);
ret = ret && AttToEmberMotionFloat(att, attStr, eEmberMotionParam::FLAME_MOTION_PERSPECTIVE, motion);
else if (!Compare(curAtt->name, "cam_yaw"))
ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_YAW, motion);
ret = ret && AttToEmberMotionFloat(att, attStr, eEmberMotionParam::FLAME_MOTION_YAW, motion);
else if (!Compare(curAtt->name, "cam_pitch"))
ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_PITCH, motion);
ret = ret && AttToEmberMotionFloat(att, attStr, eEmberMotionParam::FLAME_MOTION_PITCH, motion);
else if (!Compare(curAtt->name, "cam_dof"))
ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_DEPTH_BLUR, motion);
ret = ret && AttToEmberMotionFloat(att, attStr, eEmberMotionParam::FLAME_MOTION_DEPTH_BLUR, motion);
else if (!Compare(curAtt->name, "rotate"))
ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_ROTATE, motion);
ret = ret && AttToEmberMotionFloat(att, attStr, eEmberMotionParam::FLAME_MOTION_ROTATE, motion);
else if (!Compare(curAtt->name, "brightness"))
ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_BRIGHTNESS, motion);
ret = ret && AttToEmberMotionFloat(att, attStr, eEmberMotionParam::FLAME_MOTION_BRIGHTNESS, motion);
else if (!Compare(curAtt->name, "gamma"))
ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_GAMMA, motion);
ret = ret && AttToEmberMotionFloat(att, attStr, eEmberMotionParam::FLAME_MOTION_GAMMA, motion);
else if (!Compare(curAtt->name, "gamma_threshold"))
ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_GAMMA_THRESH, motion);
ret = ret && AttToEmberMotionFloat(att, attStr, eEmberMotionParam::FLAME_MOTION_GAMMA_THRESH, motion);
else if (!Compare(curAtt->name, "highlight_power"))
ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_HIGHLIGHT_POWER, motion);
ret = ret && AttToEmberMotionFloat(att, attStr, eEmberMotionParam::FLAME_MOTION_HIGHLIGHT_POWER, motion);
else if (!Compare(curAtt->name, "vibrancy"))
ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_VIBRANCY, motion);
ret = ret && AttToEmberMotionFloat(att, attStr, eEmberMotionParam::FLAME_MOTION_VIBRANCY, motion);
else if (!Compare(curAtt->name, "background"))
{
double r, g, b;
@ -1030,13 +1000,13 @@ private:
}
if (r != 0)
motion.m_MotionParams.push_back(MotionParam<T>(FLAME_MOTION_BACKGROUND_R, T(r)));
motion.m_MotionParams.push_back(MotionParam<T>(eEmberMotionParam::FLAME_MOTION_BACKGROUND_R, T(r)));
if (g != 0)
motion.m_MotionParams.push_back(MotionParam<T>(FLAME_MOTION_BACKGROUND_G, T(g)));
motion.m_MotionParams.push_back(MotionParam<T>(eEmberMotionParam::FLAME_MOTION_BACKGROUND_G, T(g)));
if (b != 0)
motion.m_MotionParams.push_back(MotionParam<T>(FLAME_MOTION_BACKGROUND_B, T(b)));
motion.m_MotionParams.push_back(MotionParam<T>(eEmberMotionParam::FLAME_MOTION_BACKGROUND_B, T(b)));
}
else if (!Compare(curAtt->name, "center"))
{
@ -1050,10 +1020,10 @@ private:
}
if (cx != 0)
motion.m_MotionParams.push_back(MotionParam<T>(FLAME_MOTION_CENTER_X, T(cx)));
motion.m_MotionParams.push_back(MotionParam<T>(eEmberMotionParam::FLAME_MOTION_CENTER_X, T(cx)));
if (cy != 0)
motion.m_MotionParams.push_back(MotionParam<T>(FLAME_MOTION_CENTER_Y, T(cy)));
motion.m_MotionParams.push_back(MotionParam<T>(eEmberMotionParam::FLAME_MOTION_CENTER_Y, T(cy)));
}
else
{
@ -1123,7 +1093,6 @@ private:
double a, b, c, d, e, f;
double vals[10];
xmlAttrPtr attPtr, curAtt;
//Loop through the attributes of the xform element.
attPtr = childNode->properties;
@ -1145,7 +1114,6 @@ private:
else if (ParseAndAssign(curAtt->name, attStr, "var_color", xform.m_DirectColor, success)) { }
else if (ParseAndAssign(curAtt->name, attStr, "motion_frequency", xform.m_MotionFreq, success)) { }
else if (ParseAndAssign(curAtt->name, attStr, "motion_offset", xform.m_MotionOffset, success)) { }
//Parse more complicated reads that have multiple possible values.
else if (!Compare(curAtt->name, "name"))
{
@ -1163,16 +1131,16 @@ private:
else if (!Compare(curAtt->name, "motion_function"))
{
if (!_stricmp("sin", attStr))
xform.m_MotionFunc = MOTION_SIN;
xform.m_MotionFunc = eMotion::MOTION_SIN;
else if (!_stricmp("triangle", attStr))
xform.m_MotionFunc = MOTION_TRIANGLE;
xform.m_MotionFunc = eMotion::MOTION_TRIANGLE;
else if (!_stricmp("hill", attStr))
xform.m_MotionFunc = MOTION_HILL;
xform.m_MotionFunc = eMotion::MOTION_HILL;
else if (!_stricmp("saw", attStr))
xform.m_MotionFunc = MOTION_SAW;
xform.m_MotionFunc = eMotion::MOTION_SAW;
else
{
xform.m_MotionFunc = MOTION_SIN;
xform.m_MotionFunc = eMotion::MOTION_SIN;
AddToReport(string(loc) + " : Unknown motion function " + string(attStr) + ", using sin");
}
}
@ -1254,10 +1222,10 @@ private:
if (auto var = m_VariationList.GetVariation(s))
{
auto varCopy = var->Copy();
Aton(attStr, varCopy->m_Weight);
xform.AddVariation(varCopy);
}
//else
//{
// AddToReport("Unsupported variation: " + string((const char*)curAtt->name));
@ -1421,7 +1389,8 @@ private:
{
if (!_stricmp(name, CCX(temp->name)))
return true;
} while ((temp = temp->next));
}
while ((temp = temp->next));
return false;
}
@ -1454,11 +1423,11 @@ private:
{
//Parse an RGB triplet at a time.
if (chan == 3)
ret = sscanf_s(&(colstr[colorIndex]),"%2x%2x%2x", &r, &g, &b);
ret = sscanf_s(&(colstr[colorIndex]), "%2x%2x%2x", &r, &g, &b);
else if (chan == -4)
ret = sscanf_s(&(colstr[colorIndex]),"00%2x%2x%2x", &r, &g, &b);
ret = sscanf_s(&(colstr[colorIndex]), "00%2x%2x%2x", &r, &g, &b);
else // chan==4
ret = sscanf_s(&(colstr[colorIndex]),"%2x%2x%2x%2x", &r,&g, &b, &a);
ret = sscanf_s(&(colstr[colorIndex]), "%2x%2x%2x%2x", &r, &g, &b, &a);
a = 1;//Original allows for alpha, even though it will most likely never happen. Ember omits support for it.
@ -1479,15 +1448,15 @@ private:
ember.m_Palette.m_Entries[colorCount].g = T(g) / T(255);
ember.m_Palette.m_Entries[colorCount].b = T(b) / T(255);
ember.m_Palette.m_Entries[colorCount].a = T(a);
colorCount++;
} while (colorCount < numColors && colorCount < ember.m_Palette.m_Entries.size());
}
while (colorCount < numColors && colorCount < ember.m_Palette.m_Entries.size());
#ifdef WIN32
if (sscanf_s(&(colstr[colorIndex]),"%1s", tmps, sizeof(tmps)) > 0)//Really need to migrate all of this parsing to C++.//TODO
if (sscanf_s(&(colstr[colorIndex]), "%1s", tmps, sizeof(tmps)) > 0) //Really need to migrate all of this parsing to C++.//TODO
#else
if (sscanf_s(&(colstr[colorIndex]),"%1s", tmps) > 0)
if (sscanf_s(&(colstr[colorIndex]), "%1s", tmps) > 0)
#endif
{
AddToReport(string(loc) + " : Extra data at end of hex color data " + string(&(colstr[colorIndex])));
@ -1514,7 +1483,6 @@ private:
if (!Compare(name, str))
{
istringstream istr(attStr);
istr >> val;
ret = !istr.bad() && !istr.fail();//Means the Compare() was right, and the conversion succeeded.
}

View File

@ -354,7 +354,7 @@ bool EmberAnimate(EmberOptions& opt)
renderer->Reset();
if ((renderer->Run(finalImages[finalImageIndex], localTime) != RENDER_OK) || renderer->Aborted() || finalImages[finalImageIndex].empty())
if ((renderer->Run(finalImages[finalImageIndex], localTime) != eRenderStatus::RENDER_OK) || renderer->Aborted() || finalImages[finalImageIndex].empty())
{
cout << "Error: image rendering failed, skipping to next image." << endl;
renderer->DumpErrorReport();//Something went wrong, print errors.

View File

@ -455,7 +455,7 @@ string IterOpenCLKernelCreator<T>::CreateIterKernelString(const Ember<T>& ember,
//Basic texture index interoplation does not produce identical results
//to the CPU. So the code here must explicitly do the same thing and not
//rely on the GPU texture coordinate lookup.
if (ember.m_PaletteMode == PALETTE_LINEAR)
if (ember.m_PaletteMode == ePaletteMode::PALETTE_LINEAR)
{
os <<
" real_t colorIndexFrac;\n"
@ -484,7 +484,7 @@ string IterOpenCLKernelCreator<T>::CreateIterKernelString(const Ember<T>& ember,
" palColor2 = read_imagef(palette, paletteSampler, iPaletteCoord);\n"
" palColor1 = (palColor1 * (1.0f - (float)colorIndexFrac)) + (palColor2 * (float)colorIndexFrac);\n";//The 1.0f here *must* have the 'f' suffix at the end to compile.
}
else if (ember.m_PaletteMode == PALETTE_STEP)
else if (ember.m_PaletteMode == ePaletteMode::PALETTE_STEP)
{
os <<
" iPaletteCoord.x = (int)(secondPoint.m_ColorX * COLORMAP_LENGTH);\n"
@ -922,9 +922,9 @@ string IterOpenCLKernelCreator<T>::CreateProjectionString(const Ember<T>& ember)
if (projBits)
{
if (projBits & PROJBITS_BLUR)
if (projBits & size_t(eProjBits::PROJBITS_BLUR))
{
if (projBits & PROJBITS_YAW)
if (projBits & size_t(eProjBits::PROJBITS_YAW))
{
os <<
" real_t dsin, dcos;\n"
@ -967,9 +967,9 @@ string IterOpenCLKernelCreator<T>::CreateProjectionString(const Ember<T>& ember)
" secondPoint.m_Z -= ember->m_CamZPos;\n";
}
}
else if ((projBits & PROJBITS_PITCH) || (projBits & PROJBITS_YAW))
else if ((projBits & size_t(eProjBits::PROJBITS_PITCH)) || (projBits & size_t(eProjBits::PROJBITS_YAW)))
{
if (projBits & PROJBITS_YAW)
if (projBits & size_t(eProjBits::PROJBITS_YAW))
{
os <<
" real_t z = secondPoint.m_Z - ember->m_CamZPos;\n"

View File

@ -769,14 +769,14 @@ eRenderStatus RendererCL<T, bucketT>::GaussianDensityFilter()
template <typename T, typename bucketT>
eRenderStatus RendererCL<T, bucketT>::AccumulatorToFinalImage(byte* pixels, size_t finalOffset)
{
eRenderStatus status = RunFinalAccum();
auto status = RunFinalAccum();
if (status == RENDER_OK && pixels && !m_Devices.empty() && !m_Devices[0]->m_Wrapper.Shared())
if (status == eRenderStatus::RENDER_OK && pixels && !m_Devices.empty() && !m_Devices[0]->m_Wrapper.Shared())
{
pixels += finalOffset;
if (!ReadFinal(pixels))
status = RENDER_ERROR;
status = eRenderStatus::RENDER_ERROR;
}
return status;
@ -853,7 +853,7 @@ EmberStats RendererCL<T, bucketT>::Iterate(size_t iterCount, size_t temporalSamp
{
m_IterTimer.Tic();//Tic() here to avoid including build time in iter time measurement.
if (m_LastIter == 0 && m_ProcessAction != KEEP_ITERATING)//Only reset the call count on the beginning of a new render. Do not reset on KEEP_ITERATING.
if (m_LastIter == 0 && m_ProcessAction != eProcessAction::KEEP_ITERATING)//Only reset the call count on the beginning of a new render. Do not reset on KEEP_ITERATING.
for (auto& dev : m_Devices)
dev->m_Calls = 0;
@ -1166,7 +1166,7 @@ eRenderStatus RendererCL<T, bucketT>::RunLogScaleFilter()
m_Callback->ProgressFunc(m_Ember, m_ProgressParameter, 100.0, 1, 0.0);
}
return b ? RENDER_OK : RENDER_ERROR;
return b ? eRenderStatus::RENDER_OK : eRenderStatus::RENDER_ERROR;
}
/// <summary>
@ -1288,7 +1288,7 @@ eRenderStatus RendererCL<T, bucketT>::RunDensityFilter()
AddToReport(loc);
}
return m_Abort ? RENDER_ABORT : (b ? RENDER_OK : RENDER_ERROR);
return m_Abort ? eRenderStatus::RENDER_ABORT : (b ? eRenderStatus::RENDER_OK : eRenderStatus::RENDER_ERROR);
}
/// <summary>
@ -1389,7 +1389,7 @@ eRenderStatus RendererCL<T, bucketT>::RunFinalAccum()
AddToReport(loc);
}
return b ? RENDER_OK : RENDER_ERROR;
return b ? eRenderStatus::RENDER_OK : eRenderStatus::RENDER_ERROR;
}
/// <summary>

View File

@ -441,7 +441,7 @@ static bool StripsRender(RendererBase* renderer, Ember<T>& ember, vector<byte>&
renderer->SetEmber(ember);//Set one final time after modifications for strips.
}
if ((renderer->Run(finalImage, time, 0, false, stripOffset) == RENDER_OK) && !renderer->Aborted() && !finalImage.empty())
if ((renderer->Run(finalImage, time, 0, false, stripOffset) == eRenderStatus::RENDER_OK) && !renderer->Aborted() && !finalImage.empty())
{
perStripFinish(strip);
}

View File

@ -11,8 +11,8 @@ template <typename T>
void SetDefaultTestValues(Ember<T>& ember)
{
ember.m_Time = 0.0;
ember.m_Interp = EMBER_INTERP_LINEAR;
ember.m_PaletteInterp = INTERP_HSV;
ember.m_Interp = eInterp::EMBER_INTERP_LINEAR;
ember.m_PaletteInterp = ePaletteInterp::INTERP_HSV;
ember.m_Background[0] = 0;
ember.m_Background[1] = 0;
ember.m_Background[2] = 0;
@ -25,7 +25,7 @@ void SetDefaultTestValues(Ember<T>& ember)
ember.m_FinalRasH = 128;
ember.m_Supersample = 1;
ember.m_SpatialFilterRadius = T(0.5);
ember.m_SpatialFilterType = GAUSSIAN_SPATIAL_FILTER;
ember.m_SpatialFilterType = eSpatialFilterType::GAUSSIAN_SPATIAL_FILTER;
ember.m_Zoom = 0;
ember.m_Quality = 1;
ember.m_TemporalSamples = 1;
@ -353,7 +353,7 @@ bool EmberGenome(EmberOptions& opt)
}
if (!exactTimeMatch)
interpolated.m_AffineInterp = AFFINE_INTERP_LINEAR;
interpolated.m_AffineInterp = eAffineInterp::AFFINE_INTERP_LINEAR;
}
if (pTemplate)
@ -685,7 +685,7 @@ bool EmberGenome(EmberOptions& opt)
SetDefaultTestValues(orig);
renderer->SetEmber(orig);
if (renderer->Run(finalImage) != RENDER_OK)
if (renderer->Run(finalImage) != eRenderStatus::RENDER_OK)
{
cerr << "Error: test image rendering failed, aborting." << endl;
return false;

View File

@ -255,13 +255,13 @@ FinalRenderGuiState FractoriumFinalRenderDialog::State()
eScaleType FractoriumFinalRenderDialog::Scale()
{
if (ui.FinalRenderScaleNoneRadioButton->isChecked())
return SCALE_NONE;
return eScaleType::SCALE_NONE;
else if (ui.FinalRenderScaleWidthRadioButton->isChecked())
return SCALE_WIDTH;
return eScaleType::SCALE_WIDTH;
else if (ui.FinalRenderScaleHeightRadioButton->isChecked())
return SCALE_HEIGHT;
return eScaleType::SCALE_HEIGHT;
else
return SCALE_NONE;
return eScaleType::SCALE_NONE;
}
/// <summary>
@ -272,11 +272,11 @@ void FractoriumFinalRenderDialog::Scale(eScaleType scale)
{
ui.FinalRenderScaleNoneRadioButton->blockSignals(true);
if (scale == SCALE_NONE)
if (scale == eScaleType::SCALE_NONE)
ui.FinalRenderScaleNoneRadioButton->setChecked(true);
else if (scale == SCALE_WIDTH)
else if (scale == eScaleType::SCALE_WIDTH)
ui.FinalRenderScaleWidthRadioButton->setChecked(true);
else if (scale == SCALE_HEIGHT)
else if (scale == eScaleType::SCALE_HEIGHT)
ui.FinalRenderScaleHeightRadioButton->setChecked(true);
else
ui.FinalRenderScaleNoneRadioButton->setChecked(true);

View File

@ -235,7 +235,7 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
renderTimer.Tic();//Toc() is called in RenderComplete().
//Can't use strips render here. Run() must be called directly for animation.
if (renderer->Run(finalImages[finalImageIndex], localTime) != RENDER_OK)
if (renderer->Run(finalImages[finalImageIndex], localTime) != eRenderStatus::RENDER_OK)
{
Output("Rendering failed.\n");
m_Fractorium->ErrorReportToQTextEdit(renderer->ErrorReport(), m_FinalRenderDialog->ui.FinalRenderTextOutput, false);//Internally calls invoke.
@ -874,7 +874,7 @@ void FinalRenderEmberController<T>::RenderComplete(Ember<T>& ember, const EmberS
m_Settings->FinalDoAll(m_GuiState.m_DoAll);
m_Settings->FinalDoSequence(m_GuiState.m_DoSequence);
m_Settings->FinalKeepAspect(m_GuiState.m_KeepAspect);
m_Settings->FinalScale(m_GuiState.m_Scale);
m_Settings->FinalScale(uint(m_GuiState.m_Scale));
m_Settings->FinalExt(m_GuiState.m_Ext);
m_Settings->FinalThreadCount(m_GuiState.m_ThreadCount);
m_Settings->FinalThreadPriority(m_GuiState.m_ThreadPriority);

View File

@ -108,13 +108,13 @@ FractoriumEmberController<T>::FractoriumEmberController(Fractorium* fractorium)
{
Ember<T> ember = m_EmberFile.m_Embers[i];
ember.SyncSize();
ember.SetSizeAndAdjustScale(PREVIEW_SIZE, PREVIEW_SIZE, false, SCALE_WIDTH);
ember.SetSizeAndAdjustScale(PREVIEW_SIZE, PREVIEW_SIZE, false, eScaleType::SCALE_WIDTH);
ember.m_TemporalSamples = 1;
ember.m_Quality = 25;
ember.m_Supersample = 1;
m_PreviewRenderer->SetEmber(ember);
if (m_PreviewRenderer->Run(m_PreviewFinalImage) == RENDER_OK)
if (m_PreviewRenderer->Run(m_PreviewFinalImage) == eRenderStatus::RENDER_OK)
{
if (EmberTreeWidgetItem<T>* treeItem = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(i)))
{
@ -211,7 +211,7 @@ void FractoriumEmberController<T>::SetEmber(size_t index)
/// </summary>
/// <param name="func">The function to call</param>
/// <param name="updateRender">True to update renderer, else false. Default: true.</param>
/// <param name="action">The action to add to the rendering queue. Default: FULL_RENDER.</param>
/// <param name="action">The action to add to the rendering queue. Default: eProcessAction::FULL_RENDER.</param>
template <typename T>
void FractoriumEmberController<T>::Update(std::function<void (void)> func, bool updateRender, eProcessAction action)
{
@ -228,7 +228,7 @@ void FractoriumEmberController<T>::Update(std::function<void (void)> func, bool
/// <param name="func">The function to call</param>
/// <param name="updateType">Whether to apply this update operation on the current, all or selected xforms. Default: UPDATE_CURRENT.</param>
/// <param name="updateRender">True to update renderer, else false. Default: true.</param>
/// <param name="action">The action to add to the rendering queue. Default: FULL_RENDER.</param>
/// <param name="action">The action to add to the rendering queue. Default: eProcessAction::FULL_RENDER.</param>
template <typename T>
void FractoriumEmberController<T>::UpdateXform(std::function<void(Xform<T>*)> func, eXformUpdate updateType, bool updateRender, eProcessAction action)
{

View File

@ -219,7 +219,7 @@ public:
void StopRenderTimer(bool wait);
void ClearFinalImages();
void Shutdown();
void UpdateRender(eProcessAction action = FULL_RENDER);
void UpdateRender(eProcessAction action = eProcessAction::FULL_RENDER);
void DeleteRenderer();
void SaveCurrentRender(const QString& filename, const EmberImageComments& comments, vector<byte>& pixels, size_t width, size_t height, size_t channels, size_t bpc);
RendererBase* Renderer() { return m_Renderer.get(); }
@ -231,7 +231,7 @@ protected:
//Rendering/progress.
void AddProcessAction(eProcessAction action);
eProcessAction CondenseAndClearProcessActions();
eProcessState ProcessState() { return m_Renderer.get() ? m_Renderer->ProcessState() : NONE; }
eProcessState ProcessState() { return m_Renderer.get() ? m_Renderer->ProcessState() : eProcessState::NONE; }
//Non-templated members.
bool m_Rendering;
@ -473,13 +473,13 @@ private:
QString MakeXformCaption(size_t i);
bool XformCheckboxAt(int i, std::function<void(QCheckBox*)> func);
bool XformCheckboxAt(Xform<T>* xform, std::function<void(QCheckBox*)> func);
void UpdateXform(std::function<void(Xform<T>*)> func, eXformUpdate updateType = eXformUpdate::UPDATE_CURRENT, bool updateRender = true, eProcessAction action = FULL_RENDER);
void UpdateXform(std::function<void(Xform<T>*)> func, eXformUpdate updateType = eXformUpdate::UPDATE_CURRENT, bool updateRender = true, eProcessAction action = eProcessAction::FULL_RENDER);
//Palette.
void UpdateAdjustedPaletteGUI(Palette<T>& palette);
//Rendering/progress.
void Update(std::function<void (void)> func, bool updateRender = true, eProcessAction action = FULL_RENDER);
void Update(std::function<void (void)> func, bool updateRender = true, eProcessAction action = eProcessAction::FULL_RENDER);
bool SyncSizes();
//Templated members.

View File

@ -37,7 +37,7 @@ void Fractorium::InitParamsUI()
comboVals.push_back("Step");
comboVals.push_back("Linear");
SetupCombo(table, this, row, 1, m_PaletteModeCombo, comboVals, SIGNAL(currentIndexChanged(int)), SLOT(OnPaletteModeComboCurrentIndexChanged(int)));
m_PaletteModeCombo->SetCurrentIndexStealth(PALETTE_LINEAR);
m_PaletteModeCombo->SetCurrentIndexStealth(int(ePaletteMode::PALETTE_LINEAR));
//Geometry.
row = 0;
table = ui.GeometryTable;
@ -100,7 +100,7 @@ void Fractorium::InitParamsUI()
/// </summary>
/// <param name="d">The brightness</param>
template <typename T>
void FractoriumEmberController<T>::BrightnessChanged(double d) { Update([&] { m_Ember.m_Brightness = d; }, true, FILTER_AND_ACCUM); }
void FractoriumEmberController<T>::BrightnessChanged(double d) { Update([&] { m_Ember.m_Brightness = d; }, true, eProcessAction::FILTER_AND_ACCUM); }
void Fractorium::OnBrightnessChanged(double d) { m_Controller->BrightnessChanged(d); }
/// <summary>
@ -110,7 +110,7 @@ void Fractorium::OnBrightnessChanged(double d) { m_Controller->BrightnessChanged
/// else if early clip is true, filter and accum, else final accum only.
/// </summary>
/// <param name="d">The gamma value</param>
template <typename T> void FractoriumEmberController<T>::GammaChanged(double d) { Update([&] { m_Ember.m_Gamma = d; }, true, m_Ember.m_TemporalSamples > 1 ? FULL_RENDER : (m_Renderer->EarlyClip() ? FILTER_AND_ACCUM : ACCUM_ONLY)); }
template <typename T> void FractoriumEmberController<T>::GammaChanged(double d) { Update([&] { m_Ember.m_Gamma = d; }, true, m_Ember.m_TemporalSamples > 1 ? eProcessAction::FULL_RENDER : (m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY)); }
void Fractorium::OnGammaChanged(double d) { m_Controller->GammaChanged(d); }
/// <summary>
@ -119,7 +119,7 @@ void Fractorium::OnGammaChanged(double d) { m_Controller->GammaChanged(d); }
/// Resets the rendering process to the final accumulation stage.
/// </summary>
/// <param name="d">The gamma threshold</param>
template <typename T> void FractoriumEmberController<T>::GammaThresholdChanged(double d) { Update([&] { m_Ember.m_GammaThresh = d; }, true, m_Ember.m_TemporalSamples > 1 ? FULL_RENDER : (m_Renderer->EarlyClip() ? FILTER_AND_ACCUM : ACCUM_ONLY)); }
template <typename T> void FractoriumEmberController<T>::GammaThresholdChanged(double d) { Update([&] { m_Ember.m_GammaThresh = d; }, true, m_Ember.m_TemporalSamples > 1 ? eProcessAction::FULL_RENDER : (m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY)); }
void Fractorium::OnGammaThresholdChanged(double d) { m_Controller->GammaThresholdChanged(d); }
/// <summary>
@ -128,7 +128,7 @@ void Fractorium::OnGammaThresholdChanged(double d) { m_Controller->GammaThreshol
/// Resets the rendering process to the final accumulation stage if temporal samples is 1, else full reset.
/// </summary>
/// <param name="d">The vibrancy</param>
template <typename T> void FractoriumEmberController<T>::VibrancyChanged(double d) { Update([&] { m_Ember.m_Vibrancy = d; }, true, m_Ember.m_TemporalSamples > 1 ? FULL_RENDER : (m_Renderer->EarlyClip() ? FILTER_AND_ACCUM : ACCUM_ONLY)); }
template <typename T> void FractoriumEmberController<T>::VibrancyChanged(double d) { Update([&] { m_Ember.m_Vibrancy = d; }, true, m_Ember.m_TemporalSamples > 1 ? eProcessAction::FULL_RENDER : (m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY)); }
void Fractorium::OnVibrancyChanged(double d) { m_Controller->VibrancyChanged(d); }
/// <summary>
@ -137,7 +137,7 @@ void Fractorium::OnVibrancyChanged(double d) { m_Controller->VibrancyChanged(d);
/// Resets the rendering process to the final accumulation stage.
/// </summary>
/// <param name="d">The highlight power</param>
template <typename T> void FractoriumEmberController<T>::HighlightPowerChanged(double d) { Update([&] { m_Ember.m_HighlightPower = d; }, true, m_Ember.m_TemporalSamples > 1 ? FULL_RENDER : (m_Renderer->EarlyClip() ? FILTER_AND_ACCUM : ACCUM_ONLY)); }
template <typename T> void FractoriumEmberController<T>::HighlightPowerChanged(double d) { Update([&] { m_Ember.m_HighlightPower = d; }, true, m_Ember.m_TemporalSamples > 1 ? eProcessAction::FULL_RENDER : (m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY)); }
void Fractorium::OnHighlightPowerChanged(double d) { m_Controller->HighlightPowerChanged(d); }
/// <summary>
@ -188,7 +188,7 @@ void Fractorium::OnColorSelected(const QColor& color) { m_Controller->Background
/// Resets the rendering process.
/// </summary>
/// <param name="index">The index of the palette mode combo box</param>
template <typename T> void FractoriumEmberController<T>::PaletteModeChanged(uint i) { Update([&] { m_Ember.m_PaletteMode = i == 0 ? PALETTE_STEP : PALETTE_LINEAR; }); }
template <typename T> void FractoriumEmberController<T>::PaletteModeChanged(uint i) { Update([&] { m_Ember.m_PaletteMode = i == 0 ? ePaletteMode::PALETTE_STEP : ePaletteMode::PALETTE_LINEAR; }); }
void Fractorium::OnPaletteModeComboCurrentIndexChanged(int index) { m_Controller->PaletteModeChanged(index); }
/// <summary>
@ -302,7 +302,7 @@ void Fractorium::OnSpatialFilterTypeComboCurrentIndexChanged(const QString& text
/// In the future, when animation is implemented, this will have an effect.
/// </summary>
/// <param name="d">The temporal filter width</param>
template <typename T> void FractoriumEmberController<T>::TemporalFilterWidthChanged(double d) { Update([&] { m_Ember.m_TemporalFilterWidth = d; }, true, NOTHING); }//Don't do anything until animation is implemented.
template <typename T> void FractoriumEmberController<T>::TemporalFilterWidthChanged(double d) { Update([&] { m_Ember.m_TemporalFilterWidth = d; }, true, eProcessAction::NOTHING); }//Don't do anything until animation is implemented.
void Fractorium::OnTemporalFilterWidthChanged(double d) { m_Controller->TemporalFilterWidthChanged(d); }
/// <summary>
@ -312,7 +312,7 @@ void Fractorium::OnTemporalFilterWidthChanged(double d) { m_Controller->Temporal
/// In the future, when animation is implemented, this will have an effect.
/// </summary>
/// <param name="text">The name of the temporal filter</param>
template <typename T> void FractoriumEmberController<T>::TemporalFilterTypeChanged(const QString& text) { Update([&] { m_Ember.m_TemporalFilterType = TemporalFilterCreator<T>::FromString(text.toStdString()); }, true, NOTHING); }//Don't do anything until animation is implemented.
template <typename T> void FractoriumEmberController<T>::TemporalFilterTypeChanged(const QString& text) { Update([&] { m_Ember.m_TemporalFilterType = TemporalFilterCreator<T>::FromString(text.toStdString()); }, true, eProcessAction::NOTHING); }//Don't do anything until animation is implemented.
void Fractorium::OnTemporalFilterTypeComboCurrentIndexChanged(const QString& text) { m_Controller->TemporalFilterTypeChanged(text); }
/// <summary>
@ -399,7 +399,7 @@ void Fractorium::OnFuseChanged(int d) { m_Controller->FuseChanged(d); }
/// the rendering process is continued, else it's reset.
/// </summary>
/// <param name="d">The quality in terms of iterations per pixel</param>
template <typename T> void FractoriumEmberController<T>::QualityChanged(double d) { /*Update([&] { m_Ember.m_Quality = d; }, true, d > m_Ember.m_Quality ? KEEP_ITERATING : FULL_RENDER);*/ }
template <typename T> void FractoriumEmberController<T>::QualityChanged(double d) { /*Update([&] { m_Ember.m_Quality = d; }, true, d > m_Ember.m_Quality ? KEEP_ITERATING : eProcessAction::FULL_RENDER);*/ }
void Fractorium::OnQualityChanged(double d) { /*m_Controller->QualityChanged(d);*/ }
/// <summary>
@ -423,7 +423,7 @@ void Fractorium::OnSupersampleChanged(int d) { m_Controller->SupersampleChanged(
/// In the future, when animation is implemented, this will have an effect.
/// </summary>
/// <param name="d">The temporal samples value</param>
template <typename T> void FractoriumEmberController<T>::TemporalSamplesChanged(int i) { Update([&] { m_Ember.m_TemporalSamples = i; }, true, NOTHING); }//Don't do anything until animation is implemented.
template <typename T> void FractoriumEmberController<T>::TemporalSamplesChanged(int i) { Update([&] { m_Ember.m_TemporalSamples = i; }, true, eProcessAction::NOTHING); }//Don't do anything until animation is implemented.
void Fractorium::OnTemporalSamplesChanged(int d) { m_Controller->TemporalSamplesChanged(d); }
/// <summary>
@ -439,12 +439,12 @@ void FractoriumEmberController<T>::AffineInterpTypeChanged(int i)
Update([&]
{
if (i == 0)
m_Ember.m_AffineInterp = AFFINE_INTERP_LINEAR;
m_Ember.m_AffineInterp = eAffineInterp::AFFINE_INTERP_LINEAR;
else if (i == 1)
m_Ember.m_AffineInterp = AFFINE_INTERP_LOG;
m_Ember.m_AffineInterp = eAffineInterp::AFFINE_INTERP_LOG;
else
m_Ember.m_AffineInterp = AFFINE_INTERP_LINEAR;
}, true, NOTHING);
m_Ember.m_AffineInterp = eAffineInterp::AFFINE_INTERP_LINEAR;
}, true, eProcessAction::NOTHING);
}
void Fractorium::OnAffineInterpTypeComboCurrentIndexChanged(int index) { m_Controller->AffineInterpTypeChanged(index); }
@ -462,12 +462,12 @@ void FractoriumEmberController<T>::InterpTypeChanged(int i)
Update([&]
{
if (i == 0)
m_Ember.m_Interp = EMBER_INTERP_LINEAR;
m_Ember.m_Interp = eInterp::EMBER_INTERP_LINEAR;
else if (i == 1)
m_Ember.m_Interp = EMBER_INTERP_SMOOTH;
m_Ember.m_Interp = eInterp::EMBER_INTERP_SMOOTH;
else
m_Ember.m_Interp = EMBER_INTERP_LINEAR;
}, true, NOTHING);
m_Ember.m_Interp = eInterp::EMBER_INTERP_LINEAR;
}, true, eProcessAction::NOTHING);
}
void Fractorium::OnInterpTypeComboCurrentIndexChanged(int index) { m_Controller->InterpTypeChanged(index); }
@ -530,8 +530,8 @@ void FractoriumEmberController<T>::FillParamTablesAndPalette()
m_Fractorium->m_QualitySpin->SetValueStealth(m_Ember.m_Quality);
m_Fractorium->m_SupersampleSpin->SetValueStealth(m_Ember.m_Supersample);
m_Fractorium->m_TemporalSamplesSpin->SetValueStealth(m_Ember.m_TemporalSamples);
m_Fractorium->m_AffineInterpTypeCombo->SetCurrentIndexStealth(m_Ember.m_AffineInterp);
m_Fractorium->m_InterpTypeCombo->SetCurrentIndexStealth(m_Ember.m_Interp);
m_Fractorium->m_AffineInterpTypeCombo->SetCurrentIndexStealth(int(m_Ember.m_AffineInterp));
m_Fractorium->m_InterpTypeCombo->SetCurrentIndexStealth(int(m_Ember.m_Interp));
//Palette related items:
//The temp palette is assigned the palette read when the file was parsed/saved. The user can apply adjustments on the GUI later.
//These adjustments will be applied to the temp palette, then assigned back to m_Ember.m_Palette.

View File

@ -201,7 +201,7 @@ void FractoriumEmberControllerBase::AddProcessAction(eProcessAction action)
eProcessAction FractoriumEmberControllerBase::CondenseAndClearProcessActions()
{
m_Cs.Enter();
eProcessAction action = NOTHING;
auto action = eProcessAction::NOTHING;
for (auto a : m_ProcessActions)
if (a > action)
@ -310,7 +310,7 @@ bool FractoriumEmberController<T>::Render()
m_Ember.m_Quality = d;
qualityAction = eProcessAction::FULL_RENDER;
}
else if (d > m_Ember.m_Quality && ProcessState() == ACCUM_DONE)//If quality increased, keep iterating after current render finishes.
else if (d > m_Ember.m_Quality && ProcessState() == eProcessState::ACCUM_DONE)//If quality increased, keep iterating after current render finishes.
{
m_Ember.m_Quality = d;
qualityAction = eProcessAction::KEEP_ITERATING;
@ -332,7 +332,7 @@ bool FractoriumEmberController<T>::Render()
m_Ember.m_TemporalSamples = 1;
//Take care of solo xforms and set the current ember and action.
if (action != NOTHING)
if (action != eProcessAction::NOTHING)
{
int i, solo = m_Fractorium->ui.CurrentXformCombo->property("soloxform").toInt();
@ -361,12 +361,12 @@ bool FractoriumEmberController<T>::Render()
//Ensure sizes are equal and if not, update dimensions.
if (SyncSizes())
{
action = FULL_RENDER;
action = eProcessAction::FULL_RENDER;
return true;
}
//Determining if a completely new rendering process is being started.
bool iterBegin = ProcessState() == NONE;
bool iterBegin = ProcessState() == eProcessState::NONE;
if (iterBegin)
{
@ -380,10 +380,10 @@ bool FractoriumEmberController<T>::Render()
}
//If the rendering process hasn't finished, render with the current specified action.
if (ProcessState() != ACCUM_DONE)
if (ProcessState() != eProcessState::ACCUM_DONE)
{
//if (m_Renderer->Run(m_FinalImage, 0) == RENDER_OK)//Full, non-incremental render for debugging.
if (m_Renderer->Run(m_FinalImage, 0, m_SubBatchCount, (iterBegin || m_Fractorium->m_Settings->ContinuousUpdate())) == RENDER_OK)//Force output on iterBegin or if the settings specify to always do it.
if (m_Renderer->Run(m_FinalImage, 0, m_SubBatchCount, (iterBegin || m_Fractorium->m_Settings->ContinuousUpdate())) == eRenderStatus::RENDER_OK)//Force output on iterBegin or if the settings specify to always do it.
{
//The amount to increment sub batch while rendering proceeds is purely empirical.
//Change later if better values can be derived/observed.
@ -401,7 +401,7 @@ bool FractoriumEmberController<T>::Render()
}
//Rendering has finished, update final stats.
if (ProcessState() == ACCUM_DONE)
if (ProcessState() == eProcessState::ACCUM_DONE)
{
EmberStats stats = m_Renderer->Stats();
QString iters = ToString<qulonglong>(stats.m_Iters);
@ -454,7 +454,7 @@ bool FractoriumEmberController<T>::Render()
//Update the GL window on start because the output will be forced.
//Update it on finish because the rendering process is completely done.
if (iterBegin || ProcessState() == ACCUM_DONE)
if (iterBegin || ProcessState() == eProcessState::ACCUM_DONE)
{
if (m_FinalImage.size() == m_Renderer->FinalBufferSize())//Make absolutely sure the correct amount of data is passed.
gl->update();
@ -500,7 +500,7 @@ bool FractoriumEmberController<T>::Render()
}
//Upon finishing, or having nothing to do, rest.
if (ProcessState() == ACCUM_DONE)
if (ProcessState() == eProcessState::ACCUM_DONE)
QThread::msleep(1);
//QApplication::processEvents();
@ -578,10 +578,10 @@ bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, cons
m_Renderer->ThreadCount(s->ThreadCount());
m_Renderer->Transparency(s->Transparency());
if (m_Renderer->RendererType() == CPU_RENDERER)
m_Renderer->InteractiveFilter(s->CpuDEFilter() ? FILTER_DE : FILTER_LOG);
if (m_Renderer->RendererType() == eRendererType::CPU_RENDERER)
m_Renderer->InteractiveFilter(s->CpuDEFilter() ? eInteractiveFilter::FILTER_DE : eInteractiveFilter::FILTER_LOG);
else
m_Renderer->InteractiveFilter(s->OpenCLDEFilter() ? FILTER_DE : FILTER_LOG);
m_Renderer->InteractiveFilter(s->OpenCLDEFilter() ? eInteractiveFilter::FILTER_DE : eInteractiveFilter::FILTER_LOG);
if ((m_Renderer->EarlyClip() != m_PreviewRenderer->EarlyClip()) ||
(m_Renderer->YAxisUp() != m_PreviewRenderer->YAxisUp()))

View File

@ -45,12 +45,11 @@ void FractoriumSettings::EnsureDefaults()
FinalThreadCount(Timing::ProcessorCount());
FinalThreadPriority(Clamp<int>(FinalThreadPriority(), (int)eThreadPriority::LOWEST, (int)eThreadPriority::HIGHEST));
CpuSubBatch(std::max(1u, CpuSubBatch()));
OpenCLSubBatch(std::max(1u, OpenCLSubBatch()));
RandomCount(std::max(1u, RandomCount()));
if (FinalScale() > SCALE_HEIGHT)
if (FinalScale() > int(eScaleType::SCALE_HEIGHT))
FinalScale(0);
if (OpenXmlExt() == "")
@ -86,22 +85,22 @@ void FractoriumSettings::EnsureDefaults()
bool FractoriumSettings::EarlyClip() { return value(EARLYCLIP).toBool(); }
void FractoriumSettings::EarlyClip(bool b) { setValue(EARLYCLIP, b); }
bool FractoriumSettings::YAxisUp() { return value(YAXISUP).toBool(); }
void FractoriumSettings::YAxisUp(bool b) { setValue(YAXISUP, b); }
bool FractoriumSettings::Transparency() { return value(TRANSPARENCY).toBool(); }
void FractoriumSettings::Transparency(bool b) { setValue(TRANSPARENCY, b); }
bool FractoriumSettings::OpenCL() { return value(OPENCL).toBool(); }
void FractoriumSettings::OpenCL(bool b) { setValue(OPENCL, b); }
bool FractoriumSettings::Double() { return value(DOUBLEPRECISION).toBool(); }
void FractoriumSettings::Double(bool b) { setValue(DOUBLEPRECISION, b); }
bool FractoriumSettings::ShowAllXforms() { return value(SHOWALLXFORMS).toBool(); }
void FractoriumSettings::ShowAllXforms(bool b) { setValue(SHOWALLXFORMS, b); }
bool FractoriumSettings::ContinuousUpdate() { return value(CONTUPDATE).toBool(); }
void FractoriumSettings::ContinuousUpdate(bool b) { setValue(CONTUPDATE, b); }
@ -110,19 +109,19 @@ void FractoriumSettings::Devices(const QList<QVariant>& devices) { setValue(DEVI
uint FractoriumSettings::ThreadCount() { return value(THREADCOUNT).toUInt(); }
void FractoriumSettings::ThreadCount(uint i) { setValue(THREADCOUNT, i); }
bool FractoriumSettings::CpuDEFilter() { return value(CPUDEFILTER).toBool(); }
void FractoriumSettings::CpuDEFilter(bool b) { setValue(CPUDEFILTER, b); }
bool FractoriumSettings::OpenCLDEFilter() { return value(OPENCLDEFILTER).toBool(); }
void FractoriumSettings::OpenCLDEFilter(bool b) { setValue(OPENCLDEFILTER, b); }
uint FractoriumSettings::CpuSubBatch() { return value(CPUSUBBATCH).toUInt(); }
void FractoriumSettings::CpuSubBatch(uint i) { setValue(CPUSUBBATCH, i); }
uint FractoriumSettings::OpenCLSubBatch() { return value(OPENCLSUBBATCH).toUInt(); }
void FractoriumSettings::OpenCLSubBatch(uint i) { setValue(OPENCLSUBBATCH, i); }
uint FractoriumSettings::RandomCount() { return value(RANDOMCOUNT).toUInt(); }
void FractoriumSettings::RandomCount(uint i) { setValue(RANDOMCOUNT, i); }
@ -132,77 +131,77 @@ void FractoriumSettings::RandomCount(uint i) { setValue(RANDOMCOUNT, i);
bool FractoriumSettings::FinalEarlyClip() { return value(FINALEARLYCLIP).toBool(); }
void FractoriumSettings::FinalEarlyClip(bool b) { setValue(FINALEARLYCLIP, b); }
bool FractoriumSettings::FinalYAxisUp() { return value(FINALYAXISUP).toBool(); }
void FractoriumSettings::FinalYAxisUp(bool b) { setValue(FINALYAXISUP, b); }
bool FractoriumSettings::FinalTransparency() { return value(FINALTRANSPARENCY).toBool(); }
void FractoriumSettings::FinalTransparency(bool b) { setValue(FINALTRANSPARENCY, b); }
bool FractoriumSettings::FinalOpenCL() { return value(FINALOPENCL).toBool(); }
void FractoriumSettings::FinalOpenCL(bool b) { setValue(FINALOPENCL, b); }
bool FractoriumSettings::FinalDouble() { return value(FINALDOUBLEPRECISION).toBool(); }
void FractoriumSettings::FinalDouble(bool b) { setValue(FINALDOUBLEPRECISION, b); }
bool FractoriumSettings::FinalSaveXml() { return value(FINALSAVEXML).toBool(); }
void FractoriumSettings::FinalSaveXml(bool b) { setValue(FINALSAVEXML, b); }
bool FractoriumSettings::FinalDoAll() { return value(FINALDOALL).toBool(); }
void FractoriumSettings::FinalDoAll(bool b) { setValue(FINALDOALL, b); }
bool FractoriumSettings::FinalDoSequence() { return value(FINALDOSEQUENCE).toBool(); }
void FractoriumSettings::FinalDoSequence(bool b) { setValue(FINALDOSEQUENCE, b); }
bool FractoriumSettings::FinalKeepAspect() { return value(FINALKEEPASPECT).toBool(); }
void FractoriumSettings::FinalKeepAspect(bool b) { setValue(FINALKEEPASPECT, b); }
uint FractoriumSettings::FinalScale() { return value(FINALSCALE).toUInt(); }
void FractoriumSettings::FinalScale(uint i) { setValue(FINALSCALE, i); }
QString FractoriumSettings::FinalExt() { return value(FINALEXT).toString(); }
void FractoriumSettings::FinalExt(const QString& s) { setValue(FINALEXT, s); }
QList<QVariant> FractoriumSettings::FinalDevices() { return value(FINALDEVICES).toList(); }
void FractoriumSettings::FinalDevices(const QList<QVariant>& devices) { setValue(FINALDEVICES, devices); }
uint FractoriumSettings::FinalThreadCount() { return value(FINALTHREADCOUNT).toUInt(); }
void FractoriumSettings::FinalThreadCount(uint i) { setValue(FINALTHREADCOUNT, i); }
int FractoriumSettings::FinalThreadPriority() { return value(FINALTHREADPRIORITY).toInt(); }
void FractoriumSettings::FinalThreadPriority(int i) { setValue(FINALTHREADPRIORITY, i); }
uint FractoriumSettings::FinalQuality() { return value(FINALQUALITY).toUInt(); }
void FractoriumSettings::FinalQuality(uint i) { setValue(FINALQUALITY, i); }
uint FractoriumSettings::FinalTemporalSamples() { return value(FINALTEMPORALSAMPLES).toUInt(); }
void FractoriumSettings::FinalTemporalSamples(uint i) { setValue(FINALTEMPORALSAMPLES, i); }
uint FractoriumSettings::FinalSupersample() { return value(FINALSUPERSAMPLE).toUInt(); }
void FractoriumSettings::FinalSupersample(uint i) { setValue(FINALSUPERSAMPLE, i); }
uint FractoriumSettings::FinalStrips() { return value(FINALSTRIPS).toUInt(); }
void FractoriumSettings::FinalStrips(uint i) { setValue(FINALSTRIPS, i); }
/// <summary>
/// Xml file saving settings.
/// </summary>
uint FractoriumSettings::XmlTemporalSamples() { return value(XMLTEMPORALSAMPLES).toUInt(); }
void FractoriumSettings::XmlTemporalSamples(uint i) { setValue(XMLTEMPORALSAMPLES, i); }
uint FractoriumSettings::XmlQuality() { return value(XMLQUALITY).toUInt(); }
void FractoriumSettings::XmlQuality(uint i) { setValue(XMLQUALITY, i); }
uint FractoriumSettings::XmlSupersample() { return value(XMLSUPERSAMPLE).toUInt(); }
void FractoriumSettings::XmlSupersample(uint i) { setValue(XMLSUPERSAMPLE, i); }
QString FractoriumSettings::Id() { return value(IDENTITYID).toString(); }
void FractoriumSettings::Id(const QString& s) { setValue(IDENTITYID, s); }
QString FractoriumSettings::Url() { return value(IDENTITYURL).toString(); }
void FractoriumSettings::Url(const QString& s) { setValue(IDENTITYURL, s); }
QString FractoriumSettings::Nick() { return value(IDENTITYNICK).toString(); }
void FractoriumSettings::Nick(const QString& s) { setValue(IDENTITYNICK, s); }
@ -212,19 +211,19 @@ void FractoriumSettings::Nick(const QString& s) { setValue(IDENTITYNICK, s);
QString FractoriumSettings::OpenFolder() { return value(OPENFOLDER).toString(); }
void FractoriumSettings::OpenFolder(const QString& s) { setValue(OPENFOLDER, s); }
QString FractoriumSettings::SaveFolder() { return value(SAVEFOLDER).toString(); }
void FractoriumSettings::SaveFolder(const QString& s) { setValue(SAVEFOLDER, s); }
QString FractoriumSettings::OpenXmlExt() { return value(OPENXMLEXT).toString(); }
void FractoriumSettings::OpenXmlExt(const QString& s) { setValue(OPENXMLEXT, s); }
QString FractoriumSettings::SaveXmlExt() { return value(SAVEXMLEXT).toString(); }
void FractoriumSettings::SaveXmlExt(const QString& s) { setValue(SAVEXMLEXT, s); }
QString FractoriumSettings::OpenImageExt() { return value(OPENIMAGEEXT).toString(); }
void FractoriumSettings::OpenImageExt(const QString& s) { setValue(OPENIMAGEEXT, s); }
QString FractoriumSettings::SaveImageExt() { return value(SAVEIMAGEEXT).toString(); }
void FractoriumSettings::SaveImageExt(const QString& s) { setValue(SAVEIMAGEEXT, s); }

View File

@ -7,27 +7,22 @@
void Fractorium::InitXformsColorUI()
{
int spinHeight = 20, row = 0;
m_XformColorValueItem = new QTableWidgetItem();
ui.XformColorIndexTable->setItem(0, 0, m_XformColorValueItem);
m_PaletteRefItem = new QTableWidgetItem();
ui.XformPaletteRefTable->setItem(0, 0, m_PaletteRefItem);
ui.XformPaletteRefTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
connect(ui.XformPaletteRefTable->horizontalHeader(), SIGNAL(sectionResized(int, int, int)), this, SLOT(OnXformRefPaletteResized(int, int, int)), Qt::QueuedConnection);
SetupSpinner<DoubleSpinBox, double>(ui.XformColorIndexTable, this, row, 1, m_XformColorIndexSpin, spinHeight, 0, 1, 0.01, SIGNAL(valueChanged(double)), SLOT(OnXformColorIndexChanged(double)), false, 0, 1, 0);
SetupSpinner<DoubleSpinBox, double>(ui.XformColorValuesTable, this, row, 1, m_XformColorSpeedSpin, spinHeight, -1, 1, 0.1, SIGNAL(valueChanged(double)), SLOT(OnXformColorSpeedChanged(double)), true, 0.5, 0.5, 0.5);
SetupSpinner<DoubleSpinBox, double>(ui.XformColorValuesTable, this, row, 1, m_XformOpacitySpin, spinHeight, 0, 1, 0.1, SIGNAL(valueChanged(double)), SLOT(OnXformOpacityChanged(double)), true, 1, 1, 0);
SetupSpinner<DoubleSpinBox, double>(ui.XformColorValuesTable, this, row, 1, m_XformDirectColorSpin, spinHeight, 0, 1, 0.1, SIGNAL(valueChanged(double)), SLOT(OnXformDirectColorChanged(double)), true, 1, 1, 0);
m_XformColorIndexSpin->setDecimals(3);
m_XformColorSpeedSpin->setDecimals(3);
m_XformOpacitySpin->setDecimals(3);
m_XformDirectColorSpin->setDecimals(3);
connect(ui.XformColorScroll, SIGNAL(valueChanged(int)), this, SLOT(OnXformScrollColorIndexChanged(int)), Qt::QueuedConnection);
connect(ui.SoloXformCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnSoloXformCheckBoxStateChanged(int)), Qt::QueuedConnection);
connect(ui.ResetCurvesButton, SIGNAL(clicked(bool)), this, SLOT(OnResetCurvesButtonClicked(bool)), Qt::QueuedConnection);
connect(ui.CurvesView, SIGNAL(PointChangedSignal(int, int, const QPointF&)), this, SLOT(OnCurvesPointChanged(int, int, const QPointF&)), Qt::QueuedConnection);
connect(ui.CurvesAllRadio, SIGNAL(toggled(bool)), this, SLOT(OnCurvesAllRadioButtonToggled(bool)), Qt::QueuedConnection);
@ -49,11 +44,9 @@ void FractoriumEmberController<T>::XformColorIndexChanged(double d, bool updateR
{
auto scroll = m_Fractorium->ui.XformColorScroll;
int scrollVal = d * scroll->maximum();
scroll->blockSignals(true);
scroll->setValue(scrollVal);
scroll->blockSignals(false);
SetCurrentXformColorIndex(d, updateRender);
}
@ -143,7 +136,6 @@ void Fractorium::OnSoloXformCheckBoxStateChanged(int state)
void Fractorium::OnXformRefPaletteResized(int logicalIndex, int oldSize, int newSize)
{
QPixmap pixmap = QPixmap::fromImage(m_Controller->FinalPaletteImage());
SetPaletteTableItem(&pixmap, ui.XformPaletteRefTable, m_PaletteRefItem, 0, 0);
}
@ -158,8 +150,7 @@ void FractoriumEmberController<T>::ClearColorCurves()
Update([&]
{
m_Ember.m_Curves.Init();
}, true, m_Renderer->EarlyClip() ? FILTER_AND_ACCUM : ACCUM_ONLY);
}, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY);
FillCurvesControl();
}
@ -180,7 +171,7 @@ void FractoriumEmberController<T>::ColorCurveChanged(int curveIndex, int pointIn
{
m_Ember.m_Curves.m_Points[curveIndex][pointIndex].x = point.x();
m_Ember.m_Curves.m_Points[curveIndex][pointIndex].y = point.y();
}, true, m_Renderer->EarlyClip() ? FILTER_AND_ACCUM : ACCUM_ONLY);
}, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY);
}
void Fractorium::OnCurvesPointChanged(int curveIndex, int pointIndex, const QPointF& point) { m_Controller->ColorCurveChanged(curveIndex, pointIndex, point); }
@ -206,11 +197,9 @@ template <typename T>
QColor FractoriumEmberController<T>::ColorIndexToQColor(double d)
{
v4T entry = m_Ember.m_Palette[Clamp<int>(d * COLORMAP_LENGTH_MINUS_1, 0, m_Ember.m_Palette.Size())];
entry.r *= 255;
entry.g *= 255;
entry.b *= 255;
QRgb rgb = uint(entry.r) << 16 | uint(entry.g) << 8 | uint(entry.b);
return QColor::fromRgb(rgb);
}
@ -226,7 +215,6 @@ void FractoriumEmberController<T>::SetCurrentXformColorIndex(double d, bool upda
UpdateXform([&] (Xform<T>* xform)
{
xform->m_ColorX = Clamp<T>(d, 0, 1);
//Grab the current color from the index and assign it to the first cell of the first table.
m_Fractorium->ui.XformColorIndexTable->item(0, 0)->setBackgroundColor(ColorIndexToQColor(xform->m_ColorX)/*QColor::fromRgb(rgb)*/);
}, eXformUpdate::UPDATE_SELECTED, updateRender);
@ -245,7 +233,6 @@ void FractoriumEmberController<T>::FillCurvesControl()
for (size_t j = 1; j < 3; j++)//Only do middle points.
{
QPointF point(m_Ember.m_Curves.m_Points[i][j].x, m_Ember.m_Curves.m_Points[i][j].y);
m_Fractorium->ui.CurvesView->Set(i, j, point);
}
}
@ -290,5 +277,5 @@ void Fractorium::SetPaletteTableItem(QPixmap* pixmap, QTableWidget* table, QTabl
template class FractoriumEmberController<float>;
#ifdef DO_DOUBLE
template class FractoriumEmberController<double>;
template class FractoriumEmberController<double>;
#endif