mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-06-30 21:36:33 -04:00
--User changes
-Remove the option --intpalette to format the palette in the xml as ints. If they are not hex formatted, then they should always be float. This option was pointless. -Cleanup some options text for the command line programs. -Allow for dragging around flames in the library tab. This is useful for setting up the order of an animation. -Make the opening of large files in Fractorium much more efficient when not-appending. -Make the opening of large files in all EmberRender and EmberAnimate more efficient. -Better error reporting when opening files. --Bug fixes -Get rid of leftover artifacts that would appear on preview thumbnails when either switching SP/DP or re-rendering previews. -Filename extension was not being appended on Linux when saving as Xml, thus making it impossible to drag that file back in becase drop is filtered on extension. --Code changes -Move GCC compiler spec to C++14. Building with 5.3 now on linux. -Use inline member data initializers. -Make a #define for static for use in Utils.h to make things a little cleaner. -Make various functions able to take arbitrary collections as their parameters rather than just vectors. -Make library collection a list rather than vector. This alleviates the need to re-sync pointers whenever the collection changes. -Subclass QTreeWidget for the library tree. Two new files added for this. -Remove all usage of #ifdef ROW_ONLY_DE in DEOpenCLKernelCreator, it was never used. -Add move constructor and assignment operator to EmberFile. -Add the ability to use a pointer to outside memory in the renderer for the vector of Ember<T>. -Make a lot more functions const where they should be.
This commit is contained in:
@ -25,9 +25,7 @@ public:
|
||||
/// <summary>
|
||||
/// Empty constructor. This class should never be used unless it's been properly constructed with the constructor that takes arguments.
|
||||
/// </summary>
|
||||
CarToRas()
|
||||
{
|
||||
}
|
||||
CarToRas() = default;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor that takes arguments to set up the bounds and passes them to Init().
|
||||
|
@ -44,9 +44,12 @@ public:
|
||||
/// Default constructor which calls Init() to set default values.
|
||||
/// </summary>
|
||||
Ember()
|
||||
: m_VariationList(VariationList<T>::Instance())
|
||||
{
|
||||
Init();
|
||||
m_Background.Reset();
|
||||
m_Curves.Init();
|
||||
m_Xforms.reserve(12);
|
||||
m_CamMat = m3T(0);
|
||||
m_ProjFunc = &EmberNs::Ember<T>::ProjectNone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -54,8 +57,6 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="ember">The Ember object to copy</param>
|
||||
Ember(const Ember<T>& ember)
|
||||
: m_Edits(nullptr),
|
||||
m_VariationList(VariationList<T>::Instance())
|
||||
{
|
||||
Ember<T>::operator=<T>(ember);
|
||||
}
|
||||
@ -66,8 +67,6 @@ public:
|
||||
/// <param name="ember">The Ember object to copy</param>
|
||||
template <typename U>
|
||||
Ember(const Ember<U>& ember)
|
||||
: m_Edits(nullptr),
|
||||
m_VariationList(VariationList<T>::Instance())
|
||||
{
|
||||
Ember<T>::operator=<U>(ember);
|
||||
}
|
||||
@ -178,74 +177,10 @@ public:
|
||||
if (ember.m_Edits)
|
||||
m_Edits = xmlCopyDoc(ember.m_Edits, 1);
|
||||
|
||||
CopyVec(m_EmberMotionElements, ember.m_EmberMotionElements);
|
||||
CopyCont(m_EmberMotionElements, ember.m_EmberMotionElements);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set common default values.
|
||||
/// </summary>
|
||||
void Init()
|
||||
{
|
||||
m_FinalRasW = 1920;
|
||||
m_FinalRasH = 1080;
|
||||
m_OrigFinalRasW = 1920;
|
||||
m_OrigFinalRasH = 1080;
|
||||
m_OrigPixPerUnit = 240;
|
||||
m_SubBatchSize = DEFAULT_SBS;
|
||||
m_FuseCount = 15;
|
||||
m_Supersample = 1;
|
||||
m_TemporalSamples = 100;
|
||||
m_Symmetry = 0;
|
||||
m_Quality = 100;
|
||||
m_PixelsPerUnit = 240;
|
||||
m_Zoom = 0;
|
||||
m_ProjFunc = &EmberNs::Ember<T>::ProjectNone;
|
||||
m_CamZPos = 0;
|
||||
m_CamPerspective = 0;
|
||||
m_CamYaw = 0;
|
||||
m_CamPitch = 0;
|
||||
m_CamDepthBlur = 0;
|
||||
m_BlurCoef = 0;
|
||||
m_CamMat = m3T(0);
|
||||
m_CenterX = 0;
|
||||
m_CenterY = 0;
|
||||
m_RotCenterY = 0;
|
||||
m_Rotate = 0;
|
||||
m_Brightness = 4;
|
||||
m_Gamma = 4;
|
||||
m_Vibrancy = 1;
|
||||
m_GammaThresh = T(0.01);
|
||||
m_HighlightPower = -1;
|
||||
m_Time = 0;
|
||||
m_Background.Reset();
|
||||
m_Interp = eInterp::EMBER_INTERP_SMOOTH;
|
||||
m_AffineInterp = eAffineInterp::AFFINE_INTERP_LOG;
|
||||
//DE filter.
|
||||
m_MinRadDE = 0;
|
||||
m_MaxRadDE = 9;
|
||||
m_CurveDE = T(0.4);
|
||||
//Spatial filter.
|
||||
m_SpatialFilterType = eSpatialFilterType::GAUSSIAN_SPATIAL_FILTER;
|
||||
m_SpatialFilterRadius = T(0.5);
|
||||
//Temporal filter.
|
||||
m_TemporalFilterType = eTemporalFilterType::BOX_TEMPORAL_FILTER;
|
||||
m_TemporalFilterExp = 0;
|
||||
m_TemporalFilterWidth = 1;
|
||||
//Palette.
|
||||
m_PaletteMode = ePaletteMode::PALETTE_LINEAR;
|
||||
m_PaletteInterp = ePaletteInterp::INTERP_HSV;
|
||||
//Curves.
|
||||
m_Curves.Init();
|
||||
m_Name = "No name";
|
||||
m_ParentFilename = "No parent";
|
||||
//Internal values.
|
||||
m_Index = 0;
|
||||
m_ScaleType = eScaleType::SCALE_NONE;
|
||||
m_Xforms.reserve(12);
|
||||
m_Edits = nullptr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a copy of a new xform to the xforms vector.
|
||||
/// </summary>
|
||||
@ -286,7 +221,7 @@ public:
|
||||
/// <param name="xformPad">The total number of xforms if additional padding xforms are desired. Default: 0.</param>
|
||||
/// <param name="doFinal">Whether to copy the final xform. Default: false.</param>
|
||||
/// <returns>The newly constructed ember</returns>
|
||||
Ember<T> Copy(size_t xformPad = 0, bool doFinal = false)
|
||||
Ember<T> Copy(size_t xformPad = 0, bool doFinal = false) const
|
||||
{
|
||||
Ember<T> ember(*this);
|
||||
ember.PadXforms(xformPad);
|
||||
@ -443,7 +378,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="xform">A pointer to the xform to test</param>
|
||||
/// <returns>True if matched, else false.</returns>
|
||||
bool IsFinalXform(Xform<T>* xform)
|
||||
bool IsFinalXform(Xform<T>* xform) const
|
||||
{
|
||||
return &m_FinalXform == xform;
|
||||
}
|
||||
@ -695,7 +630,7 @@ public:
|
||||
/// <param name="embers">Vector of embers</param>
|
||||
/// <param name="coefs">Coefficients vector which must be the same length as the vector of embers</param>
|
||||
/// <param name="stagger">Stagger if greater than 0</param>
|
||||
void Interpolate(vector<Ember<T>>& embers, vector<T>& coefs, T stagger)
|
||||
void Interpolate(const vector<Ember<T>>& embers, vector<T>& coefs, T stagger)
|
||||
{
|
||||
Interpolate(embers.data(), embers.size(), coefs, stagger);
|
||||
}
|
||||
@ -708,7 +643,7 @@ public:
|
||||
/// <param name="size">Number of elements in the buffer of embers</param>
|
||||
/// <param name="coefs">Coefficients vector which must be the same length as the vector of embers</param>
|
||||
/// <param name="stagger">Stagger if greater than 0</param>
|
||||
void Interpolate(Ember<T>* embers, size_t size, vector<T>& coefs, T stagger)
|
||||
void Interpolate(const Ember<T>* embers, size_t size, vector<T>& coefs, T stagger)
|
||||
{
|
||||
if (size != coefs.size() || size < 2)
|
||||
return;
|
||||
@ -996,7 +931,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="embers">Vector of embers</param>
|
||||
/// <param name="t">Used in calculating Catmull-Rom coefficients</param>
|
||||
void InterpolateCatmullRom(vector<Ember<T>>& embers, T t)
|
||||
void InterpolateCatmullRom(const vector<Ember<T>>& embers, T t)
|
||||
{
|
||||
InterpolateCatmullRom(embers.data(), embers.size(), t);
|
||||
}
|
||||
@ -1008,7 +943,7 @@ public:
|
||||
/// <param name="embers">Pointer to buffer of embers</param>
|
||||
/// <param name="size">Number of elements in the buffer of embers</param>
|
||||
/// <param name="t">Used in calculating Catmull-Rom coefficients</param>
|
||||
void InterpolateCatmullRom(Ember<T>* embers, size_t size, T t)
|
||||
void InterpolateCatmullRom(const Ember<T>* embers, size_t size, T t)
|
||||
{
|
||||
T t2 = t * t;
|
||||
T t3 = t2 * t;
|
||||
@ -1537,50 +1472,50 @@ public:
|
||||
|
||||
//The width and height in pixels of the final output image. The size of the histogram and DE filtering buffers will differ from this.
|
||||
//Xml fields: "size".
|
||||
size_t m_FinalRasW;
|
||||
size_t m_FinalRasH;
|
||||
size_t m_OrigFinalRasW;//Keep track of the originals read from the Xml, because...
|
||||
size_t m_OrigFinalRasH;//the dimension may change in an editor and the originals are needed for the aspect ratio.
|
||||
T m_OrigPixPerUnit;
|
||||
size_t m_FinalRasW = 1920;
|
||||
size_t m_FinalRasH = 1080;
|
||||
size_t m_OrigFinalRasW = 1920;//Keep track of the originals read from the Xml, because...
|
||||
size_t m_OrigFinalRasH = 1080;//the dimension may change in an editor and the originals are needed for the aspect ratio.
|
||||
T m_OrigPixPerUnit = 240;
|
||||
|
||||
//The iteration depth. This was a rendering parameter in flam3 but has been made a member here
|
||||
//so that it can be adjusted more easily.
|
||||
size_t m_SubBatchSize;
|
||||
size_t m_SubBatchSize = DEFAULT_SBS;
|
||||
|
||||
//The number of iterations to disregard for each sub batch. This was a rendering parameter in flam3 but has been made a member here
|
||||
//so that it can be adjusted more easily.
|
||||
size_t m_FuseCount;
|
||||
size_t m_FuseCount = 15;
|
||||
|
||||
//The multiplier in size of the histogram and DE filtering buffers. Must be at least one, preferrably never larger than 4, only useful at 2.
|
||||
//Xml field: "supersample" or "overample (deprecated)".
|
||||
size_t m_Supersample;
|
||||
size_t m_Supersample = 1;
|
||||
|
||||
//When animating, split each pass into this many pieces, each doing a fraction of the total iterations. Each temporal sample
|
||||
//will render an interpolated instance of the ember that is a fraction of the current ember and the next one.
|
||||
//When rendering a single image, this field is always set to 1.
|
||||
//Xml field: "temporal_samples".
|
||||
size_t m_TemporalSamples;
|
||||
size_t m_TemporalSamples = 100;
|
||||
|
||||
//Whether or not any symmetry was added. This field is in a bit of a state of conflict right now as flam3 has a severe bug.
|
||||
//Xml field: "symmetry".
|
||||
intmax_t m_Symmetry;
|
||||
intmax_t m_Symmetry = 0;
|
||||
|
||||
//The number of iterations per pixel of the final output image. Note this is not affected by the increase in pixels in the
|
||||
//histogram and DE filtering buffer due to supersampling. It can be affected by a non-zero zoom value though.
|
||||
//10 is a good value for interactive/real-time rendering, 100-200 is good for previewing, 1000 is good for final output. Above that is mostly a waste of energy.
|
||||
//Xml field: "quality".
|
||||
T m_Quality;
|
||||
T m_Quality = 100;
|
||||
|
||||
//The number of pixels in the final output image that corresponds to the distance from 0-1 in the cartesian plane used for iterating.
|
||||
//A larger value produces a more zoomed in imgage. A value of 240 is commonly used, but in practice it varies widely depending on the image.
|
||||
//Note that increasing this value does not adjust the quality by a proportional amount, so an increased value may produce a degraded image.
|
||||
//Xml field: "scale".
|
||||
T m_PixelsPerUnit;
|
||||
T m_PixelsPerUnit = 240;
|
||||
|
||||
//A value greater than 0 will zoom in the field of view, however it will also increase the quality by a proportional amount. This is used to
|
||||
//overcome the shortcoming of scale by also adjusting the quality.
|
||||
//Xml field: "zoom".
|
||||
T m_Zoom;
|
||||
T m_Zoom = 0;
|
||||
|
||||
//3D fields.
|
||||
private:
|
||||
@ -1589,22 +1524,22 @@ private:
|
||||
|
||||
public:
|
||||
//Xml field: "cam_zpos".
|
||||
T m_CamZPos;
|
||||
T m_CamZPos = 0;
|
||||
|
||||
//Xml field: "cam_persp".
|
||||
T m_CamPerspective;
|
||||
T m_CamPerspective = 0;
|
||||
|
||||
//Xml field: "cam_yaw".
|
||||
T m_CamYaw;
|
||||
T m_CamYaw = 0;
|
||||
|
||||
//Xml field: "cam_pitch".
|
||||
T m_CamPitch;
|
||||
T m_CamPitch = 0;
|
||||
|
||||
//Xml field: "cam_dof".
|
||||
T m_CamDepthBlur;
|
||||
T m_CamDepthBlur = 0;
|
||||
|
||||
private:
|
||||
T m_BlurCoef;
|
||||
T m_BlurCoef = 0;
|
||||
|
||||
public:
|
||||
m3T m_CamMat;
|
||||
@ -1612,38 +1547,38 @@ public:
|
||||
//The camera offset from the center of the cartesian plane. Since this is the camera offset, the final output image will be moved in the opposite
|
||||
//direction of the values specified. There is also a second copy of the Y coordinate needed because m_CenterY will be modified during strips rendering.
|
||||
//Xml field: "center".
|
||||
T m_CenterX;
|
||||
T m_CenterY;
|
||||
T m_RotCenterY;
|
||||
T m_CenterX = 0;
|
||||
T m_CenterY = 0;
|
||||
T m_RotCenterY = 0;
|
||||
|
||||
//Rotate the camera by this many degrees. Since this is a camera rotation, the final output image will be rotated counter-clockwise.
|
||||
//Xml field: "rotate".
|
||||
T m_Rotate;
|
||||
T m_Rotate = 0;
|
||||
|
||||
//Determine how bright to make the image during final accumulation.
|
||||
//Xml field: "brightness".
|
||||
T m_Brightness;
|
||||
T m_Brightness = 4;
|
||||
|
||||
//Gamma level used in gamma correction during final accumulation.
|
||||
//Xml field: "gamma".
|
||||
T m_Gamma;
|
||||
T m_Gamma = 4;
|
||||
|
||||
//Used in color correction during final accumulation.
|
||||
//Xml field: "vibrancy".
|
||||
T m_Vibrancy;
|
||||
T m_Vibrancy = 1;
|
||||
|
||||
//Gamma threshold used in gamma correction during final accumulation.
|
||||
//Xml field: "gamma_threshold".
|
||||
T m_GammaThresh;
|
||||
T m_GammaThresh = T(0.01);
|
||||
|
||||
//Value to control saturation of some pixels in gamma correction during final accumulation.
|
||||
//Xml field: "highlight_power".
|
||||
T m_HighlightPower;
|
||||
T m_HighlightPower = -1;
|
||||
|
||||
//When animating a file full of many embers, this value is used to specify the time in the animation
|
||||
//that this ember should be rendered. They must all be sequential and increase by a default value of 1.
|
||||
//Xml field: "time".
|
||||
T m_Time;
|
||||
T m_Time = 0;
|
||||
|
||||
//The background color of the image used in final accumulation, ranged 0-1.
|
||||
//Xml field: "background".
|
||||
@ -1653,66 +1588,66 @@ public:
|
||||
|
||||
//The type of interpolation to use when interpolating between embers for animation.
|
||||
//Xml field: "interpolation".
|
||||
eInterp m_Interp;
|
||||
eInterp m_Interp = eInterp::EMBER_INTERP_SMOOTH;
|
||||
|
||||
//The type of interpolation to use on affine transforms when interpolating embers for animation.
|
||||
//Xml field: "interpolation_type" or "interpolation_space (deprecated)".
|
||||
eAffineInterp m_AffineInterp;
|
||||
eAffineInterp m_AffineInterp = eAffineInterp::AFFINE_INTERP_LOG;
|
||||
|
||||
//The type of interpolation to use for the palette when interpolating embers for animation.
|
||||
//Xml field: "palette_interpolation".
|
||||
ePaletteInterp m_PaletteInterp;
|
||||
ePaletteInterp m_PaletteInterp = ePaletteInterp::INTERP_HSV;
|
||||
|
||||
//Temporal Filter.
|
||||
|
||||
//Only used if temporal filter type is exp, else unused.
|
||||
//Xml field: "temporal_filter_exp".
|
||||
T m_TemporalFilterExp;
|
||||
T m_TemporalFilterExp = 0;
|
||||
|
||||
//The width of the temporal filter.
|
||||
//Xml field: "temporal_filter_width".
|
||||
T m_TemporalFilterWidth;
|
||||
T m_TemporalFilterWidth = 1;
|
||||
|
||||
//The type of the temporal filter: Gaussian, Box or Exp.
|
||||
//Xml field: "temporal_filter_type".
|
||||
eTemporalFilterType m_TemporalFilterType;
|
||||
eTemporalFilterType m_TemporalFilterType = eTemporalFilterType::BOX_TEMPORAL_FILTER;
|
||||
|
||||
//Density Estimation Filter.
|
||||
|
||||
//The minimum radius of the DE filter.
|
||||
//Xml field: "estimator_minimum".
|
||||
T m_MinRadDE;
|
||||
T m_MinRadDE = 0;
|
||||
|
||||
//The maximum radius of the DE filter.
|
||||
//Xml field: "estimator_radius".
|
||||
T m_MaxRadDE;
|
||||
T m_MaxRadDE = 9;
|
||||
|
||||
//The shape of the curve that governs how quickly or slowly the filter drops off as it moves away from the center point.
|
||||
//Xml field: "estimator_curve".
|
||||
T m_CurveDE;
|
||||
T m_CurveDE = T(0.4);
|
||||
|
||||
//Spatial Filter.
|
||||
|
||||
//The radius of the spatial filter used in final accumulation.
|
||||
//Xml field: "filter".
|
||||
T m_SpatialFilterRadius;
|
||||
T m_SpatialFilterRadius = T(0.5);
|
||||
|
||||
//The type of spatial filter used in final accumulation:
|
||||
//Gaussian, Hermite, Box, Triangle, Bell, Bspline, Lanczos3
|
||||
//Lanczos2, Mitchell, Blackman, Catrom, Hamming, Hanning, Quadratic.
|
||||
//Xml field: "filter_shape".
|
||||
eSpatialFilterType m_SpatialFilterType;
|
||||
eSpatialFilterType m_SpatialFilterType = eSpatialFilterType::GAUSSIAN_SPATIAL_FILTER;
|
||||
|
||||
//Palette.
|
||||
|
||||
//The method used for retrieving a color from the palette when accumulating to the histogram: step, linear.
|
||||
//Xml field: "palette_mode".
|
||||
ePaletteMode m_PaletteMode;
|
||||
ePaletteMode m_PaletteMode = ePaletteMode::PALETTE_LINEAR;
|
||||
|
||||
//The color palette to use. Can be specified inline as Xml color fields, or as a hex buffer. Can also be specified
|
||||
//as an index into the palette file with an optional hue rotation applied. Inserting as a hex buffer is the preferred method.
|
||||
//Xml field: "color" or "colors" or "palette" .
|
||||
Palette<T> m_Palette;
|
||||
Palette<T> m_Palette;//Final palette that is actually used is a copy of this inside of render, which will be of type bucketT (float).
|
||||
|
||||
//Curves used to adjust the color during final accumulation.
|
||||
Curves<T> m_Curves;
|
||||
@ -1721,18 +1656,18 @@ public:
|
||||
|
||||
//The name of this ember.
|
||||
//Xml field: "name".
|
||||
string m_Name;
|
||||
string m_Name = string("No name");
|
||||
|
||||
//The name of the file that this ember was contained in.
|
||||
//Xml field: "".
|
||||
string m_ParentFilename;
|
||||
string m_ParentFilename = string("No parent");
|
||||
|
||||
//An Xml edit document describing information about the author as well as an edit history of the ember.
|
||||
//Xml field: "edit".
|
||||
xmlDocPtr m_Edits;
|
||||
xmlDocPtr m_Edits = nullptr;
|
||||
|
||||
//The 0-based position of this ember in the file it was contained in.
|
||||
size_t m_Index;
|
||||
size_t m_Index = 0;
|
||||
|
||||
//The list of motion elements for the top-level flame params
|
||||
vector<EmberMotion<T>> m_EmberMotionElements;
|
||||
@ -1741,7 +1676,7 @@ private:
|
||||
/// <summary>
|
||||
/// The type of scaling used when resizing.
|
||||
/// </summary>
|
||||
eScaleType m_ScaleType;
|
||||
eScaleType m_ScaleType = eScaleType::SCALE_NONE;
|
||||
|
||||
//The vector containing all of the xforms.
|
||||
//Xml field: "xform".
|
||||
@ -1753,7 +1688,7 @@ private:
|
||||
Xform<T> m_FinalXform;
|
||||
|
||||
//Single global reference to create variations with.
|
||||
VariationList<T>& m_VariationList;
|
||||
VariationList<T>& m_VariationList = VariationList<T>::Instance();
|
||||
|
||||
/// <summary>
|
||||
/// Interpolation function that takes the address of a member variable of type T as a template parameter.
|
||||
@ -1763,7 +1698,7 @@ private:
|
||||
/// <param name="coefs">The list of coefficients to interpolate</param>
|
||||
/// <param name="size">The size of the lists, both must match.</param>
|
||||
template <T Ember<T>::*m>
|
||||
void InterpT(Ember<T>* embers, vector<T>& coefs, size_t size)
|
||||
void InterpT(const Ember<T>* embers, const vector<T>& coefs, size_t size)
|
||||
{
|
||||
this->*m = 0;
|
||||
|
||||
@ -1778,7 +1713,7 @@ private:
|
||||
/// <param name="coefs">The list of coefficients to interpolate</param>
|
||||
/// <param name="size">The size of the lists, both must match.</param>
|
||||
template <typename M, M Ember<T>::*m>
|
||||
void InterpX(Ember<T>* embers, vector<T>& coefs, size_t size)
|
||||
void InterpX(const Ember<T>* embers, const vector<T>& coefs, size_t size)
|
||||
{
|
||||
this->*m = M();
|
||||
|
||||
@ -1793,7 +1728,7 @@ private:
|
||||
/// <param name="coefs">The list of coefficients to interpolate</param>
|
||||
/// <param name="size">The size of the lists, both must match.</param>
|
||||
template <size_t Ember<T>::*m>
|
||||
void InterpI(Ember<T>* embers, vector<T>& coefs, size_t size)
|
||||
void InterpI(const Ember<T>* embers, const vector<T>& coefs, size_t size)
|
||||
{
|
||||
T t = 0;
|
||||
|
||||
@ -1813,7 +1748,7 @@ private:
|
||||
/// <param name="coefs">The list of coefficients to interpolate</param>
|
||||
/// <param name="size">The size of the lists, both must match.</param>
|
||||
template <T Xform<T>::*m>
|
||||
void InterpXform(Xform<T>* xform, size_t i, Ember<T>* embers, vector<T>& coefs, size_t size)
|
||||
void InterpXform(Xform<T>* xform, size_t i, const Ember<T>* embers, const vector<T>& coefs, size_t size)
|
||||
{
|
||||
xform->*m = T(0);
|
||||
|
||||
|
@ -94,8 +94,10 @@ static inline size_t NowMs()
|
||||
//These two must always match.
|
||||
#ifdef _WIN32
|
||||
#define ALIGN __declspec(align(16))
|
||||
#define STATIC static
|
||||
#else
|
||||
#define ALIGN __attribute__ ((aligned (16)))
|
||||
#define STATIC
|
||||
#endif
|
||||
|
||||
#define ALIGN_CL "((aligned (16)))"//The extra parens are necessary.
|
||||
|
@ -17,9 +17,7 @@ public:
|
||||
/// <summary>
|
||||
/// Default constructor, which calls the base, which sets first and second to their defaults.
|
||||
/// </summary>
|
||||
MotionParam()
|
||||
{
|
||||
}
|
||||
MotionParam() = default;
|
||||
|
||||
/// <summary>
|
||||
/// Member-wise constructor.
|
||||
@ -90,12 +88,8 @@ public:
|
||||
/// <summary>
|
||||
/// Default constructor to initialize motion freq and offset to 0 and the motion func to SIN.
|
||||
/// </summary>
|
||||
EmberMotion()
|
||||
{
|
||||
m_MotionFreq = 0;
|
||||
m_MotionFunc = eMotion::MOTION_SIN;
|
||||
m_MotionOffset = 0;
|
||||
}
|
||||
EmberMotion() = default;
|
||||
~EmberMotion() = default;
|
||||
|
||||
/// <summary>
|
||||
/// Default copy constructor.
|
||||
@ -136,16 +130,16 @@ public:
|
||||
template <typename U>
|
||||
EmberMotion& operator = (const EmberMotion<U>& other)
|
||||
{
|
||||
CopyVec(m_MotionParams, other.m_MotionParams);
|
||||
CopyCont(m_MotionParams, other.m_MotionParams);
|
||||
m_MotionFunc = other.m_MotionFunc;
|
||||
m_MotionFreq = T(other.m_MotionFreq);
|
||||
m_MotionOffset = T(other.m_MotionOffset);
|
||||
return *this;
|
||||
}
|
||||
|
||||
T m_MotionFreq;
|
||||
T m_MotionOffset;
|
||||
eMotion m_MotionFunc;
|
||||
T m_MotionFreq = 0;
|
||||
T m_MotionOffset = 0;
|
||||
eMotion m_MotionFunc = eMotion::MOTION_SIN;
|
||||
vector<MotionParam<T>> m_MotionParams;
|
||||
};
|
||||
}
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
#include <list>
|
||||
#ifdef __APPLE__
|
||||
#include <malloc/malloc.h>
|
||||
#else
|
||||
|
@ -23,9 +23,9 @@ public:
|
||||
/// <summary>
|
||||
/// Empty constructor.
|
||||
/// </summary>
|
||||
EmberToXml()
|
||||
{
|
||||
}
|
||||
EmberToXml() = default;
|
||||
~EmberToXml() = default;
|
||||
EmberToXml(const EmberToXml<T>& e) = delete;
|
||||
|
||||
/// <summary>
|
||||
/// Save the ember to the specified file.
|
||||
@ -34,33 +34,32 @@ public:
|
||||
/// <param name="ember">The ember to save</param>
|
||||
/// <param name="printEditDepth">How deep the edit depth goes</param>
|
||||
/// <param name="doEdits">If true included edit tags, else don't.</param>
|
||||
/// <param name="intPalette">If true use integers instead of floating point numbers when embedding a non-hex formatted palette, else use floating point numbers.</param>
|
||||
/// <param name="hexPalette">If true, embed a hexadecimal palette instead of Xml Color tags, else use Xml color tags.</param>
|
||||
/// <param name="append">If true, append to the file if it already exists, else create a new file.</param>
|
||||
/// <param name="start">Whether a new file is to be started</param>
|
||||
/// <param name="finish">Whether an existing file is to be ended</param>
|
||||
/// <returns>True if successful, else false</returns>
|
||||
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)
|
||||
bool Save(const string& filename, Ember<T>& ember, size_t printEditDepth, bool doEdits, 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);
|
||||
return Save(filename, vec, printEditDepth, doEdits, hexPalette, append, start, finish);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save a vector of embers to the specified file.
|
||||
/// Save a container of embers to the specified file.
|
||||
/// </summary>
|
||||
/// <param name="filename">Full path and filename</param>
|
||||
/// <param name="embers">The vector of embers to save</param>
|
||||
/// <param name="embers">The container of embers to save</param>
|
||||
/// <param name="printEditDepth">How deep the edit depth goes</param>
|
||||
/// <param name="doEdits">If true included edit tags, else don't.</param>
|
||||
/// <param name="intPalette">If true use integers instead of floating point numbers when embedding a non-hex formatted palette, else use floating point numbers.</param>
|
||||
/// <param name="hexPalette">If true, embed a hexadecimal palette instead of Xml Color tags, else use Xml color tags.</param>
|
||||
/// <param name="append">If true, append to the file if it already exists, else create a new file.</param>
|
||||
/// <param name="start">Whether a new file is to be started</param>
|
||||
/// <param name="finish">Whether an existing file is to be ended</param>
|
||||
/// <returns>True if successful, else false</returns>
|
||||
bool Save(const string& filename, vector<Ember<T>>& embers, size_t printEditDepth, bool doEdits, bool intPalette, bool hexPalette, bool append = false, bool start = false, bool finish = false)
|
||||
template <typename Alloc, template <typename, typename> class C>
|
||||
bool Save(const string& filename, C<Ember<T>, Alloc>& embers, size_t printEditDepth, bool doEdits, bool hexPalette, bool append = false, bool start = false, bool finish = false)
|
||||
{
|
||||
bool b = false;
|
||||
bool hasTimes = false;
|
||||
@ -77,15 +76,19 @@ public:
|
||||
|
||||
if (f.is_open())
|
||||
{
|
||||
auto prev = embers.begin();
|
||||
|
||||
//Check to see if there are valid times by checking if any differed.
|
||||
//If so, assume they were intentionally entered times.
|
||||
for (size_t i = 1; i < embers.size(); i++)
|
||||
for (auto it = Advance(embers.begin(), 1); it != embers.end(); ++it)
|
||||
{
|
||||
if (embers[i].m_Time != embers[i - 1].m_Time)
|
||||
if (it->m_Time != prev->m_Time)
|
||||
{
|
||||
hasTimes = true;
|
||||
break;
|
||||
}
|
||||
|
||||
prev = it;
|
||||
}
|
||||
|
||||
if (!hasTimes)
|
||||
@ -101,7 +104,7 @@ public:
|
||||
|
||||
for (auto& ember : embers)
|
||||
{
|
||||
string s = ToString(ember, "", printEditDepth, doEdits, intPalette, hexPalette);
|
||||
string s = ToString(ember, "", printEditDepth, doEdits, hexPalette);
|
||||
f.write(s.c_str(), s.size());
|
||||
}
|
||||
|
||||
@ -144,10 +147,9 @@ public:
|
||||
/// <param name="extraAttributes">If true, add extra attributes, else don't</param>
|
||||
/// <param name="printEditDepth">How deep the edit depth goes</param>
|
||||
/// <param name="doEdits">If true included edit tags, else don't.</param>
|
||||
/// <param name="intPalette">If true use integers instead of floating point numbers when embedding a non-hex formatted palette, else use floating point numbers.</param>
|
||||
/// <param name="hexPalette">If true, embed a hexadecimal palette instead of Xml Color tags, else use Xml color tags.</param>
|
||||
/// <returns>The Xml string representation of the passed in ember</returns>
|
||||
string ToString(Ember<T>& ember, const string& extraAttributes, size_t printEditDepth, bool doEdits, bool intPalette, bool hexPalette = true)
|
||||
string ToString(Ember<T>& ember, const string& extraAttributes, size_t printEditDepth, bool doEdits, bool hexPalette = true)
|
||||
{
|
||||
size_t i, j;
|
||||
string s;
|
||||
@ -292,19 +294,9 @@ public:
|
||||
|
||||
//The original used a precision of 6 which is totally unnecessary, use 2.
|
||||
if (IsClose(a, 255.0))
|
||||
{
|
||||
if (intPalette)
|
||||
os << "<color index=\"" << i << "\" rgb=\"" << int(std::rint(r)) << " " << int(std::rint(g)) << " " << int(std::rint(b)) << "\"/>";
|
||||
else
|
||||
os << "<color index=\"" << i << "\" rgb=\"" << std::fixed << std::setprecision(2) << r << " " << g << " " << b << "\"/>";
|
||||
}
|
||||
os << "<color index=\"" << i << "\" rgb=\"" << std::fixed << std::setprecision(2) << r << " " << g << " " << b << "\"/>";
|
||||
else
|
||||
{
|
||||
if (intPalette)
|
||||
os << " <color index=\"" << i << "\" rgba=\"" << int(std::rint(r)) << " " << int(std::rint(g)) << " " << int(std::rint(b)) << " " << int(std::rint(a)) << "\"/>";
|
||||
else
|
||||
os << " <color index=\"" << i << "\" rgba=\"" << std::fixed << std::setprecision(2) << r << " " << g << " " << b << " " << a << "\"/>";
|
||||
}
|
||||
os << " <color index=\"" << i << "\" rgba=\"" << std::fixed << std::setprecision(2) << r << " " << g << " " << b << " " << a << "\"/>";
|
||||
|
||||
os << "\n";
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ public:
|
||||
/// <param name="sourceEmbers">The array of embers to align</param>
|
||||
/// <param name="destEmbers">The array which will contain the aligned embers </param>
|
||||
/// <param name="count">The number of elements in sourceEmbers</param>
|
||||
static void Align(Ember<T>* sourceEmbers, Ember<T>* destEmbers, size_t count)
|
||||
static void Align(const Ember<T>* sourceEmbers, Ember<T>* destEmbers, size_t count)
|
||||
{
|
||||
bool aligned = true;
|
||||
bool currentFinal, final = sourceEmbers[0].UseFinalXform();
|
||||
@ -297,7 +297,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="embers">The vector of embers to inspect for xaos</param>
|
||||
/// <returns>True if at least one ember contained xaos, else false.</returns>
|
||||
static bool AnyXaosPresent(vector<Ember<T>>& embers)
|
||||
static bool AnyXaosPresent(const vector<Ember<T>>& embers)
|
||||
{
|
||||
return AnyXaosPresent(embers.data(), embers.size());
|
||||
}
|
||||
@ -308,7 +308,7 @@ public:
|
||||
/// <param name="embers">The array of embers to inspect</param>
|
||||
/// <param name="size">The size of the embers array</param>
|
||||
/// <returns>True if at least one ember contained xaos, else false.</returns>
|
||||
static bool AnyXaosPresent(Ember<T>* embers, size_t size)
|
||||
static bool AnyXaosPresent(const Ember<T>* embers, size_t size)
|
||||
{
|
||||
for (size_t i = 0; i < size; i++)
|
||||
if (embers[i].XaosPresent())
|
||||
@ -333,7 +333,7 @@ public:
|
||||
/// <param name="embers">The array of embers to inspect</param>
|
||||
/// <param name="size">The size of the embers array</param>
|
||||
/// <returns>The greatest non-final xform count in any of the embers</returns>
|
||||
static size_t MaxXformCount(Ember<T>* embers, size_t size)
|
||||
static size_t MaxXformCount(const Ember<T>* embers, size_t size)
|
||||
{
|
||||
size_t i, maxCount = 0;
|
||||
|
||||
@ -349,7 +349,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="embers">The vector of embers to inspect the presence of a final xform</param>
|
||||
/// <returns>True if any contained a non-empty final xform, else false.</returns>
|
||||
static bool AnyFinalPresent(vector<Ember<T>>& embers)
|
||||
static bool AnyFinalPresent(const vector<Ember<T>>& embers)
|
||||
{
|
||||
return AnyFinalPresent(embers.data(), embers.size());
|
||||
}
|
||||
@ -360,7 +360,7 @@ public:
|
||||
/// <param name="embers">The array of embers to inspect the presence of a final xform</param>
|
||||
/// <param name="size">The size of the embers array</param>
|
||||
/// <returns>True if any contained a final xform, else false.</returns>
|
||||
static bool AnyFinalPresent(Ember<T>* embers, size_t size)
|
||||
static bool AnyFinalPresent(const Ember<T>* embers, size_t size)
|
||||
{
|
||||
for (size_t i = 0; i < size; i++)
|
||||
if (embers[i].UseFinalXform())
|
||||
@ -376,7 +376,7 @@ public:
|
||||
/// <param name="time">The time position in the vector specifying the point of interpolation</param>
|
||||
/// <param name="stagger">Stagger if > 0</param>
|
||||
/// <param name="result">The interpolated result</param>
|
||||
static void Interpolate(vector<Ember<T>>& embers, T time, T stagger, Ember<T>& result)
|
||||
static void Interpolate(const vector<Ember<T>>& embers, T time, T stagger, Ember<T>& result)
|
||||
{
|
||||
Interpolate(embers.data(), embers.size(), time, stagger, result);
|
||||
}
|
||||
@ -389,7 +389,7 @@ public:
|
||||
/// <param name="time">The time position in the vector specifying the point of interpolation</param>
|
||||
/// <param name="stagger">Stagger if > 0</param>
|
||||
/// <param name="result">The interpolated result</param>
|
||||
static void Interpolate(Ember<T>* embers, size_t size, T time, T stagger, Ember<T>& result)
|
||||
static void Interpolate(const Ember<T>* embers, size_t size, T time, T stagger, Ember<T>& result)
|
||||
{
|
||||
if (size == 1)
|
||||
{
|
||||
@ -585,7 +585,7 @@ public:
|
||||
/// <param name="cxAng">The vec2 vector to store the polar angular values</param>
|
||||
/// <param name="cxMag">The vec2 vector to store the polar magnitude values</param>
|
||||
/// <param name="cxTrn">The vec2 vector to store the polar translation values</param>
|
||||
static void ConvertLinearToPolar(vector<Ember<T>>& embers, size_t xfi, size_t cflag, vector<v2T>& cxAng, vector<v2T>& cxMag, vector<v2T>& cxTrn)
|
||||
static void ConvertLinearToPolar(const vector<Ember<T>>& embers, size_t xfi, size_t cflag, vector<v2T>& cxAng, vector<v2T>& cxMag, vector<v2T>& cxTrn)
|
||||
{
|
||||
ConvertLinearToPolar(embers.data(), embers.size(), xfi, cflag, cxAng, cxMag, cxTrn);
|
||||
}
|
||||
@ -601,7 +601,7 @@ public:
|
||||
/// <param name="cxAng">The vec2 vector to store the polar angular values</param>
|
||||
/// <param name="cxMag">The vec2 vector to store the polar magnitude values</param>
|
||||
/// <param name="cxTrn">The vec2 vector to store the polar translation values</param>
|
||||
static void ConvertLinearToPolar(Ember<T>* embers, size_t size, size_t xfi, size_t cflag, vector<v2T>& cxAng, vector<v2T>& cxMag, vector<v2T>& cxTrn)
|
||||
static void ConvertLinearToPolar(const 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() &&
|
||||
@ -765,7 +765,7 @@ public:
|
||||
/// <param name="cxMag">The vec2 vector to store the polar magnitude values</param>
|
||||
/// <param name="cxTrn">The vec2 vector to store the polar translation values</param>
|
||||
/// <param name="store">The Affine2D to store the inerpolated values in</param>
|
||||
static void InterpAndConvertBack(vector<T>& coefs, vector<v2T>& cxAng, vector<v2T>& cxMag, vector<v2T>& cxTrn, Affine2D<T>& store)
|
||||
static void InterpAndConvertBack(const vector<T>& coefs, const vector<v2T>& cxAng, const vector<v2T>& cxMag, const vector<v2T>& cxTrn, Affine2D<T>& store)
|
||||
{
|
||||
size_t size = coefs.size();
|
||||
glm::length_t i, col, accmode[2] = { 0, 0 };
|
||||
|
@ -56,7 +56,7 @@ class EMBER_API QTIsaac
|
||||
public:
|
||||
enum { N = (1 << ALPHA) };
|
||||
UintBytes m_Cache;
|
||||
size_t m_LastIndex;
|
||||
size_t m_LastIndex = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The structure which holds all of the random information.
|
||||
@ -85,7 +85,6 @@ public:
|
||||
QTIsaac(T a = 0, T b = 0, T c = 0, T* s = nullptr)
|
||||
{
|
||||
Srand(a, b, c, s);
|
||||
m_LastIndex = 0;
|
||||
m_Cache.Uint = Rand();
|
||||
RandByte();//Need to call at least once so other libraries can link.
|
||||
}
|
||||
|
@ -52,18 +52,11 @@ class EMBER_API Iterator
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Empty constructor.
|
||||
/// Empty constructor and virtual destructor so proper derived class destructors get called.
|
||||
/// </summary>
|
||||
Iterator()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Empty virtual destructor so proper derived class destructors get called.
|
||||
/// </summary>
|
||||
virtual ~Iterator()
|
||||
{
|
||||
}
|
||||
Iterator() = default;
|
||||
virtual ~Iterator() = default;
|
||||
Iterator(const Iterator<T>& iter) = delete;
|
||||
|
||||
/// <summary>
|
||||
/// Accessors.
|
||||
|
@ -25,8 +25,6 @@ public:
|
||||
/// </summary>
|
||||
Palette()
|
||||
{
|
||||
m_Name = "-";
|
||||
m_Index = -1;
|
||||
m_Entries.resize(COLORMAP_LENGTH);
|
||||
Clear();
|
||||
}
|
||||
@ -119,12 +117,9 @@ public:
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Empty destructor.
|
||||
/// Needed to eliminate warnings about inlining.
|
||||
/// </summary>
|
||||
~Palette()
|
||||
{
|
||||
}
|
||||
~Palette() = default;
|
||||
|
||||
/// <summary>
|
||||
/// Default assignment operator.
|
||||
@ -149,7 +144,7 @@ public:
|
||||
m_Index = palette.m_Index;
|
||||
m_Name = palette.m_Name;
|
||||
m_Filename = palette.m_Filename;
|
||||
CopyVec(m_Entries, palette.m_Entries);
|
||||
CopyCont(m_Entries, palette.m_Entries);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -163,6 +158,16 @@ public:
|
||||
return m_Entries[i];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convenience [] operator to index into the color entries vector in a const context.
|
||||
/// </summary>
|
||||
/// <param name="i">The index to get</param>
|
||||
/// <returns>The color value at the specified index</returns>
|
||||
const v4T& operator[] (size_t i) const
|
||||
{
|
||||
return m_Entries[i];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convenience * operator to get a pointer to the beginning of the color entries vector.
|
||||
/// </summary>
|
||||
@ -421,7 +426,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="rgb">The RGB buffer</param>
|
||||
/// <param name="hsv">The HSV buffer</param>
|
||||
static void RgbToHsv(T* rgb, T* hsv)
|
||||
static void RgbToHsv(const T* rgb, T* hsv)
|
||||
{
|
||||
RgbToHsv(rgb[0], rgb[1], rgb[2], hsv[0], hsv[1], hsv[2]);
|
||||
}
|
||||
@ -576,9 +581,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
int m_Index;//Index in the xml palette file of this palette, use -1 for random.
|
||||
string m_Name;//Name of this palette.
|
||||
int m_Index = -1;//Index in the xml palette file of this palette, use -1 for random.
|
||||
string m_Name = "-";//Name of this palette.
|
||||
shared_ptr<string> m_Filename;//Name of the parent file this palette came from, can be empty.
|
||||
vector<v4T> m_Entries;//Storage for the color values.
|
||||
vector<v4T> m_Entries;
|
||||
};
|
||||
}
|
||||
|
@ -28,6 +28,9 @@ public:
|
||||
Add(string(m_DefaultFilename));
|
||||
}
|
||||
|
||||
~PaletteList() = default;
|
||||
PaletteList(const PaletteList<T>& paletteList) = delete;
|
||||
|
||||
/// <summary>
|
||||
/// Read an Xml palette file into memory.
|
||||
/// This must be called before any palette file usage.
|
||||
|
@ -25,10 +25,8 @@ public:
|
||||
/// <summary>
|
||||
/// Constructor to initialize spatial and color coordinates to zero, with full visibility.
|
||||
/// </summary>
|
||||
Point()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
Point() = default;
|
||||
~Point() = default;
|
||||
|
||||
/// <summary>
|
||||
/// Default copy constructor.
|
||||
@ -75,29 +73,16 @@ public:
|
||||
m_ColorX = point.m_ColorX;
|
||||
//m_ColorY = point.m_ColorY;
|
||||
m_VizAdjusted = point.m_VizAdjusted;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set spatial and color coordinates to zero, with full visibility.
|
||||
/// </summary>
|
||||
void Init()
|
||||
{
|
||||
m_X = 0;
|
||||
m_Y = 0;
|
||||
m_Z = 0;
|
||||
m_ColorX = 0;
|
||||
//m_ColorY = 0;
|
||||
m_VizAdjusted = 1;
|
||||
}
|
||||
|
||||
T m_X;
|
||||
T m_Y;
|
||||
T m_Z;
|
||||
T m_ColorX;
|
||||
//Set spatial and color coordinates to zero, with full visibility.
|
||||
T m_X = 0;
|
||||
T m_Y = 0;
|
||||
T m_Z = 0;
|
||||
T m_ColorX = 0;
|
||||
//T m_ColorY;
|
||||
T m_VizAdjusted;
|
||||
T m_VizAdjusted = 1;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@ -132,10 +117,10 @@ template <typename T>
|
||||
struct EMBER_API Color : public v4T
|
||||
{
|
||||
#ifndef _WIN32
|
||||
using v4T::r;
|
||||
using v4T::g;
|
||||
using v4T::b;
|
||||
using v4T::a;
|
||||
using v4T::r;
|
||||
using v4T::g;
|
||||
using v4T::b;
|
||||
using v4T::a;
|
||||
#endif
|
||||
public:
|
||||
/// <summary>
|
||||
|
@ -3,27 +3,6 @@
|
||||
|
||||
namespace EmberNs
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor that sets default values and allocates iterators.
|
||||
/// The thread count is set to the number of cores detected on the system.
|
||||
/// </summary>
|
||||
template <typename T, typename bucketT>
|
||||
Renderer<T, bucketT>::Renderer()
|
||||
{
|
||||
m_PixelAspectRatio = 1;
|
||||
m_StandardIterator = unique_ptr<StandardIterator<T>>(new StandardIterator<T>());
|
||||
m_XaosIterator = unique_ptr<XaosIterator<T>>(new XaosIterator<T>());
|
||||
m_Iterator = m_StandardIterator.get();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Virtual destructor so derived class destructors get called.
|
||||
/// </summary>
|
||||
template <typename T, typename bucketT>
|
||||
Renderer<T, bucketT>::~Renderer()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Non-virtual processing functions.
|
||||
/// </summary>
|
||||
@ -89,7 +68,7 @@ void Renderer<T, bucketT>::ComputeBounds()
|
||||
////Check the size of the density estimation filter.
|
||||
////If the radius of the density estimation filter is greater than the
|
||||
////gutter width, have to pad with more. Otherwise, use the same value.
|
||||
//for (auto& ember : m_Embers)
|
||||
//for (auto& ember : *m_EmbersP)
|
||||
// maxDEFilterWidth = std::max<size_t>(size_t(ceil(ember.m_MaxRadDE) * m_Ember.m_Supersample), maxDEFilterWidth);
|
||||
//
|
||||
////Need an extra ss = (int)floor(m_Supersample / 2.0) of pixels so that a local iteration count for DE can be determined.//SMOULDER
|
||||
@ -162,7 +141,7 @@ void Renderer<T, bucketT>::ComputeCamera()
|
||||
/// However, changing only the brightness and setting action to ACCUM_ONLY is perfectly fine.
|
||||
/// </param>
|
||||
template <typename T, typename bucketT>
|
||||
void Renderer<T, bucketT>::SetEmber(Ember<T>& ember, eProcessAction action)
|
||||
void Renderer<T, bucketT>::SetEmber(const Ember<T>& ember, eProcessAction action)
|
||||
{
|
||||
ChangeVal([&]
|
||||
{
|
||||
@ -170,26 +149,64 @@ void Renderer<T, bucketT>::SetEmber(Ember<T>& ember, eProcessAction action)
|
||||
m_Embers.push_back(ember);
|
||||
m_Embers[0].m_TemporalSamples = 1;//Set temporal samples here to 1 because using the real value only makes sense when using a vector of Embers for animation.
|
||||
m_Ember = m_Embers[0];
|
||||
m_EmbersP = &m_Embers;
|
||||
}, action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the vector of embers and set the m_Ember member to a copy of the first element.
|
||||
/// Copy the embers in the passed in container to the internal vector of embers
|
||||
/// and set the m_Ember member to a copy of the first element.
|
||||
/// Reset the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="embers">The vector of embers</param>
|
||||
/// <param name="embers">The container of embers to be copied</param>
|
||||
template <typename T, typename bucketT>
|
||||
void Renderer<T, bucketT>::SetEmber(vector<Ember<T>>& embers)
|
||||
template <typename C>
|
||||
void Renderer<T, bucketT>::SetEmber(const C& embers)
|
||||
{
|
||||
ChangeVal([&]
|
||||
{
|
||||
m_Embers = embers;
|
||||
CopyCont(m_Embers, embers);
|
||||
m_EmbersP = &m_Embers;
|
||||
|
||||
if (!m_Embers.empty())
|
||||
m_Ember = m_Embers[0];
|
||||
}, eProcessAction::FULL_RENDER);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move the embers in the passed in vector to the internal vector of embers
|
||||
/// and set the m_Ember member to a copy of the first element.
|
||||
/// Reset the rendering process.
|
||||
/// This is preferred over SetEmber when the size of embers is large and/or
|
||||
/// the caller no longer needs to use the argument after this function returns.
|
||||
/// </summary>
|
||||
/// <param name="embers">The vector of embers to be moved</param>
|
||||
template <typename T, typename bucketT>
|
||||
void Renderer<T, bucketT>::MoveEmbers(vector<Ember<T>>& embers)
|
||||
{
|
||||
ChangeVal([&]
|
||||
{
|
||||
m_Embers = std::move(embers);
|
||||
m_EmbersP = &m_Embers;
|
||||
|
||||
if (!m_Embers.empty())
|
||||
m_Ember = m_Embers[0];
|
||||
}, eProcessAction::FULL_RENDER);
|
||||
}
|
||||
|
||||
template <typename T, typename bucketT>
|
||||
void Renderer<T, bucketT>::SetExternalEmbersPointer(vector<Ember<T>>* embers)
|
||||
{
|
||||
ChangeVal([&]
|
||||
{
|
||||
m_Embers.clear();
|
||||
m_EmbersP = embers;
|
||||
|
||||
if (!m_EmbersP->empty())
|
||||
m_Ember = (*m_EmbersP)[0];
|
||||
}, eProcessAction::FULL_RENDER);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create the density filter if the current filter parameters differ
|
||||
/// from the last density filter created.
|
||||
@ -213,7 +230,7 @@ bool Renderer<T, bucketT>::CreateDEFilter(bool& newAlloc)
|
||||
(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));
|
||||
m_DensityFilter = make_unique<DensityFilter<bucketT>>(bucketT(m_Ember.m_MinRadDE), bucketT(m_Ember.m_MaxRadDE), bucketT(m_Ember.m_CurveDE), m_Ember.m_Supersample);
|
||||
newAlloc = true;
|
||||
}
|
||||
|
||||
@ -384,7 +401,7 @@ eRenderStatus Renderer<T, bucketT>::Run(vector<byte>& finalImage, double time, s
|
||||
//Vib, gam and background are normally summed for each temporal sample. However if iteration is skipped, make sure to get the latest.
|
||||
if ((filterAndAccumOnly || accumOnly) && TemporalSamples() == 1)//Disallow jumping when temporal samples > 1.
|
||||
{
|
||||
m_Ember = m_Embers[0];
|
||||
m_Ember = (*m_EmbersP)[0];
|
||||
m_Vibrancy = Vibrancy();
|
||||
m_Gamma = Gamma();
|
||||
m_Background = m_Ember.m_Background;
|
||||
@ -398,8 +415,8 @@ eRenderStatus Renderer<T, bucketT>::Run(vector<byte>& finalImage, double time, s
|
||||
|
||||
//it.Tic();
|
||||
//Interpolate.
|
||||
if (m_Embers.size() > 1)
|
||||
Interpolater<T>::Interpolate(m_Embers, T(time), 0, m_Ember);
|
||||
if (m_EmbersP->size() > 1)
|
||||
Interpolater<T>::Interpolate(*m_EmbersP, T(time), 0, m_Ember);
|
||||
|
||||
//it.Toc("Interp 1");
|
||||
|
||||
@ -436,8 +453,8 @@ eRenderStatus Renderer<T, bucketT>::Run(vector<byte>& finalImage, double time, s
|
||||
//Interpolate and get an ember for DE purposes.
|
||||
//Additional interpolation will be done in the temporal samples loop.
|
||||
//it.Tic();
|
||||
if (m_Embers.size() > 1)
|
||||
Interpolater<T>::Interpolate(m_Embers, deTime, 0, m_Ember);
|
||||
if (m_EmbersP->size() > 1)
|
||||
Interpolater<T>::Interpolate(*m_EmbersP, deTime, 0, m_Ember);
|
||||
|
||||
//it.Toc("Interp 2");
|
||||
ClampGteRef<T>(m_Ember.m_MinRadDE, 0);
|
||||
@ -461,8 +478,8 @@ eRenderStatus Renderer<T, bucketT>::Run(vector<byte>& finalImage, double time, s
|
||||
|
||||
//Interpolate again.
|
||||
//it.Tic();
|
||||
if (TemporalSamples() > 1 && m_Embers.size() > 1)
|
||||
Interpolater<T>::Interpolate(m_Embers, temporalTime, 0, m_Ember);//This will perform all necessary precalcs via the ember/xform/variation assignment operators.
|
||||
if (TemporalSamples() > 1 && m_EmbersP->size() > 1)
|
||||
Interpolater<T>::Interpolate(*m_EmbersP, temporalTime, 0, m_Ember);//This will perform all necessary precalcs via the ember/xform/variation assignment operators.
|
||||
|
||||
//it.Toc("Interp 3");
|
||||
|
||||
@ -678,16 +695,15 @@ Finish:
|
||||
/// Run() should have completed before calling this.
|
||||
/// </summary>
|
||||
/// <param name="printEditDepth">The depth of the edit tags</param>
|
||||
/// <param name="intPalette">If true use integers instead of floating point numbers when embedding a non-hex formatted palette, else use floating point numbers.</param>
|
||||
/// <param name="hexPalette">If true, embed a hexadecimal palette instead of Xml Color tags, else use Xml color tags.</param>
|
||||
/// <returns>The EmberImageComments object with image comments filled out</returns>
|
||||
template <typename T, typename bucketT>
|
||||
EmberImageComments Renderer<T, bucketT>::ImageComments(const EmberStats& stats, size_t printEditDepth, bool intPalette, bool hexPalette)
|
||||
EmberImageComments Renderer<T, bucketT>::ImageComments(const EmberStats& stats, size_t printEditDepth, bool hexPalette)
|
||||
{
|
||||
ostringstream ss;
|
||||
EmberImageComments comments;
|
||||
ss.imbue(std::locale(""));
|
||||
comments.m_Genome = m_EmberToXml.ToString(m_Ember, "", printEditDepth, false, intPalette, hexPalette);
|
||||
comments.m_Genome = m_EmberToXml.ToString(m_Ember, "", printEditDepth, false, hexPalette);
|
||||
ss << (double(stats.m_Badvals) / double(stats.m_Iters));//Percentage of bad values to iters.
|
||||
comments.m_Badvals = ss.str(); ss.str("");
|
||||
ss << stats.m_Iters;
|
||||
@ -1702,8 +1718,12 @@ void Renderer<T, bucketT>::CurveAdjust(bucketT& a, const glm::length_t& index)
|
||||
//So the explicit instantiation must be declared here rather than in Ember.cpp where
|
||||
//all of the other classes are done.
|
||||
template EMBER_API class Renderer<float, float>;
|
||||
template EMBER_API void Renderer<float, float>::SetEmber(const vector<Ember<float>>& embers);
|
||||
template EMBER_API void Renderer<float, float>::SetEmber(const list<Ember<float>>& embers);
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
template EMBER_API class Renderer<double, float>;
|
||||
template EMBER_API void Renderer<double, float>::SetEmber(const vector<Ember<double>>& embers);
|
||||
template EMBER_API void Renderer<double, float>::SetEmber(const list<Ember<double>>& embers);
|
||||
#endif
|
||||
}
|
||||
|
@ -43,10 +43,12 @@ namespace EmberNs
|
||||
template <typename T, typename bucketT>
|
||||
class EMBER_API Renderer : public RendererBase
|
||||
{
|
||||
//using EmberReport::m_ErrorReport;
|
||||
public:
|
||||
Renderer();
|
||||
virtual ~Renderer();
|
||||
|
||||
Renderer() = default;
|
||||
Renderer(const Renderer<T, bucketT>& renderer) = delete;
|
||||
Renderer<T, bucketT>& operator = (const Renderer<T, bucketT>& renderer) = delete;
|
||||
virtual ~Renderer() = default;
|
||||
|
||||
//Non-virtual processing functions.
|
||||
void AddEmber(Ember<T>& ember);
|
||||
@ -56,14 +58,17 @@ public:
|
||||
virtual void ComputeBounds() override;
|
||||
virtual void ComputeQuality() override;
|
||||
virtual void ComputeCamera() override;
|
||||
virtual void SetEmber(Ember<T>& ember, eProcessAction action = eProcessAction::FULL_RENDER) override;
|
||||
virtual void SetEmber(vector<Ember<T>>& embers) override;
|
||||
virtual void SetEmber(const Ember<T>& ember, eProcessAction action = eProcessAction::FULL_RENDER) override;
|
||||
template <typename C>
|
||||
void SetEmber(const C& embers);
|
||||
void MoveEmbers(vector<Ember<T>>& embers);
|
||||
void SetExternalEmbersPointer(vector<Ember<T>>* embers);
|
||||
virtual bool CreateDEFilter(bool& newAlloc) override;
|
||||
virtual bool CreateSpatialFilter(bool& newAlloc) override;
|
||||
virtual bool CreateTemporalFilter(bool& newAlloc) override;
|
||||
virtual size_t HistBucketSize() const override { return sizeof(tvec4<bucketT, glm::defaultp>); }
|
||||
virtual eRenderStatus Run(vector<byte>& finalImage, double time = 0, size_t subBatchCountOverride = 0, bool forceOutput = false, size_t finalOffset = 0) override;
|
||||
virtual EmberImageComments ImageComments(const EmberStats& stats, size_t printEditDepth = 0, bool intPalette = false, bool hexPalette = true) override;
|
||||
virtual EmberImageComments ImageComments(const EmberStats& stats, size_t printEditDepth = 0, bool hexPalette = true) override;
|
||||
|
||||
protected:
|
||||
//New virtual functions to be overridden in derived renderers that use the GPU, but not accessed outside.
|
||||
@ -158,7 +163,7 @@ protected:
|
||||
T m_Scale;
|
||||
T m_PixelsPerUnitX;
|
||||
T m_PixelsPerUnitY;
|
||||
T m_PixelAspectRatio;
|
||||
T m_PixelAspectRatio = 1;
|
||||
T m_LowerLeftX;
|
||||
T m_LowerLeftY;
|
||||
T m_UpperRightX;
|
||||
@ -173,12 +178,16 @@ protected:
|
||||
Ember<T> m_Ember;
|
||||
Ember<T> m_TempEmber;
|
||||
Ember<T> m_LastEmber;
|
||||
private:
|
||||
vector<Ember<T>> m_Embers;
|
||||
|
||||
protected:
|
||||
vector<Ember<T>>* m_EmbersP = &m_Embers;
|
||||
vector<Ember<T>> m_ThreadEmbers;
|
||||
CarToRas<T> m_CarToRas;
|
||||
Iterator<T>* m_Iterator;
|
||||
unique_ptr<StandardIterator<T>> m_StandardIterator;
|
||||
unique_ptr<XaosIterator<T>> m_XaosIterator;
|
||||
unique_ptr<StandardIterator<T>> m_StandardIterator = make_unique<StandardIterator<T>>();
|
||||
unique_ptr<XaosIterator<T>> m_XaosIterator = make_unique<XaosIterator<T>>();
|
||||
Iterator<T>* m_Iterator = m_StandardIterator.get();
|
||||
Palette<bucketT> m_Dmap, m_Csa;
|
||||
vector<tvec4<bucketT, glm::defaultp>> m_HistBuckets;
|
||||
vector<tvec4<bucketT, glm::defaultp>> m_AccumulatorBuckets;
|
||||
|
@ -8,31 +8,8 @@ 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_Abort = false;
|
||||
m_LockAccum = false;
|
||||
m_EarlyClip = false;
|
||||
m_YAxisUp = false;
|
||||
m_InsertPalette = false;
|
||||
m_ReclaimOnResize = false;
|
||||
m_CurvesSet = false;
|
||||
m_NumChannels = 3;
|
||||
m_BytesPerChannel = 1;
|
||||
m_SuperSize = 0;
|
||||
m_Transparency = false;
|
||||
ThreadCount(Timing::ProcessorCount());
|
||||
m_Callback = nullptr;
|
||||
m_ProgressParameter = nullptr;
|
||||
m_LastTemporalSample = 0;
|
||||
m_LastIter = 0;
|
||||
m_LastIterPercent = 0;
|
||||
m_InteractiveFilter = eInteractiveFilter::FILTER_LOG;
|
||||
m_Priority = eThreadPriority::NORMAL;
|
||||
m_ProcessState = eProcessState::NONE;
|
||||
m_ProcessAction = eProcessAction::FULL_RENDER;
|
||||
m_InRender = false;
|
||||
m_InFinalAccum = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -21,10 +21,13 @@ namespace EmberNs
|
||||
class EMBER_API RenderCallback
|
||||
{
|
||||
public:
|
||||
RenderCallback() = default;
|
||||
RenderCallback(RenderCallback& callback) = delete;
|
||||
|
||||
/// <summary>
|
||||
/// Virtual destructor to ensure anything declared in derived classes gets cleaned up.
|
||||
/// </summary>
|
||||
virtual ~RenderCallback() { }
|
||||
virtual ~RenderCallback() = default;
|
||||
|
||||
/// <summary>
|
||||
/// Empty progress function to be implemented in derived classes to take action on progress updates.
|
||||
@ -91,10 +94,11 @@ enum class eRendererType : et { CPU_RENDERER, OPENCL_RENDERER };
|
||||
/// </summary>
|
||||
class EMBER_API RendererBase : public EmberReport
|
||||
{
|
||||
//using EmberReport::m_ErrorReport;
|
||||
public:
|
||||
RendererBase();
|
||||
virtual ~RendererBase() { }
|
||||
RendererBase(const RendererBase& renderer) = delete;
|
||||
RendererBase& operator = (const RendererBase& renderer) = delete;
|
||||
virtual ~RendererBase() = default;
|
||||
|
||||
//Non-virtual processing functions.
|
||||
void ChangeVal(std::function<void(void)> func, eProcessAction action);
|
||||
@ -106,10 +110,8 @@ public:
|
||||
//Virtual processing functions.
|
||||
virtual bool Ok() const;
|
||||
virtual size_t MemoryAvailable();
|
||||
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 = eProcessAction::FULL_RENDER) { }
|
||||
virtual void SetEmber(vector<Ember<double>>& embers) { }
|
||||
virtual void SetEmber(const Ember<float>& ember, eProcessAction action = eProcessAction::FULL_RENDER) { }
|
||||
virtual void SetEmber(const Ember<double>& ember, eProcessAction action = eProcessAction::FULL_RENDER) { }
|
||||
virtual bool RandVec(vector<QTIsaac<ISAAC_SIZE, ISAAC_INT>>& randVec);
|
||||
|
||||
//Abstract processing functions.
|
||||
@ -120,7 +122,7 @@ public:
|
||||
virtual void ComputeQuality() = 0;
|
||||
virtual void ComputeCamera() = 0;
|
||||
virtual eRenderStatus Run(vector<byte>& finalImage, double time = 0, size_t subBatchCountOverride = 0, bool forceOutput = false, size_t finalOffset = 0) = 0;
|
||||
virtual EmberImageComments ImageComments(const EmberStats& stats, size_t printEditDepth = 0, bool intPalette = false, bool hexPalette = true) = 0;
|
||||
virtual EmberImageComments ImageComments(const EmberStats& stats, size_t printEditDepth = 0, bool hexPalette = true) = 0;
|
||||
virtual DensityFilterBase* GetDensityFilter() = 0;
|
||||
|
||||
//Non-virtual renderer properties, getters only.
|
||||
@ -193,41 +195,41 @@ public:
|
||||
bool InRender();
|
||||
bool InFinalAccum();
|
||||
|
||||
void* m_ProgressParameter;
|
||||
void* m_ProgressParameter = nullptr;
|
||||
|
||||
protected:
|
||||
bool m_EarlyClip;
|
||||
bool m_YAxisUp;
|
||||
bool m_Transparency;
|
||||
bool m_LockAccum;
|
||||
bool m_InRender;
|
||||
bool m_InFinalAccum;
|
||||
bool m_InsertPalette;
|
||||
bool m_ReclaimOnResize;
|
||||
bool m_CurvesSet;
|
||||
volatile bool m_Abort;
|
||||
bool m_EarlyClip = false;
|
||||
bool m_YAxisUp = false;
|
||||
bool m_Transparency = false;
|
||||
bool m_LockAccum = false;
|
||||
bool m_InRender = false;
|
||||
bool m_InFinalAccum = false;
|
||||
bool m_InsertPalette = false;
|
||||
bool m_ReclaimOnResize = false;
|
||||
bool m_CurvesSet = false;
|
||||
volatile bool m_Abort = false;
|
||||
size_t m_SuperRasW;
|
||||
size_t m_SuperRasH;
|
||||
size_t m_SuperSize;
|
||||
size_t m_SuperSize = 0;
|
||||
size_t m_GutterWidth;
|
||||
size_t m_DensityFilterOffset;
|
||||
size_t m_NumChannels;
|
||||
size_t m_BytesPerChannel;
|
||||
size_t m_NumChannels = 3;
|
||||
size_t m_BytesPerChannel = 1;
|
||||
size_t m_ThreadsToUse;
|
||||
size_t m_VibGamCount;
|
||||
size_t m_LastTemporalSample;
|
||||
size_t m_LastIter;
|
||||
double m_LastIterPercent;
|
||||
eThreadPriority m_Priority;
|
||||
eProcessAction m_ProcessAction;
|
||||
eProcessState m_ProcessState;
|
||||
eInteractiveFilter m_InteractiveFilter;
|
||||
size_t m_LastTemporalSample = 0;
|
||||
size_t m_LastIter = 0;
|
||||
double m_LastIterPercent = 0;
|
||||
eThreadPriority m_Priority = eThreadPriority::NORMAL;
|
||||
eProcessAction m_ProcessAction = eProcessAction::FULL_RENDER;
|
||||
eProcessState m_ProcessState = eProcessState::NONE;
|
||||
eInteractiveFilter m_InteractiveFilter = eInteractiveFilter::FILTER_LOG;
|
||||
EmberStats m_Stats;
|
||||
RenderCallback* m_Callback;
|
||||
RenderCallback* m_Callback = nullptr;
|
||||
vector<size_t> m_SubBatch;
|
||||
vector<size_t> m_BadVals;
|
||||
vector<QTIsaac<ISAAC_SIZE, ISAAC_INT>> m_Rand;
|
||||
auto_ptr<tbb::task_group> m_TaskGroup;
|
||||
unique_ptr<tbb::task_group> m_TaskGroup = make_unique<tbb::task_group>();
|
||||
std::recursive_mutex m_RenderingCs, m_AccumCs, m_FinalAccumCs, m_ResizeCs;
|
||||
Timing m_RenderTimer, m_IterTimer, m_ProgressTimer;
|
||||
};
|
||||
|
@ -65,19 +65,14 @@ public:
|
||||
: m_VariationList(VariationList<T>::Instance())
|
||||
{
|
||||
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>());
|
||||
m_Renderer = unique_ptr<Renderer<T, bucketT>>(renderer);
|
||||
m_Rand = QTIsaac<ISAAC_SIZE, ISAAC_INT>(ISAAC_INT(t.Tic()), ISAAC_INT(t.Tic() * 2), ISAAC_INT(t.Tic() * 3));
|
||||
}
|
||||
|
||||
SheepTools(const SheepTools& sheepTools) = delete;
|
||||
SheepTools<T, bucketT>& operator = (const SheepTools<T, bucketT>& sheepTools) = delete;
|
||||
|
||||
/// <summary>
|
||||
/// Create the linear default ember with a random palette.
|
||||
/// </summary>
|
||||
@ -1329,12 +1324,12 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_Smooth;
|
||||
intmax_t m_SheepGen;
|
||||
intmax_t m_SheepId;
|
||||
T m_Stagger;
|
||||
T m_OffsetX;
|
||||
T m_OffsetY;
|
||||
bool m_Smooth = true;
|
||||
intmax_t m_SheepGen = -1;
|
||||
intmax_t m_SheepId = -1;
|
||||
T m_Stagger = 0;
|
||||
T m_OffsetX = 0;
|
||||
T m_OffsetY = 0;
|
||||
string m_Nick;
|
||||
string m_Url;
|
||||
string m_Id;
|
||||
@ -1345,8 +1340,8 @@ private:
|
||||
vector<uint> m_Hist;
|
||||
EmberToXml<T> m_EmberToXml;
|
||||
Iterator<T>* m_Iterator;
|
||||
unique_ptr<StandardIterator<T>> m_StandardIterator;
|
||||
unique_ptr<XaosIterator<T>> m_XaosIterator;
|
||||
unique_ptr<StandardIterator<T>> m_StandardIterator = make_unique<StandardIterator<T>>();
|
||||
unique_ptr<XaosIterator<T>> m_XaosIterator = make_unique<XaosIterator<T>>();
|
||||
unique_ptr<Renderer<T, bucketT>> m_Renderer;
|
||||
QTIsaac<ISAAC_SIZE, ISAAC_INT> m_Rand;
|
||||
PaletteList<T> m_PaletteList;
|
||||
|
@ -72,12 +72,16 @@ class EMBER_API EmberImageComments
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Empty destructor.
|
||||
/// Basic defaults.
|
||||
/// </summary>
|
||||
EmberImageComments() = default;
|
||||
EmberImageComments(const EmberImageComments& comments) = default;
|
||||
EmberImageComments& operator = (const EmberImageComments& comments) = default;
|
||||
|
||||
/// <summary>
|
||||
/// Needed to eliminate warnings about inlining.
|
||||
/// </summary>
|
||||
~EmberImageComments()
|
||||
{
|
||||
}
|
||||
~EmberImageComments() = default;
|
||||
|
||||
/// <summary>
|
||||
/// Set all values to the empty string.
|
||||
@ -304,81 +308,105 @@ static bool ReadFile(const char* filename, string& buf, bool nullTerminate = tru
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear dest and copy all of the elements of vector source with elements of type U to the vector
|
||||
/// dest with elements of type T.
|
||||
/// Thin wrapper around std::advance that returns the advanced iterator.
|
||||
/// Note the passed in iterator is constant so it will not be changed, unlike
|
||||
/// std::advance does.
|
||||
/// </summary>
|
||||
/// <param name="dest">The vector of type T to copy to</param>
|
||||
/// <param name="source">The vector of type U to copy from</param>
|
||||
template <typename T, typename U>
|
||||
static void CopyVec(vector<T>& dest, const vector<U>& source)
|
||||
/// <param name="it">A const reference to an iterator, a copy of which will be advanced.</param>
|
||||
/// <param name="off">How far to move the iterator forward</param>
|
||||
/// <returns>A copy of the passed in iterator, advanced the specified number of elements</returns>
|
||||
template<class iter, class diff>
|
||||
static iter Advance(const iter& it, diff off)
|
||||
{
|
||||
dest.clear();
|
||||
dest.resize(source.size());
|
||||
|
||||
for (size_t i = 0; i < source.size(); i++)
|
||||
dest[i] = static_cast<T>(source[i]);//Valid assignment operator between T and U types must be defined somewhere.
|
||||
auto temp = it;
|
||||
std::advance(temp, off);
|
||||
return temp;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear dest and copy all of the elements of vector source with elements of type U to the vector
|
||||
/// Clear dest and copy all of the elements of container source with elements of type U to the container
|
||||
/// dest with elements of type T.
|
||||
/// Call a function on each element after it's been copied.
|
||||
/// </summary>
|
||||
/// <param name="dest">The vector of type T to copy to</param>
|
||||
/// <param name="source">The vector of type U to copy from</param>
|
||||
/// <param name="perElementOperation">A function to call on each element after it's copied</param>
|
||||
template <typename T, typename U>
|
||||
static void CopyVec(vector<T>& dest, const vector<U>& source, std::function<void(T& t)> perElementOperation)
|
||||
/// <param name="dest">The container of type Cdest with elements of type T to copy to</param>
|
||||
/// <param name="source">The container of type Csource with elements of type U to copy from</param>
|
||||
template <typename T, typename U, typename Dalloc, typename Salloc, template <typename, typename> class Cdest, template <typename, typename> class Csource>
|
||||
static void CopyCont(Cdest<T, Dalloc>& dest, const Csource<U, Salloc>& source)
|
||||
{
|
||||
dest.clear();
|
||||
dest.resize(source.size());
|
||||
auto it1 = source.begin();
|
||||
auto it2 = dest.begin();
|
||||
|
||||
for (size_t i = 0; i < source.size(); i++)
|
||||
for (; it1 != source.end(); it1++, it2++)
|
||||
*it2 = static_cast<T>(*it1);//Valid assignment operator between T and U types must be defined somewhere.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear dest and copy all of the elements of container source with elements of type U to the container
|
||||
/// dest with elements of type T.
|
||||
/// Call a function on each element after it's been copied.
|
||||
/// </summary>
|
||||
/// <param name="dest">The container of type Cdest with elements of type T to copy to</param>
|
||||
/// <param name="source">The container of type Csource with elements of type U to copy from</param>
|
||||
/// <param name="perElementOperation">A function to call on each element after it's copied</param>
|
||||
template <typename T, typename U, typename Dalloc, typename Salloc, template <typename, typename> class Cdest, template <typename, typename> class Csource>
|
||||
static void CopyCont(Cdest<T, Dalloc>& dest, const Csource<U, Salloc>& source, std::function<void(T& t)> perElementOperation)
|
||||
{
|
||||
dest.clear();
|
||||
dest.resize(source.size());
|
||||
auto it1 = source.begin();
|
||||
auto it2 = dest.begin();
|
||||
|
||||
for (; it1 != source.end(); it1++, it2++)
|
||||
{
|
||||
dest[i] = static_cast<T>(source[i]);//Valid assignment operator between T and U types must be defined somewhere.
|
||||
perElementOperation(dest[i]);
|
||||
*it2 = static_cast<T>(*it1);//Valid assignment operator between T and U types must be defined somewhere.
|
||||
perElementOperation(*it2);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear a vector of pointers to any type by checking each element for nullptr and calling delete on it, then clearing the entire vector.
|
||||
/// Clear a container of pointers to any type by checking each element for nullptr and calling delete on it, then clearing the entire vector.
|
||||
/// Optionally call array delete if the elements themselves are pointers to dynamically allocated arrays.
|
||||
/// </summary>
|
||||
/// <param name="vec">The vector to be cleared</param>
|
||||
/// <param name="arrayDelete">Whether to call delete or delete []. Default: false.</param>
|
||||
template <typename T>
|
||||
static void ClearVec(vector<T*>& vec, bool arrayDelete = false)
|
||||
template <typename T, typename Alloc, template <typename, typename> class C>
|
||||
static void ClearVec(C<T*, Alloc>& cont, bool arrayDelete = false)
|
||||
{
|
||||
for (size_t i = 0; i < vec.size(); i++)
|
||||
for (auto& it : cont)
|
||||
{
|
||||
if (vec[i])
|
||||
if (it)
|
||||
{
|
||||
if (arrayDelete)
|
||||
delete [] vec[i];
|
||||
delete [] it;
|
||||
else
|
||||
delete vec[i];
|
||||
delete it;
|
||||
}
|
||||
|
||||
vec[i] = nullptr;
|
||||
it = nullptr;
|
||||
}
|
||||
|
||||
vec.clear();
|
||||
cont.clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine whether all elements in two containers are equal.
|
||||
/// The container types do not have to match, but their element types do.
|
||||
/// </summary>
|
||||
/// <param name="c1">The first collection to compare</param>
|
||||
/// <param name="c2">The second collection to compare</param>
|
||||
/// <returns>True if the sizes and all elements in both collections are equal, else false.</returns>
|
||||
template <typename T>
|
||||
static bool Equal(const T& c1, const T& c2)
|
||||
template <typename T, typename C1Alloc, typename C2Alloc, template <typename, typename> class C1, template <typename, typename> class C2>
|
||||
static bool Equal(const C1<T, C1Alloc>& c1, const C2<T, C2Alloc>& c2)
|
||||
{
|
||||
bool equal = c1.size() == c2.size();
|
||||
|
||||
if (equal)
|
||||
{
|
||||
for (auto it1 = c1.begin(), it2 = c2.begin(); it1 != c1.end(); ++it1, ++it2)
|
||||
auto it1 = c1.begin();
|
||||
auto it2 = c2.begin();
|
||||
|
||||
for (; it1 != c1.end(); ++it1, ++it2)
|
||||
{
|
||||
if (*it1 != *it2)
|
||||
{
|
||||
@ -443,10 +471,7 @@ static inline T Clamp(T val, T min, T max)
|
||||
}
|
||||
|
||||
template <>
|
||||
#ifdef _WIN32
|
||||
static
|
||||
#endif
|
||||
float Clamp<float>(float val, float min, float max)
|
||||
STATIC float Clamp<float>(float val, float min, float max)
|
||||
{
|
||||
if (val < min)
|
||||
return min;
|
||||
@ -459,10 +484,7 @@ float Clamp<float>(float val, float min, float max)
|
||||
}
|
||||
|
||||
template <>
|
||||
#ifdef _WIN32
|
||||
static
|
||||
#endif
|
||||
double Clamp<double>(double val, double min, double max)
|
||||
STATIC double Clamp<double>(double val, double min, double max)
|
||||
{
|
||||
if (val < min)
|
||||
return min;
|
||||
@ -512,10 +534,7 @@ static inline void ClampRef(T& val, T min, T max)
|
||||
}
|
||||
|
||||
template <>
|
||||
#ifdef _WIN32
|
||||
static
|
||||
#endif
|
||||
void ClampRef<float>(float& val, float min, float max)
|
||||
STATIC void ClampRef<float>(float& val, float min, float max)
|
||||
{
|
||||
if (val < min)
|
||||
val = min;
|
||||
@ -526,10 +545,7 @@ void ClampRef<float>(float& val, float min, float max)
|
||||
}
|
||||
|
||||
template <>
|
||||
#ifdef _WIN32
|
||||
static
|
||||
#endif
|
||||
void ClampRef<double>(double& val, double min, double max)
|
||||
STATIC void ClampRef<double>(double& val, double min, double max)
|
||||
{
|
||||
if (val < min)
|
||||
val = min;
|
||||
@ -552,20 +568,14 @@ static inline void ClampLteRef(T& val, T lte)
|
||||
}
|
||||
|
||||
template <>
|
||||
#ifdef _WIN32
|
||||
static
|
||||
#endif
|
||||
void ClampLteRef<float>(float& val, float lte)
|
||||
STATIC void ClampLteRef<float>(float& val, float lte)
|
||||
{
|
||||
if (val > lte || !std::isfinite(val))
|
||||
val = lte;
|
||||
}
|
||||
|
||||
template <>
|
||||
#ifdef _WIN32
|
||||
static
|
||||
#endif
|
||||
void ClampLteRef<double>(double& val, double lte)
|
||||
STATIC void ClampLteRef<double>(double& val, double lte)
|
||||
{
|
||||
if (val > lte || !std::isfinite(val))
|
||||
val = lte;
|
||||
@ -585,10 +595,7 @@ static inline T ClampGte(T val, T gte)
|
||||
}
|
||||
|
||||
template <>
|
||||
#ifdef _WIN32
|
||||
static
|
||||
#endif
|
||||
float ClampGte<float>(float val, float gte)
|
||||
STATIC float ClampGte<float>(float val, float gte)
|
||||
{
|
||||
if (val < gte || !std::isfinite(val))
|
||||
return gte;
|
||||
@ -597,10 +604,7 @@ float ClampGte<float>(float val, float gte)
|
||||
}
|
||||
|
||||
template <>
|
||||
#ifdef _WIN32
|
||||
static
|
||||
#endif
|
||||
double ClampGte<double>(double val, double gte)
|
||||
STATIC double ClampGte<double>(double val, double gte)
|
||||
{
|
||||
if (val < gte || !std::isfinite(val))
|
||||
return gte;
|
||||
@ -621,20 +625,14 @@ static inline void ClampGteRef(T& val, T gte)
|
||||
}
|
||||
|
||||
template <>
|
||||
#ifdef _WIN32
|
||||
static
|
||||
#endif
|
||||
void ClampGteRef<float>(float& val, float gte)
|
||||
STATIC void ClampGteRef<float>(float& val, float gte)
|
||||
{
|
||||
if (val < gte || !std::isfinite(val))
|
||||
val = gte;
|
||||
}
|
||||
|
||||
template <>
|
||||
#ifdef _WIN32
|
||||
static
|
||||
#endif
|
||||
void ClampGteRef<double>(double& val, double gte)
|
||||
STATIC void ClampGteRef<double>(double& val, double gte)
|
||||
{
|
||||
if (val < gte || !std::isfinite(val))
|
||||
val = gte;
|
||||
@ -721,19 +719,13 @@ static inline T SafeTan(T x)
|
||||
}
|
||||
|
||||
template <>
|
||||
#ifdef _WIN32
|
||||
static
|
||||
#endif
|
||||
float SafeTan<float>(float x)
|
||||
STATIC float SafeTan<float>(float x)
|
||||
{
|
||||
return std::tan(Clamp<float>(x, FLOAT_MIN_TAN, FLOAT_MAX_TAN));
|
||||
}
|
||||
|
||||
template <>
|
||||
#ifdef _WIN32
|
||||
static
|
||||
#endif
|
||||
double SafeTan<double>(double x)
|
||||
STATIC double SafeTan<double>(double x)
|
||||
{
|
||||
return std::tan(x);
|
||||
}
|
||||
@ -940,10 +932,7 @@ static inline T Arg(char* name, T def)
|
||||
/// <param name="def">The default value to return if the environment variable was not present</param>
|
||||
/// <returns>The value of the specified environment variable if found, else default</returns>
|
||||
template <>
|
||||
#ifdef _WIN32
|
||||
static
|
||||
#endif
|
||||
bool Arg<bool>(char* name, bool def)
|
||||
STATIC bool Arg<bool>(char* name, bool def)
|
||||
{
|
||||
return (Arg<int>(name, -999) != -999) ? true : def;
|
||||
}
|
||||
@ -955,10 +944,7 @@ bool Arg<bool>(char* name, bool def)
|
||||
/// <param name="def">The default value to return if the environment variable was not present</param>
|
||||
/// <returns>The value of the specified environment variable if found, else default</returns>
|
||||
template <>
|
||||
#ifdef _WIN32
|
||||
static
|
||||
#endif
|
||||
string Arg<string>(char* name, string def)
|
||||
STATIC string Arg<string>(char* name, string def)
|
||||
{
|
||||
char* ch;
|
||||
string returnVal;
|
||||
|
@ -69,9 +69,9 @@ public:
|
||||
T pe = 1,
|
||||
T pc = 0,
|
||||
T pf = 0)
|
||||
: Xform()
|
||||
|
||||
{
|
||||
Init();
|
||||
m_Weight = weight;
|
||||
m_ColorX = colorX;
|
||||
m_ColorSpeed = colorSpeed;
|
||||
@ -184,8 +184,8 @@ public:
|
||||
if (!m_ParentEmber && (typeid(T) == typeid(U)))
|
||||
m_ParentEmber = reinterpret_cast<Ember<T>*>(xform.ParentEmber());
|
||||
|
||||
CopyVec<T, U>(m_Xaos, xform.XaosVec());
|
||||
CopyVec(m_Motion, xform.m_Motion);
|
||||
CopyCont(m_Xaos, xform.XaosVec());//<T, U> needed?//TODO
|
||||
CopyCont(m_Motion, xform.m_Motion);
|
||||
m_Name = xform.m_Name;
|
||||
return *this;
|
||||
}
|
||||
|
@ -296,14 +296,15 @@ public:
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse the specified buffer and place the results in the vector of embers passed in.
|
||||
/// Parse the specified buffer and place the results in the container of embers passed in.
|
||||
/// </summary>
|
||||
/// <param name="buf">The buffer to parse</param>
|
||||
/// <param name="filename">Full path and filename, optionally empty</param>
|
||||
/// <param name="embers">The newly constructed embers based on what was parsed</param>
|
||||
/// <param name="useDefaults">True to use defaults if they are not present in the file, else false to use invalid values as placeholders to indicate the values were not present. Default: true.</param>
|
||||
/// <returns>True if there were no errors, else false.</returns>
|
||||
bool Parse(byte* buf, const char* filename, vector<Ember<T>>& embers, bool useDefaults = true)
|
||||
template <typename Alloc, template <typename, typename> class C>
|
||||
bool Parse(byte* buf, const char* filename, C<Ember<T>, Alloc>& embers, bool useDefaults = true)
|
||||
{
|
||||
char* bn;
|
||||
const char* xmlPtr;
|
||||
@ -318,7 +319,7 @@ public:
|
||||
//Parse XML string into internal document.
|
||||
xmlPtr = CX(&buf[0]);
|
||||
bufSize = strlen(xmlPtr);
|
||||
embers.reserve(bufSize / 2500);//The Xml text for an ember is around 2500 bytes, but can be much more. Pre-allocate to aovid unnecessary resizing.
|
||||
//embers.reserve(bufSize / 2500);//The Xml text for an ember is around 2500 bytes, but can be much more. Pre-allocate to aovid unnecessary resizing.
|
||||
doc = xmlReadMemory(xmlPtr, int(bufSize), filename, "ISO-8859-1", XML_PARSE_NONET);//Forbid network access during read.
|
||||
//t.Toc("xmlReadMemory");
|
||||
|
||||
@ -336,6 +337,8 @@ public:
|
||||
ScanForEmberNodes(rootnode, bn, embers, useDefaults);
|
||||
xmlFreeDoc(doc);
|
||||
emberSize = embers.size();
|
||||
auto b = embers.begin();
|
||||
auto secondToLast = Advance(embers.begin(), emberSize - 2);
|
||||
//t.Toc("ScanForEmberNodes");
|
||||
|
||||
//Check to see if the first control point or the second-to-last
|
||||
@ -343,11 +346,11 @@ public:
|
||||
//and should be reset to linear (with a warning).
|
||||
if (emberSize > 0)
|
||||
{
|
||||
if (embers[0].m_Interp == eInterp::EMBER_INTERP_SMOOTH)
|
||||
embers[0].m_Interp = eInterp::EMBER_INTERP_LINEAR;
|
||||
if (b->m_Interp == eInterp::EMBER_INTERP_SMOOTH)
|
||||
b->m_Interp = eInterp::EMBER_INTERP_LINEAR;
|
||||
|
||||
if (emberSize >= 2 && embers[emberSize - 2].m_Interp == eInterp::EMBER_INTERP_SMOOTH)
|
||||
embers[emberSize - 2].m_Interp = eInterp::EMBER_INTERP_LINEAR;
|
||||
if (emberSize >= 2 && secondToLast->m_Interp == eInterp::EMBER_INTERP_SMOOTH)
|
||||
secondToLast->m_Interp = eInterp::EMBER_INTERP_LINEAR;
|
||||
}
|
||||
|
||||
//Finally, ensure that consecutive 'rotate' parameters never exceed
|
||||
@ -355,17 +358,22 @@ public:
|
||||
//An adjustment of +/- 360 degrees is made until this is true.
|
||||
if (emberSize > 1)
|
||||
{
|
||||
for (size_t i = 1; i < emberSize; i++)
|
||||
auto prev = embers.begin();
|
||||
auto second = Advance(embers.begin(), 1);
|
||||
|
||||
for (auto it = second; it != embers.end(); ++it)
|
||||
{
|
||||
//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)
|
||||
if (prev->m_AffineInterp != eAffineInterp::AFFINE_INTERP_COMPAT && prev->m_AffineInterp != eAffineInterp::AFFINE_INTERP_OLDER)
|
||||
{
|
||||
while (embers[i].m_Rotate < embers[i - 1].m_Rotate - 180)
|
||||
embers[i].m_Rotate += 360;
|
||||
while (it->m_Rotate < prev->m_Rotate - 180)
|
||||
it->m_Rotate += 360;
|
||||
|
||||
while (embers[i].m_Rotate > embers[i - 1].m_Rotate + 180)
|
||||
embers[i].m_Rotate -= 360;
|
||||
while (it->m_Rotate > prev->m_Rotate + 180)
|
||||
it->m_Rotate -= 360;
|
||||
}
|
||||
|
||||
prev = it;
|
||||
}
|
||||
}
|
||||
|
||||
@ -373,14 +381,16 @@ public:
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse the specified file and place the results in the vector of embers passed in.
|
||||
/// Parse the specified file and place the results in the container of embers passed in.
|
||||
/// This will strip out ampersands because the Xml parser can't handle them.
|
||||
/// </summary>
|
||||
/// <param name="filename">Full path and filename</param>
|
||||
/// <param name="embers">The newly constructed embers based on what was parsed</param>
|
||||
/// <param name="useDefaults">True to use defaults if they are not present in the file, else false to use invalid values as placeholders to indicate the values were not present. Default: true.</param>
|
||||
/// <returns>True if there were no errors, else false.</returns>
|
||||
bool Parse(const char* filename, vector<Ember<T>>& embers, bool useDefaults = true)
|
||||
//template <typename T, typename Alloc, template <typename, typename> class C>
|
||||
template <typename Alloc, template <typename, typename> class C>
|
||||
bool Parse(const char* filename, C<Ember<T>, Alloc>& embers, bool useDefaults = true)
|
||||
{
|
||||
const char* loc = __FUNCTION__;
|
||||
string buf;
|
||||
@ -465,13 +475,14 @@ public:
|
||||
|
||||
private:
|
||||
/// <summary>
|
||||
/// Scan the file for ember nodes, and parse them out into the vector of embers.
|
||||
/// Scan the file for ember nodes, and parse them out into the container of embers.
|
||||
/// </summary>
|
||||
/// <param name="curNode">The current node to parse</param>
|
||||
/// <param name="parentFile">The full path and filename</param>
|
||||
/// <param name="embers">The newly constructed embers based on what was parsed</param>
|
||||
/// <param name="useDefaults">True to use defaults if they are not present in the file, else false to use invalid values as placeholders to indicate the values were not present.</param>
|
||||
void ScanForEmberNodes(xmlNode* curNode, char* parentFile, vector<Ember<T>>& embers, bool useDefaults)
|
||||
template <typename Alloc, template <typename, typename> class C>
|
||||
void ScanForEmberNodes(xmlNode* curNode, char* parentFile, C<Ember<T>, Alloc>& embers, bool useDefaults)
|
||||
{
|
||||
bool parseEmberSuccess;
|
||||
xmlNodePtr thisNode = nullptr;
|
||||
|
Reference in New Issue
Block a user