--User changes

-Add variations changes to the list of functionality that can be applied to all xforms using the Select tab.
 -Allow for graphical affine adjustments to apply to multiple selected xforms.
 -Slight optimization of the pie variation.
 -Undo state is only saved when the render completes and the mouse buttons are released. This helps avoid intermediate steps for quickly completing renders while dragging.
 -Add some keyboard shortcuts for toolbar and menu items.
 -Make info tab tree always expanded.

--Bug fixes
 -Make precalcs for all hypertile variations safer by using Zeps() for denominators.
 -Changing the current xform with more than one selected would set all xform's color index value that of the current one.
 -Use hard found palette path information for randoms as well.
 -OpenCL build and assignment errors for Z value in epispiral variation.
 -Unitialized local variables in hexaplay3D, crob, pRose3D.

--Code changes
 -Change static member variables from m_ to s_.
 -Get rid of excessive endl and replace with "\n".
 -Remove old IMAGEGL2D define from before Nvidia supported OpenCL 1.2.
 -Remove old CriticalSection code and use std::recursive_mutex.
 -Make Affine2D Rotate() and RotateTrans() take radians instead of angles.
 -More C++11 work.
 -General cleanup.
This commit is contained in:
mfeemster 2016-02-11 21:38:21 -08:00
parent a345e2d5e1
commit a800b08b67
69 changed files with 981 additions and 1094 deletions

View File

@ -208,16 +208,25 @@ void Affine2D<T>::Scale(T amount)
/// </summary> /// </summary>
/// <param name="angle">The angle to rotate by</param> /// <param name="angle">The angle to rotate by</param>
template <typename T> template <typename T>
void Affine2D<T>::Rotate(T angle) void Affine2D<T>::Rotate(T rad)
{ {
m4T origMat4 = ToMat4ColMajor(true);//Must center and use column major for glm to work. m4T origMat4 = ToMat4ColMajor(true);//Must center and use column major for glm to work.
m4T newMat4 = glm::rotate(origMat4, angle * DEG_2_RAD_T, v3T(0, 0, 1));//Assuming only rotating around z. m4T newMat4 = glm::rotate(origMat4, rad, v3T(0, 0, 1));//Assuming only rotating around z.
A(newMat4[0][0]);//Use direct assignments instead of constructor to skip assigning C and F. A(newMat4[0][0]);//Use direct assignments instead of constructor to skip assigning C and F.
B(newMat4[0][1]); B(newMat4[0][1]);
D(newMat4[1][0]); D(newMat4[1][0]);
E(newMat4[1][1]); E(newMat4[1][1]);
} }
template <typename T>
void Affine2D<T>::RotateTrans(T rad)
{
m4T origMat4 = TransToMat4ColMajor();//Only put translation in this matrix.
m4T newMat4 = glm::rotate(origMat4, rad, v3T(0, 0, 1));//Assuming only rotating around z.
C(newMat4[0][3]);//Use direct assignments instead of constructor to skip assigning A, B, D, E.
F(newMat4[1][3]);
}
/// <summary> /// <summary>
/// Move by v. /// Move by v.
/// </summary> /// </summary>
@ -341,6 +350,16 @@ typename m4T Affine2D<T>::ToMat4RowMajor(bool center) const
return mat; return mat;
} }
template <typename T>
typename m4T Affine2D<T>::TransToMat4ColMajor() const
{
m4T mat(1, 0, 0, C(), //Col0...
0, 1, 0, F(), //1
0, 0, 1, 0, //2
0, 0, 0, 1);//3
return mat;
}
/// <summary> /// <summary>
/// Accessors. /// Accessors.
/// </summary> /// </summary>
@ -366,6 +385,19 @@ template <typename T> void Affine2D<T>::X(const v2T& x) { A(x.x); D(x.y); }//X A
template <typename T> void Affine2D<T>::Y(const v2T& y) { B(y.x); E(y.y); }//Y Axis. template <typename T> void Affine2D<T>::Y(const v2T& y) { B(y.x); E(y.y); }//Y Axis.
template <typename T> void Affine2D<T>::O(const v2T& t) { C(t.x); F(t.y); }//Translation. template <typename T> void Affine2D<T>::O(const v2T& t) { C(t.x); F(t.y); }//Translation.
template <typename T>
string Affine2D<T>::ToString() const
{
ostringstream ss;
ss << "A: " << A() << " "
<< "B: " << B() << " "
<< "C: " << C()
<< "\nD: " << D() << " "
<< "E: " << E() << " "
<< "F: " << F();
return ss.str();
}
/// <summary> /// <summary>
/// Rotate and scale this affine transform and return as a copy. Orginal is unchanged. /// Rotate and scale this affine transform and return as a copy. Orginal is unchanged.
/// </summary> /// </summary>

View File

@ -77,7 +77,8 @@ public:
bool IsEmpty() const; bool IsEmpty() const;
void Scale(T amount); void Scale(T amount);
Affine2D<T> ScaleCopy(T amount); Affine2D<T> ScaleCopy(T amount);
void Rotate(T angle); void Rotate(T rad);
void RotateTrans(T rad);
void Translate(const v2T& v); void Translate(const v2T& v);
void RotateScaleXTo(const v2T& v); void RotateScaleXTo(const v2T& v);
void RotateScaleYTo(const v2T& v); void RotateScaleYTo(const v2T& v);
@ -88,6 +89,7 @@ public:
m2T ToMat2RowMajor() const; m2T ToMat2RowMajor() const;
m4T ToMat4ColMajor(bool center = false) const; m4T ToMat4ColMajor(bool center = false) const;
m4T ToMat4RowMajor(bool center = false) const; m4T ToMat4RowMajor(bool center = false) const;
m4T TransToMat4ColMajor() const;
//Note that returning a copy is actually faster than a const ref&. //Note that returning a copy is actually faster than a const ref&.
T A() const; T A() const;
@ -112,6 +114,8 @@ public:
void Y(const v2T& y); void Y(const v2T& y);
void O(const v2T& t); void O(const v2T& t);
string ToString() const;
static Affine2D CalcRotateScale(const v2T& from, const v2T& to); static Affine2D CalcRotateScale(const v2T& from, const v2T& to);
static void CalcRSAC(const v2T& from, const v2T& to, T& a, T& c); static void CalcRSAC(const v2T& from, const v2T& to, T& a, T& c);

View File

@ -99,7 +99,6 @@ public:
m_PadCarLlY = T(carToRas.PadCarLlY()); m_PadCarLlY = T(carToRas.PadCarLlY());
m_PadCarUrX = T(carToRas.PadCarUrX()); m_PadCarUrX = T(carToRas.PadCarUrX());
m_PadCarUrY = T(carToRas.PadCarUrY()); m_PadCarUrY = T(carToRas.PadCarUrY());
return *this; return *this;
} }
@ -117,29 +116,22 @@ public:
{ {
m_RasWidth = rasW; m_RasWidth = rasW;
m_RasHeight = rasH; m_RasHeight = rasH;
m_CarLlX = carLlX; m_CarLlX = carLlX;
m_CarLlY = carLlY; m_CarLlY = carLlY;
m_CarUrX = carUrX; m_CarUrX = carUrX;
m_CarUrY = carUrY; m_CarUrY = carUrY;
T carW = m_CarUrX - m_CarLlX;//Right minus left. T carW = m_CarUrX - m_CarLlX;//Right minus left.
T carH = m_CarUrY - m_CarLlY;//Top minus bottom. T carH = m_CarUrY - m_CarLlY;//Top minus bottom.
T invSizeW = T(1.0) / carW; T invSizeW = T(1.0) / carW;
T invSizeH = T(1.0) / carH; T invSizeH = T(1.0) / carH;
m_PixPerImageUnitW = static_cast<T>(rasW) * invSizeW; m_PixPerImageUnitW = static_cast<T>(rasW) * invSizeW;
m_RasLlX = m_PixPerImageUnitW * carLlX; m_RasLlX = m_PixPerImageUnitW * carLlX;
m_PixPerImageUnitH = static_cast<T>(rasH) * invSizeH; m_PixPerImageUnitH = static_cast<T>(rasH) * invSizeH;
m_RasLlY = m_PixPerImageUnitH * carLlY; m_RasLlY = m_PixPerImageUnitH * carLlY;
m_OneRow = abs(m_CarUrY - m_CarLlY) / m_RasHeight; m_OneRow = abs(m_CarUrY - m_CarLlY) / m_RasHeight;
m_OneCol = abs(m_CarUrX - m_CarLlX) / m_RasWidth; m_OneCol = abs(m_CarUrX - m_CarLlX) / m_RasWidth;
m_PadCarLlX = m_CarLlX + m_OneCol; m_PadCarLlX = m_CarLlX + m_OneCol;
m_PadCarUrX = m_CarUrX - m_OneCol; m_PadCarUrX = m_CarUrX - m_OneCol;
m_PadCarLlY = m_CarLlY + m_OneRow; m_PadCarLlY = m_CarLlY + m_OneRow;
m_PadCarUrY = m_CarUrY - m_OneRow; m_PadCarUrY = m_CarUrY - m_OneRow;
} }
@ -209,9 +201,8 @@ public:
//if (point.m_Y > m_CarLlY && point.m_Y <= m_PadCarLlY && //Mapped to top row... //if (point.m_Y > m_CarLlY && point.m_Y <= m_PadCarLlY && //Mapped to top row...
// point.m_X > m_CarLlX && point.m_X <= m_PadCarLlX)//...first col. // point.m_X > m_CarLlX && point.m_X <= m_PadCarLlX)//...first col.
//{ //{
// cout << "First pixel hit." << endl; // cout << "First pixel hit.\n";
//} //}
return point.m_X >= m_CarLlX && return point.m_X >= m_CarLlX &&
point.m_X < m_CarUrX && point.m_X < m_CarUrX &&
point.m_Y < m_CarUrY && point.m_Y < m_CarUrY &&

View File

@ -115,10 +115,8 @@ public:
T finalMinRad = m_MinRad * m_Supersample + 1;//Should scale the filter width by the oversample. T finalMinRad = m_MinRad * m_Supersample + 1;//Should scale the filter width by the oversample.
T finalMaxRad = m_MaxRad * m_Supersample + 1;//The '+1' comes from the assumed distance to the first pixel. T finalMaxRad = m_MaxRad * m_Supersample + 1;//The '+1' comes from the assumed distance to the first pixel.
GaussianFilter<T> gaussianFilter(m_MaxRad, m_Supersample); GaussianFilter<T> gaussianFilter(m_MaxRad, m_Supersample);
m_KernelSize = 0; m_KernelSize = 0;
m_MaxFilterIndex = 0; m_MaxFilterIndex = 0;
//Calculate how many filter kernels are needed based on the decay function //Calculate how many filter kernels are needed based on the decay function
// //
// num filters = (de_max_width / de_min_width)^(1 / estimator_curve) // num filters = (de_max_width / de_min_width)^(1 / estimator_curve)
@ -146,7 +144,6 @@ public:
rowSize = static_cast<int>(2 * ceil(finalMaxRad) - 1); rowSize = static_cast<int>(2 * ceil(finalMaxRad) - 1);
m_FilterWidth = (rowSize - 1) / 2; m_FilterWidth = (rowSize - 1) / 2;
m_KernelSize = (m_FilterWidth + 1) * (2 + m_FilterWidth) / 2; m_KernelSize = (m_FilterWidth + 1) * (2 + m_FilterWidth) / 2;
m_Coefs.resize(maxIndex * m_KernelSize); m_Coefs.resize(maxIndex * m_KernelSize);
m_Widths.resize(maxIndex); m_Widths.resize(maxIndex);
@ -261,7 +258,6 @@ public:
{ {
T finalMaxRad = m_MaxRad * m_Supersample + 1; T finalMaxRad = m_MaxRad * m_Supersample + 1;
T finalMinRad = m_MinRad * m_Supersample + 1; T finalMinRad = m_MinRad * m_Supersample + 1;
return std::pow(finalMaxRad / finalMinRad, T(1.0) / m_Curve) <= 1e7; return std::pow(finalMaxRad / finalMinRad, T(1.0) / m_Curve) <= 1e7;
} }
@ -273,30 +269,28 @@ public:
{ {
size_t i, j, coefIndex = 0, w = m_FilterWidth + 1; size_t i, j, coefIndex = 0, w = m_FilterWidth + 1;
stringstream ss; stringstream ss;
ss ss
<< "Density Filter:" << endl << "Density Filter:"
<< " Min radius: " << MinRad() << endl << "\n Min radius: " << MinRad()
<< " Max radius: " << MaxRad() << endl << "\n Max radius: " << MaxRad()
<< " Curve: " << Curve() << endl << "\n Curve: " << Curve()
<< " Kernel size: " << KernelSize() << endl << "\n Kernel size: " << KernelSize()
<< " Max filter index: " << MaxFilterIndex() << endl << "\n Max filter index: " << MaxFilterIndex()
<< "Max Filtered counts: " << MaxFilteredCounts() << endl << "\nMax Filtered counts: " << MaxFilteredCounts()
<< " Filter width: " << FilterWidth() << endl; << "\n Filter width: " << FilterWidth();
ss << "\nCoefficients: \n";
ss << "Coefficients: " << endl;
for (i = 0; i < m_Widths.size(); i++) for (i = 0; i < m_Widths.size(); i++)
{ {
for (coefIndex = 0; coefIndex < m_KernelSize; coefIndex++) for (coefIndex = 0; coefIndex < m_KernelSize; coefIndex++)
ss << "Kernel[" << i << "].Coefs[" << coefIndex << "]: " << m_Coefs[(i * m_KernelSize) + coefIndex] << endl; ss << "Kernel[" << i << "].Coefs[" << coefIndex << "]: " << m_Coefs[(i * m_KernelSize) + coefIndex] << "\n";
} }
ss << endl << "Widths: " << endl; ss << "\nWidths: \n";
for (i = 0; i < m_Widths.size(); i++) for (i = 0; i < m_Widths.size(); i++)
{ {
ss << "Widths[" << i << "]: " << m_Widths[i] << endl; ss << "Widths[" << i << "]: " << m_Widths[i] << "\n";
} }
for (i = 0; i < w; i++) for (i = 0; i < w; i++)
@ -306,7 +300,7 @@ public:
cout << std::setw(2) << std::setfill('0') << m_CoefIndices[i * w + j] << "\t"; cout << std::setw(2) << std::setfill('0') << m_CoefIndices[i * w + j] << "\t";
} }
cout << endl; cout << "\n";
} }
return ss.str(); return ss.str();

View File

@ -5,7 +5,7 @@
namespace EmberNs namespace EmberNs
{ {
template<> unique_ptr<QTIsaac<ISAAC_SIZE, ISAAC_INT>> QTIsaac<ISAAC_SIZE, ISAAC_INT>::GlobalRand = unique_ptr<QTIsaac<ISAAC_SIZE, ISAAC_INT>>(new QTIsaac<ISAAC_SIZE, ISAAC_INT>()); template<> unique_ptr<QTIsaac<ISAAC_SIZE, ISAAC_INT>> QTIsaac<ISAAC_SIZE, ISAAC_INT>::GlobalRand = unique_ptr<QTIsaac<ISAAC_SIZE, ISAAC_INT>>(new QTIsaac<ISAAC_SIZE, ISAAC_INT>());
template<> CriticalSection QTIsaac<ISAAC_SIZE, ISAAC_INT>::m_CS = CriticalSection(); template<> std::recursive_mutex QTIsaac<ISAAC_SIZE, ISAAC_INT>::s_CS = std::recursive_mutex();
} }
#include "Curves.h" #include "Curves.h"
@ -56,7 +56,7 @@ uint Timing::m_ProcessorCount;
#define EXPORT_SINGLE_TYPE_EMBER(T) \ #define EXPORT_SINGLE_TYPE_EMBER(T) \
template<> const char* PaletteList<T>::m_DefaultFilename = "flam3-palettes.xml"; \ template<> const char* PaletteList<T>::m_DefaultFilename = "flam3-palettes.xml"; \
template<> map<string, vector<Palette<T>>> PaletteList<T>::m_Palettes = map<string, vector<Palette<T>>>(); \ template<> map<string, vector<Palette<T>>> PaletteList<T>::s_Palettes = map<string, vector<Palette<T>>>(); \
template<> bool XmlToEmber<T>::m_Init = false; \ template<> bool XmlToEmber<T>::m_Init = false; \
template<> vector<string> XmlToEmber<T>::m_FlattenNames = vector<string>(); \ template<> vector<string> XmlToEmber<T>::m_FlattenNames = vector<string>(); \
template<> unordered_map<string, string> XmlToEmber<T>::m_BadParamNames = unordered_map<string, string>(); \ template<> unordered_map<string, string> XmlToEmber<T>::m_BadParamNames = unordered_map<string, string>(); \

View File

@ -1034,7 +1034,7 @@ public:
if (m_Xforms[i].Empty() && m_AffineInterp != eAffineInterp::AFFINE_INTERP_LOG) if (m_Xforms[i].Empty() && m_AffineInterp != eAffineInterp::AFFINE_INTERP_LOG)
continue; continue;
m_Xforms[i].m_Affine.Rotate(angle); m_Xforms[i].m_Affine.Rotate(angle * DEG_2_RAD_T);
//Don't rotate post. //Don't rotate post.
} }
} }

View File

@ -74,6 +74,7 @@ namespace EmberNs
#define EMPTYFIELD -9999 #define EMPTYFIELD -9999
typedef std::chrono::high_resolution_clock Clock; typedef std::chrono::high_resolution_clock Clock;
typedef uint et; typedef uint et;
typedef std::lock_guard <std::recursive_mutex> rlg;
/// <summary> /// <summary>
/// Thin wrapper around getting the current time in milliseconds. /// Thin wrapper around getting the current time in milliseconds.

View File

@ -46,6 +46,7 @@
#include <map> #include <map>
#include <math.h> #include <math.h>
#include <memory> #include <memory>
#include <mutex>
#include <numeric> #include <numeric>
#include <ostream> #include <ostream>
#include <sstream> #include <sstream>

View File

@ -116,18 +116,18 @@ public:
} }
else else
{ {
cout << "Error: Writing flame " << filename << " failed." << endl; cout << "Error: Writing flame " << filename << " failed.\n";
b = false; b = false;
} }
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
cout << "Error: Writing flame " << filename << " failed: " << e.what() << endl; cout << "Error: Writing flame " << filename << " failed: " << e.what() << "\n";
b = false; b = false;
} }
catch (...) catch (...)
{ {
cout << "Error: Writing flame " << filename << " failed." << endl; cout << "Error: Writing flame " << filename << " failed.\n";
b = false; b = false;
} }
@ -275,7 +275,7 @@ public:
os << hex << setw(2) << setfill('0') << int(std::rint(ember.m_Palette[idx][2] * 255)); os << hex << setw(2) << setfill('0') << int(std::rint(ember.m_Palette[idx][2] * 255));
} }
os << endl; os << "\n";
} }
os << " </palette>\n"; os << " </palette>\n";
@ -472,7 +472,7 @@ public:
} }
else else
{ {
cout << "Failed to parse comment into Xml." << endl; cout << "Failed to parse comment into Xml.\n";
} }
} }

View File

@ -639,7 +639,7 @@ public:
} }
else else
{ {
cout << loc << ": xform " << xfi << " is missing when it was expected, something is severely wrong." << endl; cout << loc << ": xform " << xfi << " is missing when it was expected, something is severely wrong.\n";
} }
} }
@ -684,7 +684,7 @@ public:
} }
else else
{ {
cout << loc << ": xform " << xfi << " is missing when it was expected, something is severely wrong." << endl; cout << loc << ": xform " << xfi << " is missing when it was expected, something is severely wrong.\n";
} }
} }
} }

View File

@ -65,7 +65,7 @@ public:
/// </summary> /// </summary>
static unique_ptr<QTIsaac<ALPHA, ISAAC_INT>> GlobalRand; static unique_ptr<QTIsaac<ALPHA, ISAAC_INT>> GlobalRand;
static CriticalSection m_CS; static std::recursive_mutex s_CS;
/// <summary> /// <summary>
/// The structure which holds all of the random information. /// The structure which holds all of the random information.
@ -124,9 +124,8 @@ public:
/// <returns>The next random integer in the range of 0-255</returns> /// <returns>The next random integer in the range of 0-255</returns>
static inline T LockedRandByte() static inline T LockedRandByte()
{ {
m_CS.Enter(); rlg l(s_CS);
T t = GlobalRand->RandByte(); T t = GlobalRand->RandByte();
m_CS.Leave();
return t; return t;
} }
@ -149,9 +148,8 @@ public:
/// <returns>The next random integer</returns> /// <returns>The next random integer</returns>
static inline T LockedRand() static inline T LockedRand()
{ {
m_CS.Enter(); rlg l(s_CS);
T t = GlobalRand->Rand(); T t = GlobalRand->Rand();
m_CS.Leave();
return t; return t;
} }
@ -172,9 +170,8 @@ public:
/// <returns>A value between 0 and the value passed in minus 1</returns> /// <returns>A value between 0 and the value passed in minus 1</returns>
static inline T LockedRand(T upper) static inline T LockedRand(T upper)
{ {
m_CS.Enter(); rlg l(s_CS);
T t = GlobalRand->Rand(upper); T t = GlobalRand->Rand(upper);
m_CS.Leave();
return t; return t;
} }
@ -201,9 +198,8 @@ public:
template<typename floatType> template<typename floatType>
static inline floatType LockedFrand(floatType fMin, floatType fMax) static inline floatType LockedFrand(floatType fMin, floatType fMax)
{ {
m_CS.Enter(); rlg l(s_CS);
floatType t = GlobalRand->template Frand<floatType>(fMin, fMax); floatType t = GlobalRand->template Frand<floatType>(fMin, fMax);
m_CS.Leave();
return t; return t;
} }
@ -229,9 +225,8 @@ public:
template<typename floatType> template<typename floatType>
static inline floatType LockedFrand01() static inline floatType LockedFrand01()
{ {
m_CS.Enter(); rlg l(s_CS);
floatType t = GlobalRand->template Frand01<floatType>(); floatType t = GlobalRand->template Frand01<floatType>();
m_CS.Leave();
return t; return t;
} }
@ -257,9 +252,8 @@ public:
template<typename floatType> template<typename floatType>
static inline floatType LockedFrand11() static inline floatType LockedFrand11()
{ {
m_CS.Enter(); rlg l(s_CS);
floatType t = GlobalRand->template Frand11<floatType>(); floatType t = GlobalRand->template Frand11<floatType>();
m_CS.Leave();
return t; return t;
} }
@ -280,9 +274,8 @@ public:
template<typename floatType> template<typename floatType>
static inline floatType LockedGoldenBit() static inline floatType LockedGoldenBit()
{ {
m_CS.Enter(); rlg l(s_CS);
floatType t = GlobalRand->template GoldenBit<floatType>(); floatType t = GlobalRand->template GoldenBit<floatType>();
m_CS.Leave();
return t; return t;
} }
@ -301,9 +294,8 @@ public:
/// <returns>A random 0 or 1</returns> /// <returns>A random 0 or 1</returns>
static inline uint LockedRandBit() static inline uint LockedRandBit()
{ {
m_CS.Enter(); rlg l(s_CS);
uint t = GlobalRand->RandBit(); uint t = GlobalRand->RandBit();
m_CS.Leave();
return t; return t;
} }
@ -329,7 +321,6 @@ public:
T a, b, c, d, e, f, g, h; T a, b, c, d, e, f, g, h;
T* m = ctx->randmem; T* m = ctx->randmem;
T* r = ctx->randrsl; T* r = ctx->randrsl;
a = b = c = d = e = f = g = h = GOLDEN_RATIO; a = b = c = d = e = f = g = h = GOLDEN_RATIO;
if (!useSeed) if (!useSeed)
@ -352,9 +343,7 @@ public:
{ {
a += r[i ]; b += r[i + 1]; c += r[i + 2]; d += r[i + 3]; a += r[i ]; b += r[i + 1]; c += r[i + 2]; d += r[i + 3];
e += r[i + 4]; f += r[i + 5]; g += r[i + 6]; h += r[i + 7]; e += r[i + 4]; f += r[i + 5]; g += r[i + 6]; h += r[i + 7];
Shuffle(a, b, c, d, e, f, g, h); Shuffle(a, b, c, d, e, f, g, h);
m[i ] = a; m[i + 1] = b; m[i + 2] = c; m[i + 3] = d; m[i ] = a; m[i + 1] = b; m[i + 2] = c; m[i + 3] = d;
m[i + 4] = e; m[i + 5] = f; m[i + 6] = g; m[i + 7] = h; m[i + 4] = e; m[i + 5] = f; m[i + 6] = g; m[i + 7] = h;
} }
@ -364,9 +353,7 @@ public:
{ {
a += m[i ]; b += m[i + 1]; c += m[i + 2]; d += m[i + 3]; a += m[i ]; b += m[i + 1]; c += m[i + 2]; d += m[i + 3];
e += m[i + 4]; f += m[i + 5]; g += m[i + 6]; h += m[i + 7]; e += m[i + 4]; f += m[i + 5]; g += m[i + 6]; h += m[i + 7];
Shuffle(a, b, c, d, e, f, g, h); Shuffle(a, b, c, d, e, f, g, h);
m[i ] = a; m[i + 1] = b; m[i + 2] = c; m[i + 3] = d; m[i ] = a; m[i + 1] = b; m[i + 2] = c; m[i + 3] = d;
m[i + 4] = e; m[i + 5] = f; m[i + 6] = g; m[i + 7] = h; m[i + 4] = e; m[i + 5] = f; m[i + 6] = g; m[i + 7] = h;
} }
@ -375,7 +362,6 @@ public:
{ {
//Fill in mm[] with messy stuff. //Fill in mm[] with messy stuff.
Shuffle(a, b, c, d, e, f, g, h); Shuffle(a, b, c, d, e, f, g, h);
m[i ] = a; m[i + 1] = b; m[i + 2] = c; m[i + 3] = d; m[i ] = a; m[i + 1] = b; m[i + 2] = c; m[i + 3] = d;
m[i + 4] = e; m[i + 5] = f; m[i + 6] = g; m[i + 7] = h; m[i + 4] = e; m[i + 5] = f; m[i + 6] = g; m[i + 7] = h;
} }
@ -406,6 +392,7 @@ public:
} }
#ifndef ISAAC_FLAM3_DEBUG #ifndef ISAAC_FLAM3_DEBUG
if (a == 0 && b == 0 && c == 0) if (a == 0 && b == 0 && c == 0)
{ {
m_Rc.randa = static_cast<T>(NowMs()); m_Rc.randa = static_cast<T>(NowMs());
@ -431,13 +418,10 @@ protected:
void Isaac(randctx* ctx) void Isaac(randctx* ctx)
{ {
T x, y; T x, y;
T* mm = ctx->randmem; T* mm = ctx->randmem;
T* r = ctx->randrsl; T* r = ctx->randrsl;
T a = (ctx->randa); T a = (ctx->randa);
T b = (ctx->randb + (++ctx->randc)); T b = (ctx->randb + (++ctx->randc));
T* m = mm; T* m = mm;
T* m2 = (m + (N / 2)); T* m2 = (m + (N / 2));
T* mend = m2; T* mend = m2;

View File

@ -38,7 +38,7 @@ public:
bool Add(const string& filename, bool force = false) bool Add(const string& filename, bool force = false)
{ {
bool added = true; bool added = true;
auto palettes = m_Palettes.insert(make_pair(filename, vector<Palette<T>>())); auto palettes = s_Palettes.insert(make_pair(filename, vector<Palette<T>>()));
if (force || palettes.second) if (force || palettes.second)
{ {
@ -53,7 +53,6 @@ public:
{ {
auto rootNode = xmlDocGetRootElement(doc); auto rootNode = xmlDocGetRootElement(doc);
auto pfilename = shared_ptr<string>(new string(filename)); auto pfilename = shared_ptr<string>(new string(filename));
palettes.first->second.clear(); palettes.first->second.clear();
palettes.first->second.reserve(buf.size() / 2048);//Roughly what it takes per palette. palettes.first->second.reserve(buf.size() / 2048);//Roughly what it takes per palette.
ParsePalettes(rootNode, pfilename, palettes.first->second); ParsePalettes(rootNode, pfilename, palettes.first->second);
@ -62,14 +61,14 @@ public:
else else
{ {
added = false; added = false;
m_Palettes.erase(filename); s_Palettes.erase(filename);
AddToReport(string(loc) + " : Couldn't load xml doc"); AddToReport(string(loc) + " : Couldn't load xml doc");
} }
} }
else else
{ {
added = false; added = false;
m_Palettes.erase(filename); s_Palettes.erase(filename);
AddToReport(string(loc) + " : Couldn't read palette file " + filename); AddToReport(string(loc) + " : Couldn't read palette file " + filename);
} }
} }
@ -82,11 +81,11 @@ public:
/// </summary> /// </summary>
Palette<T>* GetRandomPalette() Palette<T>* GetRandomPalette()
{ {
auto p = m_Palettes.begin(); auto p = s_Palettes.begin();
size_t i = 0, paletteFileIndex = QTIsaac<ISAAC_SIZE, ISAAC_INT>::GlobalRand->Rand() % Size(); size_t i = 0, paletteFileIndex = QTIsaac<ISAAC_SIZE, ISAAC_INT>::GlobalRand->Rand() % Size();
//Move p forward i elements. //Move p forward i elements.
while (i < paletteFileIndex && p != m_Palettes.end()) while (i < paletteFileIndex && p != s_Palettes.end())
{ {
++i; ++i;
++p; ++p;
@ -111,7 +110,7 @@ public:
/// <returns>A pointer to the requested palette if the index was in range, else nullptr.</returns> /// <returns>A pointer to the requested palette if the index was in range, else nullptr.</returns>
Palette<T>* GetPalette(const string& filename, size_t i) Palette<T>* GetPalette(const string& filename, size_t i)
{ {
auto& palettes = m_Palettes[filename]; auto& palettes = s_Palettes[filename];
if (!palettes.empty() && i < palettes.size()) if (!palettes.empty() && i < palettes.size())
return &palettes[i]; return &palettes[i];
@ -127,7 +126,7 @@ public:
/// <returns>A pointer to the palette if found, else nullptr</returns> /// <returns>A pointer to the palette if found, else nullptr</returns>
Palette<T>* GetPaletteByName(const string& filename, const string& name) Palette<T>* GetPaletteByName(const string& filename, const string& name)
{ {
for (auto& palettes : m_Palettes) for (auto& palettes : s_Palettes)
if (palettes.first == filename) if (palettes.first == filename)
for (auto& palette : palettes.second) for (auto& palette : palettes.second)
if (palette.m_Name == name) if (palette.m_Name == name)
@ -163,7 +162,7 @@ public:
/// </summary> /// </summary>
void Clear() void Clear()
{ {
m_Palettes.clear(); s_Palettes.clear();
} }
/// <summary> /// <summary>
@ -171,7 +170,7 @@ public:
/// This will be the number of files read. /// This will be the number of files read.
/// </summary> /// </summary>
/// <returns>The size of the palettes map</returns> /// <returns>The size of the palettes map</returns>
size_t Size() { return m_Palettes.size(); } size_t Size() { return s_Palettes.size(); }
/// <summary> /// <summary>
/// Get the size of specified palette vector in the palettes map. /// Get the size of specified palette vector in the palettes map.
@ -181,9 +180,9 @@ public:
size_t Size(size_t index) size_t Size(size_t index)
{ {
size_t i = 0; size_t i = 0;
auto p = m_Palettes.begin(); auto p = s_Palettes.begin();
while (i < index && p != m_Palettes.end()) while (i < index && p != s_Palettes.end())
{ {
++i; ++i;
++p; ++p;
@ -199,7 +198,7 @@ public:
/// <returns>The size of the palette vector at the specified index in the palettes map</returns> /// <returns>The size of the palette vector at the specified index in the palettes map</returns>
size_t Size(const string& s) size_t Size(const string& s)
{ {
return m_Palettes[s].size(); return s_Palettes[s].size();
} }
/// <summary> /// <summary>
@ -210,9 +209,9 @@ public:
const string& Name(size_t index) const string& Name(size_t index)
{ {
size_t i = 0; size_t i = 0;
auto p = m_Palettes.begin(); auto p = s_Palettes.begin();
while (i < index && p != m_Palettes.end()) while (i < index && p != s_Palettes.end())
{ {
++i; ++i;
++p; ++p;
@ -274,9 +273,9 @@ private:
palette[colorCount].r = T(r) / T(255);//Store as normalized colors in the range of 0-1. palette[colorCount].r = T(r) / T(255);//Store as normalized colors in the range of 0-1.
palette[colorCount].g = T(g) / T(255); palette[colorCount].g = T(g) / T(255);
palette[colorCount].b = T(b) / T(255); palette[colorCount].b = T(b) / T(255);
colorCount++; colorCount++;
} while (colorCount < COLORMAP_LENGTH); }
while (colorCount < COLORMAP_LENGTH);
} }
else if (!Compare(attr->name, "number")) else if (!Compare(attr->name, "number"))
{ {
@ -306,6 +305,6 @@ private:
} }
} }
static map<string, vector<Palette<T>>> m_Palettes;//The map of filenames to vectors that store the palettes. static map<string, vector<Palette<T>>> s_Palettes;//The map of filenames to vectors that store the palettes.
}; };
} }

View File

@ -139,7 +139,7 @@ void Renderer<T, bucketT>::ComputeCamera()
T carUrX = m_UpperRightX + t0; T carUrX = m_UpperRightX + t0;
T carUrY = m_UpperRightY + t1 + shift; T carUrY = m_UpperRightY + t1 + shift;
m_RotMat.MakeID(); m_RotMat.MakeID();
m_RotMat.Rotate(-Rotate()); m_RotMat.Rotate(-Rotate() * DEG_2_RAD_T);
m_CarToRas.Init(carLlX, carLlY, carUrX, carUrY, m_SuperRasW, m_SuperRasH, PixelAspectRatio()); m_CarToRas.Init(carLlX, carLlY, carUrX, carUrY, m_SuperRasW, m_SuperRasH, PixelAspectRatio());
} }
@ -215,8 +215,6 @@ bool Renderer<T, bucketT>::CreateDEFilter(bool& newAlloc)
if (!m_DensityFilter.get()) { return false; }//Did object creation succeed? if (!m_DensityFilter.get()) { return false; }//Did object creation succeed?
if (!m_DensityFilter->Create()) { return false; }//Object creation succeeded, did filter 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?
} }
@ -1299,7 +1297,7 @@ EmberStats Renderer<T, bucketT>::Iterate(size_t iterCount, size_t temporalSample
//iterationTime += t.Toc(); //iterationTime += t.Toc();
if (m_LockAccum) if (m_LockAccum)
m_AccumCs.Enter(); m_AccumCs.lock();
//t.Tic(); //t.Tic();
//Map temp buffer samples into the histogram using the palette for color. //Map temp buffer samples into the histogram using the palette for color.
@ -1307,7 +1305,7 @@ EmberStats Renderer<T, bucketT>::Iterate(size_t iterCount, size_t temporalSample
//accumulationTime += t.Toc(); //accumulationTime += t.Toc();
if (m_LockAccum) if (m_LockAccum)
m_AccumCs.Leave(); m_AccumCs.unlock();
if (m_Callback && threadIndex == 0) if (m_Callback && threadIndex == 0)
{ {

View File

@ -263,12 +263,12 @@ size_t RendererBase::MemoryAvailable()
} }
else else
{ {
cout << "Warning: unable to determine physical memory." << endl; cout << "Warning: unable to determine physical memory.\n";
memAvailable = 4e9; memAvailable = 4e9;
} }
#else #else
cout << "Warning: unable to determine physical memory." << endl; cout << "Warning: unable to determine physical memory.\n";
memAvailable = 4e9; memAvailable = 4e9;
#endif #endif
return memAvailable; return memAvailable;
@ -610,14 +610,14 @@ void RendererBase::Reset()
m_ProcessAction = eProcessAction::FULL_RENDER; m_ProcessAction = eProcessAction::FULL_RENDER;
} }
void RendererBase::EnterRender() { m_RenderingCs.Enter(); } void RendererBase::EnterRender() { m_RenderingCs.lock(); }
void RendererBase::LeaveRender() { m_RenderingCs.Leave(); } void RendererBase::LeaveRender() { m_RenderingCs.unlock(); }
void RendererBase::EnterFinalAccum() { m_FinalAccumCs.Enter(); m_InFinalAccum = true; } void RendererBase::EnterFinalAccum() { m_FinalAccumCs.lock(); m_InFinalAccum = true; }
void RendererBase::LeaveFinalAccum() { m_FinalAccumCs.Leave(); m_InFinalAccum = false; } void RendererBase::LeaveFinalAccum() { m_FinalAccumCs.unlock(); m_InFinalAccum = false; }
void RendererBase::EnterResize() { m_ResizeCs.Enter(); } void RendererBase::EnterResize() { m_ResizeCs.lock(); }
void RendererBase::LeaveResize() { m_ResizeCs.Leave(); } void RendererBase::LeaveResize() { m_ResizeCs.unlock(); }
void RendererBase::Abort() { m_Abort = true; } void RendererBase::Abort() { m_Abort = true; }
bool RendererBase::Aborted() { return m_Abort; } bool RendererBase::Aborted() { return m_Abort; }

View File

@ -228,7 +228,7 @@ protected:
vector<size_t> m_BadVals; vector<size_t> m_BadVals;
vector<QTIsaac<ISAAC_SIZE, ISAAC_INT>> m_Rand; vector<QTIsaac<ISAAC_SIZE, ISAAC_INT>> m_Rand;
auto_ptr<tbb::task_group> m_TaskGroup; auto_ptr<tbb::task_group> m_TaskGroup;
CriticalSection m_RenderingCs, m_AccumCs, m_FinalAccumCs, m_ResizeCs; std::recursive_mutex m_RenderingCs, m_AccumCs, m_FinalAccumCs, m_ResizeCs;
Timing m_RenderTimer, m_IterTimer, m_ProgressTimer; Timing m_RenderTimer, m_IterTimer, m_ProgressTimer;
}; };
} }

View File

@ -804,7 +804,7 @@ public:
if (best < 0) if (best < 0)
{ {
cout << "Error in TryColors(), skipping ImproveColors()" << endl; cout << "Error in TryColors(), skipping ImproveColors()\n";
return; return;
} }
@ -815,7 +815,7 @@ public:
if (b < 0) if (b < 0)
{ {
cout << "Error in TryColors, aborting tries." << endl; cout << "Error in TryColors, aborting tries.\n";
break; break;
} }
@ -861,7 +861,7 @@ public:
if (m_Renderer->Run(m_FinalImage) != eRenderStatus::RENDER_OK) if (m_Renderer->Run(m_FinalImage) != eRenderStatus::RENDER_OK)
{ {
cout << "Error rendering test image for TryColors(). Aborting." << endl; cout << "Error rendering test image for TryColors(). Aborting.\n";
return -1; return -1;
} }
@ -902,7 +902,7 @@ public:
else else
{ {
ember.m_Palette.Clear(false); ember.m_Palette.Clear(false);
cout << "Error retrieving random palette, setting to all white" << endl; cout << "Error retrieving random palette, setting to all white.\n";
} }
} }

View File

@ -159,18 +159,18 @@ public:
size_t i; size_t i;
stringstream ss; stringstream ss;
ss ss
<< "Spatial Filter:" << endl << "Spatial Filter:"
<< " Support: " << m_Support << endl << "\n Support: " << m_Support
<< " Filter radius: " << m_FilterRadius << endl << "\n Filter radius: " << m_FilterRadius
<< " Supersample: " << m_Supersample << endl << "\n Supersample: " << m_Supersample
<< "Pixel aspect ratio: " << m_PixelAspectRatio << endl << "\nPixel aspect ratio: " << m_PixelAspectRatio
<< "Final filter width: " << m_FinalFilterWidth << endl << "\nFinal filter width: " << m_FinalFilterWidth
<< "Filter buffer size: " << m_Filter.size() << endl; << "\nFilter buffer size: " << m_Filter.size();
ss << "Filter: " << endl; ss << "\nFilter: \n";
for (i = 0; i < m_Filter.size(); i++) for (i = 0; i < m_Filter.size(); i++)
{ {
ss << "Filter[" << i << "]: " << m_Filter[i] << endl; ss << "Filter[" << i << "]: " << m_Filter[i] << "\n";
} }
return ss.str(); return ss.str();

View File

@ -115,22 +115,22 @@ public:
{ {
size_t i; size_t i;
stringstream ss; stringstream ss;
ss << "Temporal Filter:" << endl ss << "Temporal Filter:\n"
<< " Size: " << Size() << endl << "\n Size: " << Size()
<< " Type: " << TemporalFilterCreator<T>::ToString(m_FilterType) << endl << "\n Type: " << TemporalFilterCreator<T>::ToString(m_FilterType)
<< " Sum Filt: " << SumFilt() << endl; << "\n Sum Filt: " << SumFilt();
ss << "Deltas: " << endl; ss << "\nDeltas: \n";
for (i = 0; i < m_Deltas.size(); i++) for (i = 0; i < m_Deltas.size(); i++)
{ {
ss << "Deltas[" << i << "]: " << m_Deltas[i] << endl; ss << "Deltas[" << i << "]: " << m_Deltas[i] << "\n";
} }
ss << "Filter: " << endl; ss << "Filter: \n";
for (i = 0; i < m_Filter.size(); i++) for (i = 0; i < m_Filter.size(); i++)
{ {
ss << "Filter[" << i << "]: " << m_Filter[i] << endl; ss << "Filter[" << i << "]: " << m_Filter[i] << "\n";
} }
return ss.str(); return ss.str();

View File

@ -52,7 +52,7 @@ public:
if (str) if (str)
{ {
cout << string(str) << (fullString ? "" : " processing time: ") << Format(ms) << endl; cout << string(str) << (fullString ? "" : " processing time: ") << Format(ms) << "\n";
} }
return ms; return ms;
@ -77,7 +77,6 @@ public:
double ElapsedTime() const double ElapsedTime() const
{ {
duration<double> elapsed = duration_cast<milliseconds, Clock::rep, Clock::period>(m_EndTime - m_BeginTime); duration<double> elapsed = duration_cast<milliseconds, Clock::rep, Clock::period>(m_EndTime - m_BeginTime);
return elapsed.count() * 1000.0; return elapsed.count() * 1000.0;
} }
@ -92,7 +91,6 @@ public:
string Format(double ms) const string Format(double ms) const
{ {
stringstream ss; stringstream ss;
double x = ms / 1000; double x = ms / 1000;
double secs = fmod(x, 60); double secs = fmod(x, 60);
x /= 60; x /= 60;
@ -146,78 +144,4 @@ private:
static bool m_TimingInit;//Whether the performance info has bee queried. static bool m_TimingInit;//Whether the performance info has bee queried.
static uint m_ProcessorCount;//The number of cores on the system, set in Init(). static uint m_ProcessorCount;//The number of cores on the system, set in Init().
}; };
/// <summary>
/// Cross platform critical section class which can be used for thread locking.
/// </summary>
class EMBER_API CriticalSection
{
public:
#ifdef _WIN32
/// <summary>
/// Constructor which initialized the underlying CRITICAL_SECTION object.
/// </summary>
CriticalSection() { InitializeCriticalSection(&m_CriticalSection); }
/// <summary>
/// Constructor which initialized the underlying CRITICAL_SECTION object
/// with the specified spin count value.
/// </summary>
/// <param name="spinCount">The spin count.</param>
CriticalSection(DWORD spinCount) { InitializeCriticalSectionAndSpinCount(&m_CriticalSection, spinCount); }
/// <summary>
/// Deletes the underlying CRITICAL_SECTION object.
/// </summary>
~CriticalSection() { DeleteCriticalSection(&m_CriticalSection); }
/// <summary>
/// Lock the critical section.
/// </summary>
void Enter() { EnterCriticalSection(&m_CriticalSection); }
/// <summary>
/// Unlock the critical section.
/// </summary>
void Leave() { LeaveCriticalSection(&m_CriticalSection); }
private:
CRITICAL_SECTION m_CriticalSection;//The Windows specific critical section object.
#else
/// <summary>
/// Constructor which initialized the underlying pthread_mutex_t object.
/// </summary>
CriticalSection()
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
pthread_mutex_init(&m_CriticalSection, &attr);
pthread_mutexattr_destroy(&attr);
}
/// <summary>
/// Deletes the underlying pthread_mutex_t object.
/// </summary>
~CriticalSection() { pthread_mutex_destroy(&m_CriticalSection); }
/// <summary>
/// Lock the critical section.
/// </summary>
void Enter() { pthread_mutex_lock(&m_CriticalSection); }
/// <summary>
/// Unlock the critical section.
/// </summary>
void Leave() { pthread_mutex_unlock(&m_CriticalSection); }
private:
pthread_mutex_t m_CriticalSection;//The *nix/pthread specific critical section object.
#endif
};
} }

View File

@ -169,7 +169,7 @@ public:
{ {
stringstream ss; stringstream ss;
for (auto& s : errorReport) ss << s << endl; for (auto& s : errorReport) ss << s << "\n";
return ss.str(); return ss.str();
} }
@ -288,12 +288,12 @@ static bool ReadFile(const char* filename, string& buf, bool nullTerminate = tru
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
cout << "Error: Reading file " << filename << " failed: " << e.what() << endl; cout << "Error: Reading file " << filename << " failed: " << e.what() << "\n";
b = false; b = false;
} }
catch (...) catch (...)
{ {
cout << "Error: Reading file " << filename << " failed." << endl; cout << "Error: Reading file " << filename << " failed.\n";
b = false; b = false;
} }

View File

@ -288,7 +288,7 @@ public:
//released under CC share-alike license. //released under CC share-alike license.
//Less accurate for faster rendering (still very precise). //Less accurate for faster rendering (still very precise).
T const CA = T(0.0003);//The accuracy is the square of CA. T const CA = T(0.0003);//The accuracy is the square of CA.
T a, b, c, d, em[13], en[13]; T a, b, c, d = 1, em[13], en[13];
int bo; int bo;
int l; int l;
int ii; int ii;

View File

@ -2023,9 +2023,9 @@ public:
virtual string ToString() const override virtual string ToString() const override
{ {
ostringstream ss; ostringstream ss;
ss << Variation<T>::ToString() << endl; ss << Variation<T>::ToString() << "\n";
for (auto& param : m_Params) ss << param.ToString() << endl; for (auto& param : m_Params) ss << param.ToString() << "\n";
return ss.str(); return ss.str();
} }

View File

@ -1971,7 +1971,7 @@ public:
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
{ {
int sl = int(rand.Frand01<T>() * m_Slices + T(0.5)); int sl = int(rand.Frand01<T>() * m_Slices + T(0.5));
T a = m_Rotation + M_2PI * (sl + rand.Frand01<T>() * m_Thickness) / m_Slices; T a = m_Rotation + m_Pi2Slices * (sl + m_Thickness * rand.Frand01<T>());
T r = m_Weight * rand.Frand01<T>(); T r = m_Weight * rand.Frand01<T>();
helper.Out.x = r * std::cos(a); helper.Out.x = r * std::cos(a);
helper.Out.y = r * std::sin(a); helper.Out.y = r * std::sin(a);
@ -1987,9 +1987,10 @@ public:
string slices = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string slices = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string rotation = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string rotation = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string thickness = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string thickness = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string pi2Slices = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n" ss << "\t{\n"
<< "\t\tint sl = (int)(MwcNext01(mwc) * " << slices << " + (real_t)(0.5));\n" << "\t\tint sl = (int)(MwcNext01(mwc) * " << slices << " + (real_t)(0.5));\n"
<< "\t\treal_t a = " << rotation << " + M_2PI * (sl + MwcNext01(mwc) * " << thickness << ") / " << slices << ";\n" << "\t\treal_t a = " << rotation << " + " << pi2Slices << " * (sl + " << thickness << " * MwcNext01(mwc));\n"
<< "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] * MwcNext01(mwc);\n" << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] * MwcNext01(mwc);\n"
<< "\n" << "\n"
<< "\t\tvOut.x = r * cos(a);\n" << "\t\tvOut.x = r * cos(a);\n"
@ -1999,6 +2000,11 @@ public:
return ss.str(); return ss.str();
} }
virtual void Precalc() override
{
m_Pi2Slices = M_2PI / m_Slices;
}
virtual void Random(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override virtual void Random(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
{ {
m_Params[0].Set(10 * rand.Frand01<T>());//Slices. m_Params[0].Set(10 * rand.Frand01<T>());//Slices.
@ -2014,12 +2020,14 @@ protected:
m_Params.push_back(ParamWithName<T>(&m_Slices, prefix + "pie_slices", 6, eParamType::INTEGER_NONZERO, 1)); m_Params.push_back(ParamWithName<T>(&m_Slices, prefix + "pie_slices", 6, eParamType::INTEGER_NONZERO, 1));
m_Params.push_back(ParamWithName<T>(&m_Rotation, prefix + "pie_rotation", T(0.5), eParamType::REAL_CYCLIC, 0, M_2PI)); m_Params.push_back(ParamWithName<T>(&m_Rotation, prefix + "pie_rotation", T(0.5), eParamType::REAL_CYCLIC, 0, M_2PI));
m_Params.push_back(ParamWithName<T>(&m_Thickness, prefix + "pie_thickness", T(0.5), eParamType::REAL, 0, 1)); m_Params.push_back(ParamWithName<T>(&m_Thickness, prefix + "pie_thickness", T(0.5), eParamType::REAL, 0, 1));
m_Params.push_back(ParamWithName<T>(true, &m_Pi2Slices, prefix + "pie_pi2_slices"));
} }
private: private:
T m_Slices; T m_Slices;
T m_Rotation; T m_Rotation;
T m_Thickness; T m_Thickness;
T m_Pi2Slices;//Precalc
}; };
/// <summary> /// <summary>

View File

@ -88,15 +88,13 @@ public:
<< "\t\t{\n" << "\t\t{\n"
<< "\t\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * t * cos(theta);\n" << "\t\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * t * cos(theta);\n"
<< "\t\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * t * sin(theta);\n" << "\t\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * t * sin(theta);\n"
<< "\t\t\tvOut.z = 0;\n"
<< "\t\t}\n" << "\t\t}\n"
<< "\t\telse\n" << "\t\telse\n"
<< "\t\t{\n" << "\t\t{\n"
<< "\t\t\tvOut.x = 0;\n" << "\t\t\tvOut.x = 0;\n"
<< "\t\t\tvOut.y = 0;\n" << "\t\t\tvOut.y = 0;\n"
<< "\t\t\tvOut.z = 0;\n"
<< "\t\t}\n" << "\t\t}\n"
<< "\t\tvOut.Z = " << DefaultZCl() << "\t\tvOut.z = " << DefaultZCl()
<< "\t}\n"; << "\t}\n";
return ss.str(); return ss.str();
} }
@ -2726,8 +2724,8 @@ public:
virtual void Precalc() override virtual void Precalc() override
{ {
T pa = 2 * T(M_PI) / m_P; T pa = 2 * T(M_PI) / Zeps(m_P);
T qa = 2 * T(M_PI) / m_Q; T qa = 2 * T(M_PI) / Zeps(m_Q);
T r = (1 - std::cos(pa)) / (std::cos(pa) + std::cos(qa)) + 1; T r = (1 - std::cos(pa)) / (std::cos(pa) + std::cos(qa)) + 1;
T a = m_N * pa; T a = m_N * pa;
@ -2822,15 +2820,15 @@ public:
virtual void Precalc() override virtual void Precalc() override
{ {
T r2 = 1 - (std::cos(2 * T(M_PI) / m_P) - 1) / T r2 = 1 - (std::cos(2 * T(M_PI) / Zeps(m_P)) - 1) /
(std::cos(2 * T(M_PI) / m_P) + std::cos(2 * T(M_PI) / m_Q)); (std::cos(2 * T(M_PI) / Zeps(m_P)) + std::cos(2 * T(M_PI) / Zeps(m_Q)));
if (r2 > 0) if (r2 > 0)
m_R = 1 / std::sqrt(r2); m_R = 1 / std::sqrt(r2);
else else
m_R = 1; m_R = 1;
m_Pa = 2 * T(M_PI) / m_P; m_Pa = 2 * T(M_PI) / Zeps(m_P);
} }
protected: protected:
@ -2913,15 +2911,15 @@ public:
virtual void Precalc() override virtual void Precalc() override
{ {
T r2 = 1 - (std::cos(2 * T(M_PI) / m_P) - 1) / T r2 = 1 - (std::cos(2 * T(M_PI) / Zeps(m_P)) - 1) /
(std::cos(2 * T(M_PI) / m_P) + std::cos(2 * T(M_PI) / m_Q)); (std::cos(2 * T(M_PI) / Zeps(m_P)) + std::cos(2 * T(M_PI) / Zeps(m_Q)));
if (r2 > 0) if (r2 > 0)
m_R = 1 / std::sqrt(r2); m_R = 1 / std::sqrt(r2);
else else
m_R = 1; m_R = 1;
m_Pa = 2 * T(M_PI) / m_P; m_Pa = 2 * T(M_PI) / Zeps(m_P);
} }
protected: protected:
@ -3001,13 +2999,13 @@ public:
virtual void Precalc() override virtual void Precalc() override
{ {
T pa = 2 * T(M_PI) / m_P; T pa = 2 * T(M_PI) / Zeps(m_P);
T qa = 2 * T(M_PI) / m_Q; T qa = 2 * T(M_PI) / Zeps(m_Q);
T r = -(std::cos(pa) - 1) / (std::cos(pa) + std::cos(qa)); T r = -(std::cos(pa) - 1) / Zeps(std::cos(pa) + std::cos(qa));
T na = m_N * pa; T na = m_N * pa;
if (r > 0) if (r > 0)
r = 1 / std::sqrt(1 + r); r = 1 / Zeps(std::sqrt(1 + r));
else else
r = 1; r = 1;
@ -3119,12 +3117,12 @@ public:
virtual void Precalc() override virtual void Precalc() override
{ {
T pa = M_2PI / m_P; T pa = M_2PI / Zeps(m_P);
T qa = M_2PI / m_Q; T qa = M_2PI / Zeps(m_Q);
T r = -(std::cos(pa) - 1) / (std::cos(pa) + std::cos(qa)); T r = -(std::cos(pa) - 1) / Zeps(std::cos(pa) + std::cos(qa));
if (r > 0) if (r > 0)
r = 1 / std::sqrt(1 + r); r = 1 / Zeps(std::sqrt(1 + r));
else else
r = 1; r = 1;
@ -3219,12 +3217,12 @@ public:
virtual void Precalc() override virtual void Precalc() override
{ {
T pa = M_2PI / m_P; T pa = M_2PI / Zeps(m_P);
T qa = M_2PI / m_Q; T qa = M_2PI / Zeps(m_Q);
T r = -(std::cos(pa) - 1) / (std::cos(pa) + std::cos(qa)); T r = -(std::cos(pa) - 1) / Zeps(std::cos(pa) + std::cos(qa));
if (r > 0) if (r > 0)
r = 1 / std::sqrt(1 + r); r = 1 / Zeps(std::sqrt(1 + r));
else else
r = 1; r = 1;

View File

@ -3466,7 +3466,7 @@ public:
int loc; int loc;
T tempx, tempy; T tempx, tempy;
T lrmaj = m_Weight;//Sets hexagon length radius - major plane. T lrmaj = m_Weight;//Sets hexagon length radius - major plane.
T boost;//Boost is the separation distance between the two planes. T boost = 1;//Boost is the separation distance between the two planes.
T sumX, sumY; T sumX, sumY;
if (m_VarType == eVariationType::VARTYPE_REG) if (m_VarType == eVariationType::VARTYPE_REG)
@ -3561,7 +3561,7 @@ public:
<< "\t\tint loc;\n" << "\t\tint loc;\n"
<< "\t\treal_t tempx, tempy;\n" << "\t\treal_t tempx, tempy;\n"
<< "\t\treal_t lrmaj = xform->m_VariationWeights[" << varIndex << "];\n" << "\t\treal_t lrmaj = xform->m_VariationWeights[" << varIndex << "];\n"
<< "\t\treal_t boost;\n" << "\t\treal_t boost = 1;\n"
<< "\t\treal_t sumX, sumY;\n\n"; << "\t\treal_t sumX, sumY;\n\n";
if (m_VarType == eVariationType::VARTYPE_REG) if (m_VarType == eVariationType::VARTYPE_REG)

View File

@ -1495,7 +1495,7 @@ public:
/// <param name="rand">The rand.</param> /// <param name="rand">The rand.</param>
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
{ {
T gradTmp, secTmp, xTmp, yTmp; T gradTmp, secTmp, xTmp = 0, yTmp = 0;
if ((helper.In.x < m_LeftBorder) || (helper.In.x > m_RightBorder) || (helper.In.y < m_TopBorder) || (helper.In.y > m_BottomBorder)) if ((helper.In.x < m_LeftBorder) || (helper.In.x > m_RightBorder) || (helper.In.y < m_TopBorder) || (helper.In.y > m_BottomBorder))
{ {
@ -1591,7 +1591,7 @@ public:
string leftBorder = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string leftBorder = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string rightBorder = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string rightBorder = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n" ss << "\t{\n"
<< "\t\treal_t gradTmp, secTmp, xTmp, yTmp;\n" << "\t\treal_t gradTmp, secTmp, xTmp = 0, yTmp = 0;\n"
<< "\n" << "\n"
<< "\t\tif ((vIn.x < " << leftBorder << ") || (vIn.x > " << rightBorder << ") || (vIn.y < " << topBorder << ") || (vIn.y > " << bottomBorder << "))\n" << "\t\tif ((vIn.x < " << leftBorder << ") || (vIn.x > " << rightBorder << ") || (vIn.y < " << topBorder << ") || (vIn.y > " << bottomBorder << "))\n"
<< "\t\t{\n" << "\t\t{\n"
@ -3626,8 +3626,6 @@ private:
case LERP_BEZIER: case LERP_BEZIER:
return BezierQuadMap(x, m); return BezierQuadMap(x, m);
} }
return x * m;
} }
inline void SynthSinCos(SynthStruct& synth, T theta, T& s, T& c, int sineType) inline void SynthSinCos(SynthStruct& synth, T theta, T& s, T& c, int sineType)

View File

@ -573,7 +573,7 @@ public:
{ {
int posNeg = 1; int posNeg = 1;
T th = 0; T th = 0;
T sth, cth, pang, wig, wag, wag2, wag3, wag12, waggle; T sth, cth, pang, wig, wag, wag2, wag3, wag12 = 0, waggle = 0;
T rad = helper.m_PrecalcSqrtSumSquares; T rad = helper.m_PrecalcSqrtSumSquares;
T curve1 = rad / m_L; T curve1 = rad / m_L;
T curve2 = Sqr(curve1); T curve2 = Sqr(curve1);

View File

@ -1113,7 +1113,7 @@ public:
<< "C: " << m_Affine.C() << " " << "C: " << m_Affine.C() << " "
<< "D: " << m_Affine.D() << " " << "D: " << m_Affine.D() << " "
<< "E: " << m_Affine.E() << " " << "E: " << m_Affine.E() << " "
<< "F: " << m_Affine.F() << " " << endl; << "F: " << m_Affine.F() << " \n";
if (m_HasPost) if (m_HasPost)
{ {
@ -1122,27 +1122,27 @@ public:
<< "Post C: " << m_Post.C() << " " << "Post C: " << m_Post.C() << " "
<< "Post D: " << m_Post.D() << " " << "Post D: " << m_Post.D() << " "
<< "Post E: " << m_Post.E() << " " << "Post E: " << m_Post.E() << " "
<< "Post F: " << m_Post.F() << " " << endl; << "Post F: " << m_Post.F() << " \n";
} }
ss << "Weight: " << m_Weight << endl; ss << "Weight: " << m_Weight;
ss << "ColorX: " << m_ColorX << endl; ss << "\nColorX: " << m_ColorX;
ss << "ColorY: " << m_ColorY << endl; ss << "\nColorY: " << m_ColorY;
ss << "Direct Color: " << m_DirectColor << endl; ss << "\nDirect Color: " << m_DirectColor;
ss << "Color Speed: " << m_ColorSpeed << endl; ss << "\nColor Speed: " << m_ColorSpeed;
ss << "Animate: " << m_Animate << endl; ss << "\nAnimate: " << m_Animate;
ss << "Opacity: " << m_Opacity << endl; ss << "\nOpacity: " << m_Opacity;
ss << "Viz Adjusted: " << m_VizAdjusted << endl; ss << "\nViz Adjusted: " << m_VizAdjusted;
ss << "Wind: " << m_Wind[0] << ", " << m_Wind[1] << endl; ss << "\nWind: " << m_Wind[0] << ", " << m_Wind[1];
ss << "Motion Frequency: " << m_MotionFreq << endl; ss << "\nMotion Frequency: " << m_MotionFreq;
ss << "Motion Func: " << m_MotionFunc << endl; ss << "\nMotion Func: " << m_MotionFunc;
ss << "Motion Offset: " << m_MotionOffset << endl; ss << "\nMotion Offset: " << m_MotionOffset;
const_cast<Xform<T>*>(this)->AllVarsFunc([&] (vector<Variation<T>*>& variations, bool & keepGoing) const_cast<Xform<T>*>(this)->AllVarsFunc([&] (vector<Variation<T>*>& variations, bool & keepGoing)
{ {
for (auto var : variations) for (auto var : variations)
ss << var->ToString() << endl; ss << var->ToString() << "\n";
ss << endl; ss << "\n";
}); });
if (XaosPresent()) if (XaosPresent())
@ -1150,7 +1150,7 @@ public:
for (auto xaos : m_Xaos) for (auto xaos : m_Xaos)
ss << xaos << " "; ss << xaos << " ";
ss << endl; ss << "\n";
} }
return ss.str(); return ss.str();

View File

@ -35,10 +35,10 @@ public:
m_OriginalLocale = setlocale(category, nullptr);//Query. m_OriginalLocale = setlocale(category, nullptr);//Query.
if (m_OriginalLocale.empty()) if (m_OriginalLocale.empty())
cout << "Couldn't get original locale." << endl; cout << "Couldn't get original locale.\n";
if (setlocale(category, loc) == nullptr)//Set. if (setlocale(category, loc) == nullptr)//Set.
cout << "Couldn't set new locale " << category << ", " << loc << "." << endl; cout << "Couldn't set new locale " << category << ", " << loc << ".\n";
} }
/// <summary> /// <summary>
@ -48,7 +48,7 @@ public:
{ {
if (!m_OriginalLocale.empty()) if (!m_OriginalLocale.empty())
if (setlocale(m_Category, m_OriginalLocale.c_str()) == nullptr)//Restore. if (setlocale(m_Category, m_OriginalLocale.c_str()) == nullptr)//Restore.
cout << "Couldn't restore original locale " << m_Category << ", " << m_OriginalLocale << "." << endl; cout << "Couldn't restore original locale " << m_Category << ", " << m_OriginalLocale << ".\n";
} }
private: private:
@ -327,13 +327,13 @@ public:
{ {
if (embers[0].m_Interp == eInterp::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; cout << "Warning: smooth interpolation cannot be used for first segment.\n switching to linear.\n";
embers[0].m_Interp = eInterp::EMBER_INTERP_LINEAR; embers[0].m_Interp = eInterp::EMBER_INTERP_LINEAR;
} }
if (emberSize >= 2 && embers[emberSize - 2].m_Interp == eInterp::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; cout << "Warning: smooth interpolation cannot be used for last segment.\n switching to linear.\n";
embers[emberSize - 2].m_Interp = eInterp::EMBER_INTERP_LINEAR; embers[emberSize - 2].m_Interp = eInterp::EMBER_INTERP_LINEAR;
} }
} }
@ -526,7 +526,7 @@ private:
char* attStr; char* attStr;
const char* loc = __FUNCTION__; const char* loc = __FUNCTION__;
int soloXform = -1; int soloXform = -1;
size_t i, count, index = 0; size_t i, count = 0, index = 0;
double vals[16]; double vals[16];
xmlAttrPtr att, curAtt; xmlAttrPtr att, curAtt;
xmlNodePtr editNode, childNode, motionNode; xmlNodePtr editNode, childNode, motionNode;

View File

@ -15,11 +15,11 @@ bool EmberAnimate(EmberOptions& opt)
std::cout.imbue(std::locale("")); std::cout.imbue(std::locale(""));
if (opt.DumpArgs()) if (opt.DumpArgs())
cout << opt.GetValues(eOptionUse::OPT_USE_ANIMATE) << endl; cout << opt.GetValues(eOptionUse::OPT_USE_ANIMATE) << "\n";
if (opt.OpenCLInfo()) if (opt.OpenCLInfo())
{ {
cout << "\nOpenCL Info: " << endl; cout << "\nOpenCL Info: \n";
cout << info->DumpInfo(); cout << info->DumpInfo();
return true; return true;
} }
@ -41,7 +41,7 @@ bool EmberAnimate(EmberOptions& opt)
unique_ptr<RenderProgress<T>> progress; unique_ptr<RenderProgress<T>> progress;
vector<unique_ptr<Renderer<T, float>>> renderers; vector<unique_ptr<Renderer<T, float>>> renderers;
vector<string> errorReport; vector<string> errorReport;
CriticalSection verboseCs; std::recursive_mutex verboseCs;
if (opt.EmberCL()) if (opt.EmberCL())
{ {
@ -53,7 +53,7 @@ bool EmberAnimate(EmberOptions& opt)
if (!renderers.size() || renderers.size() != devices.size()) if (!renderers.size() || renderers.size() != devices.size())
{ {
cout << "Only created " << renderers.size() << " renderers out of " << devices.size() << " requested, exiting." << endl; cout << "Only created " << renderers.size() << " renderers out of " << devices.size() << " requested, exiting.\n";
return false; return false;
} }
@ -63,19 +63,19 @@ bool EmberAnimate(EmberOptions& opt)
renderers[0]->Callback(progress.get()); renderers[0]->Callback(progress.get());
} }
cout << "Using OpenCL to render." << endl; cout << "Using OpenCL to render.\n";
if (opt.Verbose()) if (opt.Verbose())
{ {
for (auto& device : devices) for (auto& device : devices)
{ {
cout << "Platform: " << info->PlatformName(device.first) << endl; cout << "Platform: " << info->PlatformName(device.first) << "\n";
cout << "Device: " << info->DeviceName(device.first, device.second) << endl; cout << "Device: " << info->DeviceName(device.first, device.second) << "\n";
} }
} }
if (opt.ThreadCount() > 1) if (opt.ThreadCount() > 1)
cout << "Cannot specify threads with OpenCL, using 1 thread." << endl; cout << "Cannot specify threads with OpenCL, using 1 thread.\n";
opt.ThreadCount(1); opt.ThreadCount(1);
@ -84,7 +84,7 @@ bool EmberAnimate(EmberOptions& opt)
if (opt.BitsPerChannel() != 8) if (opt.BitsPerChannel() != 8)
{ {
cout << "Bits per channel cannot be anything other than 8 with OpenCL, setting to 8." << endl; cout << "Bits per channel cannot be anything other than 8 with OpenCL, setting to 8.\n";
opt.BitsPerChannel(8); opt.BitsPerChannel(8);
} }
} }
@ -98,7 +98,7 @@ bool EmberAnimate(EmberOptions& opt)
if (!tempRenderer.get()) if (!tempRenderer.get())
{ {
cout << "Renderer creation failed, exiting." << endl; cout << "Renderer creation failed, exiting.\n";
return false; return false;
} }
@ -110,12 +110,12 @@ bool EmberAnimate(EmberOptions& opt)
if (opt.ThreadCount() == 0) if (opt.ThreadCount() == 0)
{ {
cout << "Using " << Timing::ProcessorCount() << " automatically detected threads." << endl; cout << "Using " << Timing::ProcessorCount() << " automatically detected threads.\n";
opt.ThreadCount(Timing::ProcessorCount()); opt.ThreadCount(Timing::ProcessorCount());
} }
else else
{ {
cout << "Using " << opt.ThreadCount() << " manually specified threads." << endl; cout << "Using " << opt.ThreadCount() << " manually specified threads.\n";
} }
tempRenderer->ThreadCount(opt.ThreadCount(), opt.IsaacSeed() != "" ? opt.IsaacSeed().c_str() : nullptr); tempRenderer->ThreadCount(opt.ThreadCount(), opt.IsaacSeed() != "" ? opt.IsaacSeed().c_str() : nullptr);
@ -125,7 +125,7 @@ bool EmberAnimate(EmberOptions& opt)
if (!InitPaletteList<T>(opt.PalettePath())) if (!InitPaletteList<T>(opt.PalettePath()))
return false; return false;
cout << "Parsing ember file " << opt.Input() << endl; cout << "Parsing ember file " << opt.Input() << "\n";
if (!ParseEmberFile(parser, opt.Input(), embers)) if (!ParseEmberFile(parser, opt.Input(), embers))
return false; return false;
@ -134,7 +134,7 @@ bool EmberAnimate(EmberOptions& opt)
if (embers.size() <= 1) if (embers.size() <= 1)
{ {
cout << "Read " << embers.size() << " embers from file. At least 2 required to animate, exiting." << endl; cout << "Read " << embers.size() << " embers from file. At least 2 required to animate, exiting.\n";
return false; return false;
} }
@ -143,37 +143,37 @@ bool EmberAnimate(EmberOptions& opt)
opt.Format() != "ppm" && opt.Format() != "ppm" &&
opt.Format() != "bmp") opt.Format() != "bmp")
{ {
cout << "Format must be jpg, png, ppm, or bmp not " << opt.Format() << ". Setting to jpg." << endl; cout << "Format must be jpg, png, ppm, or bmp not " << opt.Format() << ". Setting to jpg.\n";
} }
channels = opt.Format() == "png" ? 4 : 3; channels = opt.Format() == "png" ? 4 : 3;
if (opt.BitsPerChannel() == 16 && opt.Format() != "png") if (opt.BitsPerChannel() == 16 && opt.Format() != "png")
{ {
cout << "Support for 16 bits per channel images is only present for the png format. Setting to 8." << endl; cout << "Support for 16 bits per channel images is only present for the png format. Setting to 8.\n";
opt.BitsPerChannel(8); opt.BitsPerChannel(8);
} }
else if (opt.BitsPerChannel() != 8 && opt.BitsPerChannel() != 16) else if (opt.BitsPerChannel() != 8 && opt.BitsPerChannel() != 16)
{ {
cout << "Unexpected bits per channel specified " << opt.BitsPerChannel() << ". Setting to 8." << endl; cout << "Unexpected bits per channel specified " << opt.BitsPerChannel() << ". Setting to 8.\n";
opt.BitsPerChannel(8); opt.BitsPerChannel(8);
} }
if (opt.InsertPalette() && opt.BitsPerChannel() != 8) if (opt.InsertPalette() && opt.BitsPerChannel() != 8)
{ {
cout << "Inserting palette only supported with 8 bits per channel, insertion will not take place." << endl; cout << "Inserting palette only supported with 8 bits per channel, insertion will not take place.\n";
opt.InsertPalette(false); opt.InsertPalette(false);
} }
if (opt.AspectRatio() < 0) if (opt.AspectRatio() < 0)
{ {
cout << "Invalid pixel aspect ratio " << opt.AspectRatio() << endl << ". Must be positive, setting to 1." << endl; cout << "Invalid pixel aspect ratio " << opt.AspectRatio() << "\n. Must be positive, setting to 1.\n";
opt.AspectRatio(1); opt.AspectRatio(1);
} }
if (opt.Dtime() < 1) if (opt.Dtime() < 1)
{ {
cout << "Warning: dtime must be positive, not " << opt.Dtime() << ". Setting to 1." << endl; cout << "Warning: dtime must be positive, not " << opt.Dtime() << ". Setting to 1.\n";
opt.Dtime(1); opt.Dtime(1);
} }
@ -181,13 +181,13 @@ bool EmberAnimate(EmberOptions& opt)
{ {
if (opt.Time()) if (opt.Time())
{ {
cout << "Cannot specify both time and frame." << endl; cout << "Cannot specify both time and frame.\n";
return false; return false;
} }
if (opt.FirstFrame() || opt.LastFrame()) if (opt.FirstFrame() || opt.LastFrame())
{ {
cout << "Cannot specify both frame and begin or end." << endl; cout << "Cannot specify both frame and begin or end.\n";
return false; return false;
} }
@ -199,7 +199,7 @@ bool EmberAnimate(EmberOptions& opt)
{ {
if (opt.FirstFrame() || opt.LastFrame()) if (opt.FirstFrame() || opt.LastFrame())
{ {
cout << "Cannot specify both time and begin or end." << endl; cout << "Cannot specify both time and begin or end.\n";
return false; return false;
} }
@ -225,7 +225,7 @@ bool EmberAnimate(EmberOptions& opt)
if (i > 0 && embers[i].m_Time == embers[i - 1].m_Time) if (i > 0 && embers[i].m_Time == embers[i - 1].m_Time)
{ {
cout << "Image " << i << " time of " << embers[i].m_Time << " equaled previous image time of " << embers[i - 1].m_Time << ". Adjusting up by 1." << endl; cout << "Image " << i << " time of " << embers[i].m_Time << " equaled previous image time of " << embers[i - 1].m_Time << ". Adjusting up by 1.\n";
embers[i].m_Time++; embers[i].m_Time++;
} }
@ -255,14 +255,14 @@ bool EmberAnimate(EmberOptions& opt)
if (imageMem > maxMem)//Ensure the max amount of memory for a process isn't exceeded. if (imageMem > maxMem)//Ensure the max amount of memory for a process isn't exceeded.
{ {
cout << "Image " << i << " size > " << maxMem << ". Setting to 1920 x 1080." << endl; cout << "Image " << i << " size > " << maxMem << ". Setting to 1920 x 1080.\n";
embers[i].m_FinalRasW = 1920; embers[i].m_FinalRasW = 1920;
embers[i].m_FinalRasH = 1080; embers[i].m_FinalRasH = 1080;
} }
if (embers[i].m_FinalRasW == 0 || embers[i].m_FinalRasH == 0) if (embers[i].m_FinalRasW == 0 || embers[i].m_FinalRasH == 0)
{ {
cout << "Warning: Output image " << i << " has dimension 0: " << embers[i].m_FinalRasW << ", " << embers[i].m_FinalRasH << ". Setting to 1920 x 1080." << endl; cout << "Warning: Output image " << i << " has dimension 0: " << embers[i].m_FinalRasW << ", " << embers[i].m_FinalRasH << ". Setting to 1920 x 1080.\n";
embers[i].m_FinalRasW = 1920; embers[i].m_FinalRasW = 1920;
embers[i].m_FinalRasH = 1080; embers[i].m_FinalRasH = 1080;
} }
@ -271,7 +271,7 @@ bool EmberAnimate(EmberOptions& opt)
(embers[i].m_FinalRasH != embers[0].m_FinalRasH)) (embers[i].m_FinalRasH != embers[0].m_FinalRasH))
{ {
cout << "Warning: flame " << i << " at time " << embers[i].m_Time << " size mismatch. (" << embers[i].m_FinalRasW << ", " << embers[i].m_FinalRasH << cout << "Warning: flame " << i << " at time " << embers[i].m_Time << " size mismatch. (" << embers[i].m_FinalRasW << ", " << embers[i].m_FinalRasH <<
") should be (" << embers[0].m_FinalRasW << ", " << embers[0].m_FinalRasH << "). Setting to " << embers[0].m_FinalRasW << ", " << embers[0].m_FinalRasH << "." << endl; ") should be (" << embers[0].m_FinalRasW << ", " << embers[0].m_FinalRasH << "). Setting to " << embers[0].m_FinalRasW << ", " << embers[0].m_FinalRasH << ".\n";
embers[i].m_FinalRasW = embers[0].m_FinalRasW; embers[i].m_FinalRasW = embers[0].m_FinalRasW;
embers[i].m_FinalRasH = embers[0].m_FinalRasH; embers[i].m_FinalRasH = embers[0].m_FinalRasH;
} }
@ -279,7 +279,7 @@ bool EmberAnimate(EmberOptions& opt)
if (unsorted) if (unsorted)
{ {
cout << "Embers were unsorted by time. First out of order index was " << firstUnsortedIndex << ". Sorting." << endl; cout << "Embers were unsorted by time. First out of order index was " << firstUnsortedIndex << ". Sorting.\n";
std::sort(embers.begin(), embers.end(), &CompareEmbers<T>); std::sort(embers.begin(), embers.end(), &CompareEmbers<T>);
} }
@ -295,7 +295,7 @@ bool EmberAnimate(EmberOptions& opt)
if (!opt.Out().empty()) if (!opt.Out().empty())
{ {
cout << "Single output file " << opt.Out() << " specified for multiple images. They would be all overwritten and only the last image will remain, exiting." << endl; cout << "Single output file " << opt.Out() << " specified for multiple images. They would be all overwritten and only the last image will remain, exiting.\n";
return false; return false;
} }
@ -339,7 +339,7 @@ bool EmberAnimate(EmberOptions& opt)
writeSuccess = WriteBmp(filename.c_str(), finalImagep, w, h); writeSuccess = WriteBmp(filename.c_str(), finalImagep, w, h);
if (!writeSuccess) if (!writeSuccess)
cout << "Error writing " << filename << endl; cout << "Error writing " << filename << "\n";
}; };
atomfTime.store(opt.FirstFrame()); atomfTime.store(opt.FirstFrame());
std::function<void(size_t)> iterFunc = [&](size_t index) std::function<void(size_t)> iterFunc = [&](size_t index)
@ -361,16 +361,15 @@ bool EmberAnimate(EmberOptions& opt)
if (opt.Verbose() && ((opt.LastFrame() - opt.FirstFrame()) / opt.Dtime() >= 1)) if (opt.Verbose() && ((opt.LastFrame() - opt.FirstFrame()) / opt.Dtime() >= 1))
{ {
verboseCs.Enter(); rlg l(verboseCs);
cout << "Time = " << ftime << " / " << opt.LastFrame() << " / " << opt.Dtime() << endl; cout << "Time = " << ftime << " / " << opt.LastFrame() << " / " << opt.Dtime() << "\n";
verboseCs.Leave();
} }
renderer->Reset(); renderer->Reset();
if ((renderer->Run(finalImages[finalImageIndex], localTime) != eRenderStatus::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; cout << "Error: image rendering failed, skipping to next image.\n";
renderer->DumpErrorReport();//Something went wrong, print errors. renderer->DumpErrorReport();//Something went wrong, print errors.
atomfTime.store(opt.LastFrame() + 1);//Abort all threads if any of them encounter an error. atomfTime.store(opt.LastFrame() + 1);//Abort all threads if any of them encounter an error.
break; break;
@ -386,9 +385,8 @@ bool EmberAnimate(EmberOptions& opt)
if (opt.Verbose()) if (opt.Verbose())
{ {
verboseCs.Enter(); rlg l(verboseCs);
cout << "Writing " << flameName << endl; cout << "Writing " << flameName << "\n";
verboseCs.Leave();
} }
Interpolater<T>::Interpolate(embers, localTime, 0, centerEmber);//Get center flame. Interpolater<T>::Interpolate(embers, localTime, 0, centerEmber);//Get center flame.
@ -404,16 +402,15 @@ bool EmberAnimate(EmberOptions& opt)
if (opt.Verbose()) if (opt.Verbose())
{ {
verboseCs.Enter(); rlg l(verboseCs);
cout << "\nIters ran/requested: " + os.str() << endl; cout << "\nIters ran/requested: " + os.str() << "\n";
if (!opt.EmberCL()) cout << "Bad values: " << stats.m_Badvals << endl; if (!opt.EmberCL()) cout << "Bad values: " << stats.m_Badvals << "\n";
cout << "Render time: " << t.Format(stats.m_RenderMs) << endl; cout << "Render time: " << t.Format(stats.m_RenderMs) << "\n";
cout << "Pure iter time: " << t.Format(stats.m_IterMs) << endl; cout << "Pure iter time: " << t.Format(stats.m_IterMs) << "\n";
cout << "Iters/sec: " << size_t(stats.m_Iters / (stats.m_IterMs / 1000.0)) << endl; cout << "Iters/sec: " << size_t(stats.m_Iters / (stats.m_IterMs / 1000.0)) << "\n";
cout << "Writing " << filename << endl << endl; cout << "Writing " << filename << "\n\n";
verboseCs.Leave();
} }
//Run image writing in a thread. Although doing it this way duplicates the final output memory, it saves a lot of time //Run image writing in a thread. Although doing it this way duplicates the final output memory, it saves a lot of time
@ -487,7 +484,7 @@ int _tmain(int argc, _TCHAR* argv[])
} }
else if (opt.Bits() == 32) else if (opt.Bits() == 32)
{ {
cout << "Bits 32/int histogram no longer supported. Using bits == 33 (float)." << endl; cout << "Bits 32/int histogram no longer supported. Using bits == 33 (float).\n";
b = EmberAnimate<float>(opt); b = EmberAnimate<float>(opt);
} }
} }

View File

@ -3,39 +3,39 @@
namespace EmberCLns namespace EmberCLns
{ {
std::unordered_map<string, string> FunctionMapper::m_GlobalMap; std::unordered_map<string, string> FunctionMapper::s_GlobalMap;
FunctionMapper::FunctionMapper() FunctionMapper::FunctionMapper()
{ {
if (m_GlobalMap.empty()) if (s_GlobalMap.empty())
{ {
m_GlobalMap["LRint"] = s_GlobalMap["LRint"] =
"inline real_t LRint(real_t x)\n" "inline real_t LRint(real_t x)\n"
"{\n" "{\n"
" intPrec temp = (x >= 0.0 ? (intPrec)(x + 0.5) : (intPrec)(x - 0.5));\n" " intPrec temp = (x >= 0.0 ? (intPrec)(x + 0.5) : (intPrec)(x - 0.5));\n"
" return (real_t)temp;\n" " return (real_t)temp;\n"
"}\n"; "}\n";
m_GlobalMap["Round"] = s_GlobalMap["Round"] =
"inline real_t Round(real_t r)\n" "inline real_t Round(real_t r)\n"
"{\n" "{\n"
" return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);\n" " return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);\n"
"}\n"; "}\n";
m_GlobalMap["Sign"] = s_GlobalMap["Sign"] =
"inline real_t Sign(real_t v)\n" "inline real_t Sign(real_t v)\n"
"{\n" "{\n"
" return (v < 0.0) ? -1 : (v > 0.0) ? 1 : 0.0;\n" " return (v < 0.0) ? -1 : (v > 0.0) ? 1 : 0.0;\n"
"}\n"; "}\n";
m_GlobalMap["SignNz"] = s_GlobalMap["SignNz"] =
"inline real_t SignNz(real_t v)\n" "inline real_t SignNz(real_t v)\n"
"{\n" "{\n"
" return (v < 0.0) ? -1.0 : 1.0;\n" " return (v < 0.0) ? -1.0 : 1.0;\n"
"}\n"; "}\n";
m_GlobalMap["Sqr"] = s_GlobalMap["Sqr"] =
"inline real_t Sqr(real_t v)\n" "inline real_t Sqr(real_t v)\n"
"{\n" "{\n"
" return v * v;\n" " return v * v;\n"
"}\n"; "}\n";
m_GlobalMap["SafeSqrt"] = s_GlobalMap["SafeSqrt"] =
"inline real_t SafeSqrt(real_t x)\n" "inline real_t SafeSqrt(real_t x)\n"
"{\n" "{\n"
" if (x <= 0.0)\n" " if (x <= 0.0)\n"
@ -43,7 +43,7 @@ FunctionMapper::FunctionMapper()
"\n" "\n"
" return sqrt(x);\n" " return sqrt(x);\n"
"}\n"; "}\n";
m_GlobalMap["SafeDivInv"] = s_GlobalMap["SafeDivInv"] =
"inline real_t SafeDivInv(real_t q, real_t r)\n" "inline real_t SafeDivInv(real_t q, real_t r)\n"
"{\n" "{\n"
" if (r < EPS)\n" " if (r < EPS)\n"
@ -51,81 +51,81 @@ FunctionMapper::FunctionMapper()
"\n" "\n"
" return q / r;\n" " return q / r;\n"
"}\n"; "}\n";
m_GlobalMap["Cube"] = s_GlobalMap["Cube"] =
"inline real_t Cube(real_t v)\n" "inline real_t Cube(real_t v)\n"
"{\n" "{\n"
" return v * v * v;\n" " return v * v * v;\n"
"}\n"; "}\n";
m_GlobalMap["Hypot"] = s_GlobalMap["Hypot"] =
"inline real_t Hypot(real_t x, real_t y)\n" "inline real_t Hypot(real_t x, real_t y)\n"
"{\n" "{\n"
" return sqrt(SQR(x) + SQR(y));\n" " return sqrt(SQR(x) + SQR(y));\n"
"}\n"; "}\n";
m_GlobalMap["Spread"] = s_GlobalMap["Spread"] =
"inline real_t Spread(real_t x, real_t y)\n" "inline real_t Spread(real_t x, real_t y)\n"
"{\n" "{\n"
" return Hypot(x, y) * ((x) > 0.0 ? 1.0 : -1.0);\n" " return Hypot(x, y) * ((x) > 0.0 ? 1.0 : -1.0);\n"
"}\n"; "}\n";
m_GlobalMap["Powq4"] = s_GlobalMap["Powq4"] =
"inline real_t Powq4(real_t x, real_t y)\n" "inline real_t Powq4(real_t x, real_t y)\n"
"{\n" "{\n"
" return pow(fabs(x), y) * SignNz(x);\n" " return pow(fabs(x), y) * SignNz(x);\n"
"}\n"; "}\n";
m_GlobalMap["Powq4c"] = s_GlobalMap["Powq4c"] =
"inline real_t Powq4c(real_t x, real_t y)\n" "inline real_t Powq4c(real_t x, real_t y)\n"
"{\n" "{\n"
" return y == 1.0 ? x : Powq4(x, y);\n" " return y == 1.0 ? x : Powq4(x, y);\n"
"}\n"; "}\n";
m_GlobalMap["Zeps"] = s_GlobalMap["Zeps"] =
"inline real_t Zeps(real_t x)\n" "inline real_t Zeps(real_t x)\n"
"{\n" "{\n"
" return x == 0.0 ? EPS : x;\n" " return x == 0.0 ? EPS : x;\n"
"}\n"; "}\n";
m_GlobalMap["Lerp"] = s_GlobalMap["Lerp"] =
"inline real_t Lerp(real_t a, real_t b, real_t p)\n" "inline real_t Lerp(real_t a, real_t b, real_t p)\n"
"{\n" "{\n"
" return a + (b - a) * p;\n" " return a + (b - a) * p;\n"
"}\n"; "}\n";
m_GlobalMap["Fabsmod"] = s_GlobalMap["Fabsmod"] =
"inline real_t Fabsmod(real_t v)\n" "inline real_t Fabsmod(real_t v)\n"
"{\n" "{\n"
" real_t dummy;\n" " real_t dummy;\n"
"\n" "\n"
" return modf(v, &dummy);\n" " return modf(v, &dummy);\n"
"}\n"; "}\n";
m_GlobalMap["Fosc"] = s_GlobalMap["Fosc"] =
"inline real_t Fosc(real_t p, real_t amp, real_t ph)\n" "inline real_t Fosc(real_t p, real_t amp, real_t ph)\n"
"{\n" "{\n"
" return 0.5 - cos(p * amp + ph) * 0.5;\n" " return 0.5 - cos(p * amp + ph) * 0.5;\n"
"}\n"; "}\n";
m_GlobalMap["Foscn"] = s_GlobalMap["Foscn"] =
"inline real_t Foscn(real_t p, real_t ph)\n" "inline real_t Foscn(real_t p, real_t ph)\n"
"{\n" "{\n"
" return 0.5 - cos(p + ph) * 0.5;\n" " return 0.5 - cos(p + ph) * 0.5;\n"
"}\n"; "}\n";
m_GlobalMap["LogScale"] = s_GlobalMap["LogScale"] =
"inline real_t LogScale(real_t x)\n" "inline real_t LogScale(real_t x)\n"
"{\n" "{\n"
" return x == 0.0 ? 0.0 : log((fabs(x) + 1) * M_E) * SignNz(x) / M_E;\n" " return x == 0.0 ? 0.0 : log((fabs(x) + 1) * M_E) * SignNz(x) / M_E;\n"
"}\n"; "}\n";
m_GlobalMap["LogMap"] = s_GlobalMap["LogMap"] =
"inline real_t LogMap(real_t x)\n" "inline real_t LogMap(real_t x)\n"
"{\n" "{\n"
" return x == 0.0 ? 0.0 : (M_E + log(x * M_E)) * 0.25 * SignNz(x);\n" " return x == 0.0 ? 0.0 : (M_E + log(x * M_E)) * 0.25 * SignNz(x);\n"
"}\n"; "}\n";
m_GlobalMap["ClampGte"] = s_GlobalMap["ClampGte"] =
"inline real_t ClampGte(real_t val, real_t gte)\n" "inline real_t ClampGte(real_t val, real_t gte)\n"
"{\n" "{\n"
" return (val < gte) ? gte : val;\n" " return (val < gte) ? gte : val;\n"
"}\n"; "}\n";
m_GlobalMap["Swap"] = s_GlobalMap["Swap"] =
"inline void Swap(real_t* val1, real_t* val2)\n" "inline void Swap(real_t* val1, real_t* val2)\n"
"{\n" "{\n"
" real_t tmp = *val1;\n" " real_t tmp = *val1;\n"
" *val1 = *val2;\n" " *val1 = *val2;\n"
" *val2 = tmp;\n" " *val2 = tmp;\n"
"}\n"; "}\n";
m_GlobalMap["Vratio"] = s_GlobalMap["Vratio"] =
"inline real_t Vratio(real2* p, real2* q, real2* u)\n" "inline real_t Vratio(real2* p, real2* q, real2* u)\n"
"{\n" "{\n"
" real2 pmq = *p - *q;\n" " real2 pmq = *p - *q;\n"
@ -135,7 +135,7 @@ FunctionMapper::FunctionMapper()
"\n" "\n"
" return 2 * (((*u).x - (*q).x) * pmq.x + ((*u).y - (*q).y) * pmq.y) / Zeps(SQR(pmq.x) + SQR(pmq.y));\n" " return 2 * (((*u).x - (*q).x) * pmq.x + ((*u).y - (*q).y) * pmq.y) / Zeps(SQR(pmq.x) + SQR(pmq.y));\n"
"}\n"; "}\n";
m_GlobalMap["Closest"] = s_GlobalMap["Closest"] =
"inline int Closest(real2* p, int n, real2* u)\n" "inline int Closest(real2* p, int n, real2* u)\n"
"{\n" "{\n"
" real_t d2;\n" " real_t d2;\n"
@ -155,7 +155,7 @@ FunctionMapper::FunctionMapper()
"\n" "\n"
" return j;\n" " return j;\n"
"}\n"; "}\n";
m_GlobalMap["Voronoi"] = s_GlobalMap["Voronoi"] =
"inline real_t Voronoi(real2* p, int n, int q, real2* u)\n" "inline real_t Voronoi(real2* p, int n, int q, real2* u)\n"
"{\n" "{\n"
" real_t ratio;\n" " real_t ratio;\n"
@ -175,7 +175,7 @@ FunctionMapper::FunctionMapper()
"\n" "\n"
" return ratiomax;\n" " return ratiomax;\n"
"}\n"; "}\n";
m_GlobalMap["SimplexNoise3D"] = s_GlobalMap["SimplexNoise3D"] =
"inline real_t SimplexNoise3D(real3* v, __global real_t* p, __global real3* grad)\n" "inline real_t SimplexNoise3D(real3* v, __global real_t* p, __global real3* grad)\n"
"{\n" "{\n"
" real3 c[4];\n" " real3 c[4];\n"
@ -263,7 +263,7 @@ FunctionMapper::FunctionMapper()
"\n" "\n"
" return 32 * n;\n" " return 32 * n;\n"
"}\n"; "}\n";
m_GlobalMap["PerlinNoise3D"] = s_GlobalMap["PerlinNoise3D"] =
"inline real_t PerlinNoise3D(real3* v, __global real_t* p, __global real3* grad, real_t aScale, real_t fScale, int octaves)\n" "inline real_t PerlinNoise3D(real3* v, __global real_t* p, __global real3* grad, real_t aScale, real_t fScale, int octaves)\n"
"{\n" "{\n"
" int i;\n" " int i;\n"
@ -281,11 +281,11 @@ FunctionMapper::FunctionMapper()
"\n" "\n"
" return n;\n" " return n;\n"
"}\n"; "}\n";
m_GlobalMap["JacobiElliptic"] = s_GlobalMap["JacobiElliptic"] =
"inline void JacobiElliptic(real_t uu, real_t emmc, real_t* sn, real_t* cn, real_t* dn)\n" "inline void JacobiElliptic(real_t uu, real_t emmc, real_t* sn, real_t* cn, real_t* dn)\n"
"{\n" "{\n"
" real_t CA = 0.0003;\n" " real_t CA = 0.0003;\n"
" real_t a, b, c, d, em[13], en[13];\n" " real_t a, b, c, d = 1, em[13], en[13];\n"
" int bo;\n" " int bo;\n"
" int l;\n" " int l;\n"
" int ii;\n" " int ii;\n"
@ -371,11 +371,16 @@ FunctionMapper::FunctionMapper()
} }
} }
/// <summary>
/// Get a pointer to the text of the global function whose name is the passed in string.
/// </summary>
/// <param name="func">The function name to retrieve</param>
/// <returns>A pointer to the function body string if found, else nullptr.</returns>
const string* FunctionMapper::GetGlobalFunc(const string& func) const string* FunctionMapper::GetGlobalFunc(const string& func)
{ {
const auto& text = m_GlobalMap.find(func); const auto& text = s_GlobalMap.find(func);
if (text != m_GlobalMap.end()) if (text != s_GlobalMap.end())
return &text->second; return &text->second;
else else
return nullptr; return nullptr;

View File

@ -16,6 +16,6 @@ public:
static const string* GetGlobalFunc(const string& func); static const string* GetGlobalFunc(const string& func);
private: private:
static std::unordered_map<string, string> m_GlobalMap; static std::unordered_map<string, string> s_GlobalMap;
}; };
} }

View File

@ -575,7 +575,7 @@ string IterOpenCLKernelCreator<T>::GlobalFunctionsString(const Ember<T>& ember)
for (auto& funcName : funcNames) for (auto& funcName : funcNames)
if (auto text = m_FunctionMapper.GetGlobalFunc(funcName)) if (auto text = m_FunctionMapper.GetGlobalFunc(funcName))
os << *text << endl; os << *text << "\n";
return os.str(); return os.str();
} }
@ -643,7 +643,7 @@ void IterOpenCLKernelCreator<T>::ParVarIndexDefines(const Ember<T>& ember, pair<
if (!parVar->Params()[k].IsState()) if (!parVar->Params()[k].IsState())
{ {
if (doString) if (doString)
os << "#define " << ToUpper(parVar->Params()[k].Name()) << "_" << i << " " << size << endl;//Uniquely identify this param in this variation in this xform. os << "#define " << ToUpper(parVar->Params()[k].Name()) << "_" << i << " " << size << "\n";//Uniquely identify this param in this variation in this xform.
auto elements = parVar->Params()[k].Size() / sizeof(T); auto elements = parVar->Params()[k].Size() / sizeof(T);
@ -710,7 +710,7 @@ void IterOpenCLKernelCreator<T>::SharedDataIndexDefines(const Ember<T>& ember, p
if (auto dataInfo = varFuncs->GetSharedData(s))///Will contain a name, pointer to data, and size of the data in units of sizeof(T). if (auto dataInfo = varFuncs->GetSharedData(s))///Will contain a name, pointer to data, and size of the data in units of sizeof(T).
{ {
if (doString) if (doString)
os << "#define " << ToUpper(name) << " " << offset << endl; os << "#define " << ToUpper(name) << " " << offset << "\n";
if (doVals) if (doVals)
params.second.insert(params.second.end(), dataInfo->first, dataInfo->first + dataInfo->second); params.second.insert(params.second.end(), dataInfo->first, dataInfo->first + dataInfo->second);

View File

@ -57,12 +57,12 @@ typedef void (*KernelFuncPointer) (size_t gridWidth, size_t gridHeight, size_t b
static void OpenCLSim(size_t gridWidth, size_t gridHeight, size_t blockWidth, size_t blockHeight, KernelFuncPointer func) static void OpenCLSim(size_t gridWidth, size_t gridHeight, size_t blockWidth, size_t blockHeight, KernelFuncPointer func)
{ {
cout << "OpenCLSim(): " << endl; cout << "OpenCLSim(): ";
cout << " Params: " << endl; cout << "\n Params: ";
cout << " gridW: " << gridWidth << endl; cout << "\n gridW: " << gridWidth;
cout << " gridH: " << gridHeight << endl; cout << "\n gridH: " << gridHeight;
cout << " blockW: " << blockWidth << endl; cout << "\n blockW: " << blockWidth;
cout << " blockH: " << blockHeight << endl; cout << "\n blockH: " << blockHeight;
for (size_t i = 0; i < gridHeight; i += blockHeight) for (size_t i = 0; i < gridHeight; i += blockHeight)
{ {

View File

@ -264,35 +264,35 @@ string OpenCLInfo::DumpInfo() const
for (size_t platform = 0; platform < m_Platforms.size(); platform++) for (size_t platform = 0; platform < m_Platforms.size(); platform++)
{ {
os << "Platform " << platform << ": " << PlatformName(platform) << endl; os << "Platform " << platform << ": " << PlatformName(platform) << "\n";
for (size_t device = 0; device < m_Devices[platform].size(); device++) for (size_t device = 0; device < m_Devices[platform].size(); device++)
{ {
os << "Device " << device << ": " << DeviceName(platform, device) << endl; os << "Device " << device << ": " << DeviceName(platform, device);
os << "CL_DEVICE_OPENCL_C_VERSION: " << GetInfo<string>(platform, device, CL_DEVICE_OPENCL_C_VERSION) << endl; os << "\nCL_DEVICE_OPENCL_C_VERSION: " << GetInfo<string>(platform, device, CL_DEVICE_OPENCL_C_VERSION);
os << "CL_DEVICE_LOCAL_MEM_SIZE: " << GetInfo<cl_ulong>(platform, device, CL_DEVICE_LOCAL_MEM_SIZE) << endl; os << "\nCL_DEVICE_LOCAL_MEM_SIZE: " << GetInfo<cl_ulong>(platform, device, CL_DEVICE_LOCAL_MEM_SIZE);
os << "CL_DEVICE_LOCAL_MEM_TYPE: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_LOCAL_MEM_TYPE) << endl; os << "\nCL_DEVICE_LOCAL_MEM_TYPE: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_LOCAL_MEM_TYPE);
os << "CL_DEVICE_MAX_COMPUTE_UNITS: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_MAX_COMPUTE_UNITS) << endl; os << "\nCL_DEVICE_MAX_COMPUTE_UNITS: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_MAX_COMPUTE_UNITS);
os << "CL_DEVICE_MAX_READ_IMAGE_ARGS: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_MAX_READ_IMAGE_ARGS) << endl; os << "\nCL_DEVICE_MAX_READ_IMAGE_ARGS: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_MAX_READ_IMAGE_ARGS);
os << "CL_DEVICE_MAX_WRITE_IMAGE_ARGS: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_MAX_WRITE_IMAGE_ARGS) << endl; os << "\nCL_DEVICE_MAX_WRITE_IMAGE_ARGS: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_MAX_WRITE_IMAGE_ARGS);
os << "CL_DEVICE_MAX_MEM_ALLOC_SIZE: " << GetInfo<cl_ulong>(platform, device, CL_DEVICE_MAX_MEM_ALLOC_SIZE) << endl; os << "\nCL_DEVICE_MAX_MEM_ALLOC_SIZE: " << GetInfo<cl_ulong>(platform, device, CL_DEVICE_MAX_MEM_ALLOC_SIZE);
os << "CL_DEVICE_ADDRESS_BITS: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_ADDRESS_BITS) << endl; os << "\nCL_DEVICE_ADDRESS_BITS: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_ADDRESS_BITS);
os << "CL_DEVICE_GLOBAL_MEM_CACHE_TYPE: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_GLOBAL_MEM_CACHE_TYPE) << endl; os << "\nCL_DEVICE_GLOBAL_MEM_CACHE_TYPE: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_GLOBAL_MEM_CACHE_TYPE);
os << "CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE) << endl; os << "\nCL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE);
os << "CL_DEVICE_GLOBAL_MEM_CACHE_SIZE: " << GetInfo<cl_ulong>(platform, device, CL_DEVICE_GLOBAL_MEM_CACHE_SIZE) << endl; os << "\nCL_DEVICE_GLOBAL_MEM_CACHE_SIZE: " << GetInfo<cl_ulong>(platform, device, CL_DEVICE_GLOBAL_MEM_CACHE_SIZE);
os << "CL_DEVICE_GLOBAL_MEM_SIZE: " << GetInfo<cl_ulong>(platform, device, CL_DEVICE_GLOBAL_MEM_SIZE) << endl; os << "\nCL_DEVICE_GLOBAL_MEM_SIZE: " << GetInfo<cl_ulong>(platform, device, CL_DEVICE_GLOBAL_MEM_SIZE);
os << "CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE: " << GetInfo<cl_ulong>(platform, device, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE) << endl; os << "\nCL_DEVICE_MAX_CONSTANT_BUFFER_SIZE: " << GetInfo<cl_ulong>(platform, device, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE);
os << "CL_DEVICE_MAX_CONSTANT_ARGS: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_MAX_CONSTANT_ARGS) << endl; os << "\nCL_DEVICE_MAX_CONSTANT_ARGS: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_MAX_CONSTANT_ARGS);
os << "CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS) << endl; os << "\nCL_DEVICE_MAX_WORK_ITEM_DIMENSIONS: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS);
os << "CL_DEVICE_MAX_WORK_GROUP_SIZE: " << GetInfo<size_t>(platform, device, CL_DEVICE_MAX_WORK_GROUP_SIZE) << endl; os << "\nCL_DEVICE_MAX_WORK_GROUP_SIZE: " << GetInfo<size_t>(platform, device, CL_DEVICE_MAX_WORK_GROUP_SIZE);
sizes = GetInfo<vector<size_t>>(platform, device, CL_DEVICE_MAX_WORK_ITEM_SIZES); sizes = GetInfo<vector<size_t>>(platform, device, CL_DEVICE_MAX_WORK_ITEM_SIZES);
os << "CL_DEVICE_MAX_WORK_ITEM_SIZES: " << sizes[0] << ", " << sizes[1] << ", " << sizes[2] << endl << endl; os << "\nCL_DEVICE_MAX_WORK_ITEM_SIZES: " << sizes[0] << ", " << sizes[1] << ", " << sizes[2] << "\n" << "\n";
if (device != m_Devices[platform].size() - 1 && platform != m_Platforms.size() - 1) if (device != m_Devices[platform].size() - 1 && platform != m_Platforms.size() - 1)
os << endl; os << "\n";
} }
os << endl; os << "\n";
} }
return os.str(); return os.str();
@ -309,7 +309,7 @@ bool OpenCLInfo::CheckCL(cl_int err, const char* name)
if (err != CL_SUCCESS) if (err != CL_SUCCESS)
{ {
ostringstream ss; ostringstream ss;
ss << "ERROR: " << ErrorToStringCL(err) << " in " << name << "." << endl; ss << "ERROR: " << ErrorToStringCL(err) << " in " << name << ".\n";
AddToReport(ss.str()); AddToReport(ss.str());
} }

View File

@ -332,7 +332,7 @@ bool OpenCLWrapper::AddAndWriteImage(const string& name, cl_mem_flags flags, con
if (shared) if (shared)
{ {
//::wglMakeCurrent(wglGetCurrentDC(), wglGetCurrentContext()); //::wglMakeCurrent(wglGetCurrentDC(), wglGetCurrentContext());
IMAGEGL2D imageGL(m_Context, flags, GL_TEXTURE_2D, 0, texName, &err); cl::ImageGL imageGL(m_Context, flags, GL_TEXTURE_2D, 0, texName, &err);
NamedImage2DGL namedImageGL(imageGL, name); NamedImage2DGL namedImageGL(imageGL, name);
if (m_Info->CheckCL(err, "cl::ImageGL()")) if (m_Info->CheckCL(err, "cl::ImageGL()"))
@ -360,11 +360,11 @@ bool OpenCLWrapper::AddAndWriteImage(const string& name, cl_mem_flags flags, con
{ {
if (shared) if (shared)
{ {
IMAGEGL2D imageGL = m_GLImages[imageIndex].m_Image; cl::ImageGL imageGL = m_GLImages[imageIndex].m_Image;
if (!CompareImageParams(imageGL, flags, format, width, height, row_pitch)) if (!CompareImageParams(imageGL, flags, format, width, height, row_pitch))
{ {
NamedImage2DGL namedImageGL(IMAGEGL2D(m_Context, flags, GL_TEXTURE_2D, 0, texName, &err), name);//Sizes are different, so create new. NamedImage2DGL namedImageGL(cl::ImageGL(m_Context, flags, GL_TEXTURE_2D, 0, texName, &err), name);//Sizes are different, so create new.
if (m_Info->CheckCL(err, "cl::ImageGL()")) if (m_Info->CheckCL(err, "cl::ImageGL()"))
{ {
@ -430,7 +430,7 @@ bool OpenCLWrapper::WriteImage2D(size_t index, bool shared, ::size_t width, ::si
if (shared && index < m_GLImages.size()) if (shared && index < m_GLImages.size())
{ {
IMAGEGL2D imageGL = m_GLImages[index].m_Image; cl::ImageGL imageGL = m_GLImages[index].m_Image;
if (EnqueueAcquireGLObjects(imageGL)) if (EnqueueAcquireGLObjects(imageGL))
{ {
@ -502,7 +502,7 @@ bool OpenCLWrapper::ReadImage(size_t imageIndex, ::size_t width, ::size_t height
if (shared && imageIndex < m_GLImages.size()) if (shared && imageIndex < m_GLImages.size())
{ {
IMAGEGL2D imageGL = m_GLImages[imageIndex].m_Image; cl::ImageGL imageGL = m_GLImages[imageIndex].m_Image;
if (EnqueueAcquireGLObjects(imageGL)) if (EnqueueAcquireGLObjects(imageGL))
{ {
@ -573,7 +573,7 @@ size_t OpenCLWrapper::GetImageSize(size_t imageIndex, bool shared)
{ {
vector<cl::Memory> images; vector<cl::Memory> images;
images.push_back(m_GLImages[imageIndex].m_Image); images.push_back(m_GLImages[imageIndex].m_Image);
IMAGEGL2D image = m_GLImages[imageIndex].m_Image; cl::ImageGL image = m_GLImages[imageIndex].m_Image;
if (EnqueueAcquireGLObjects(&images)) if (EnqueueAcquireGLObjects(&images))
size = image.getImageInfo<CL_IMAGE_WIDTH>(nullptr) * image.getImageInfo<CL_IMAGE_HEIGHT>(nullptr) * image.getImageInfo<CL_IMAGE_ELEMENT_SIZE>(nullptr);//Should pitch be checked here? size = image.getImageInfo<CL_IMAGE_WIDTH>(nullptr) * image.getImageInfo<CL_IMAGE_HEIGHT>(nullptr) * image.getImageInfo<CL_IMAGE_ELEMENT_SIZE>(nullptr);//Should pitch be checked here?
@ -662,12 +662,12 @@ bool OpenCLWrapper::CreateImage2D(cl::Image2D& image2D, cl_mem_flags flags, cl::
/// <param name="miplevel">The mip map level</param> /// <param name="miplevel">The mip map level</param>
/// <param name="texobj">The texture ID of the shared OpenGL texture</param> /// <param name="texobj">The texture ID of the shared OpenGL texture</param>
/// <returns>True if success, else false.</returns> /// <returns>True if success, else false.</returns>
bool OpenCLWrapper::CreateImage2DGL(IMAGEGL2D& image2DGL, cl_mem_flags flags, GLenum target, GLint miplevel, GLuint texobj) bool OpenCLWrapper::CreateImage2DGL(cl::ImageGL& image2DGL, cl_mem_flags flags, GLenum target, GLint miplevel, GLuint texobj)
{ {
if (m_Init) if (m_Init)
{ {
cl_int err; cl_int err;
image2DGL = IMAGEGL2D(m_Context, image2DGL = cl::ImageGL(m_Context,
flags, flags,
target, target,
miplevel, miplevel,
@ -699,7 +699,7 @@ bool OpenCLWrapper::EnqueueAcquireGLObjects(const string& name)
/// </summary> /// </summary>
/// <param name="image">The image to acquire</param> /// <param name="image">The image to acquire</param>
/// <returns>True if success, else false.</returns> /// <returns>True if success, else false.</returns>
bool OpenCLWrapper::EnqueueAcquireGLObjects(IMAGEGL2D& image) bool OpenCLWrapper::EnqueueAcquireGLObjects(cl::ImageGL& image)
{ {
if (m_Init && m_Shared) if (m_Init && m_Shared)
{ {
@ -733,7 +733,7 @@ bool OpenCLWrapper::EnqueueReleaseGLObjects(const string& name)
/// </summary> /// </summary>
/// <param name="image">The image to release</param> /// <param name="image">The image to release</param>
/// <returns>True if success, else false.</returns> /// <returns>True if success, else false.</returns>
bool OpenCLWrapper::EnqueueReleaseGLObjects(IMAGEGL2D& image) bool OpenCLWrapper::EnqueueReleaseGLObjects(cl::ImageGL& image)
{ {
if (m_Init && m_Shared) if (m_Init && m_Shared)
{ {

View File

@ -9,8 +9,6 @@
namespace EmberCLns namespace EmberCLns
{ {
#define IMAGEGL2D cl::ImageGL
/// <summary> /// <summary>
/// Class to contain all of the things needed to store an OpenCL program. /// Class to contain all of the things needed to store an OpenCL program.
/// The name of it, the source, the compiled program object and the kernel. /// The name of it, the source, the compiled program object and the kernel.
@ -75,13 +73,13 @@ public:
{ {
} }
NamedImage2DGL(const IMAGEGL2D& image, const string& name) NamedImage2DGL(const cl::ImageGL& image, const string& name)
{ {
m_Image = image; m_Image = image;
m_Name = name; m_Name = name;
} }
IMAGEGL2D m_Image; cl::ImageGL m_Image;
string m_Name; string m_Name;
}; };
@ -129,11 +127,11 @@ public:
bool CompareImageParams(cl::Image& image, cl_mem_flags flags, const cl::ImageFormat& format, ::size_t width, ::size_t height, ::size_t row_pitch); bool CompareImageParams(cl::Image& image, cl_mem_flags flags, const cl::ImageFormat& format, ::size_t width, ::size_t height, ::size_t row_pitch);
void ClearImages(bool shared); void ClearImages(bool shared);
bool CreateImage2D(cl::Image2D& image2D, cl_mem_flags flags, cl::ImageFormat format, ::size_t width, ::size_t height, ::size_t row_pitch = 0, void* data = NULL); bool CreateImage2D(cl::Image2D& image2D, cl_mem_flags flags, cl::ImageFormat format, ::size_t width, ::size_t height, ::size_t row_pitch = 0, void* data = NULL);
bool CreateImage2DGL(IMAGEGL2D& image2DGL, cl_mem_flags flags, GLenum target, GLint miplevel, GLuint texobj); bool CreateImage2DGL(cl::ImageGL& image2DGL, cl_mem_flags flags, GLenum target, GLint miplevel, GLuint texobj);
bool EnqueueAcquireGLObjects(const string& name); bool EnqueueAcquireGLObjects(const string& name);
bool EnqueueAcquireGLObjects(IMAGEGL2D& image); bool EnqueueAcquireGLObjects(cl::ImageGL& image);
bool EnqueueReleaseGLObjects(const string& name); bool EnqueueReleaseGLObjects(const string& name);
bool EnqueueReleaseGLObjects(IMAGEGL2D& image); bool EnqueueReleaseGLObjects(cl::ImageGL& image);
bool EnqueueAcquireGLObjects(const VECTOR_CLASS<cl::Memory>* memObjects = NULL); bool EnqueueAcquireGLObjects(const VECTOR_CLASS<cl::Memory>* memObjects = NULL);
bool EnqueueReleaseGLObjects(const VECTOR_CLASS<cl::Memory>* memObjects = NULL); bool EnqueueReleaseGLObjects(const VECTOR_CLASS<cl::Memory>* memObjects = NULL);
bool CreateSampler(cl::Sampler& sampler, cl_bool normalizedCoords, cl_addressing_mode addressingMode, cl_filter_mode filterMode); bool CreateSampler(cl::Sampler& sampler, cl_bool normalizedCoords, cl_addressing_mode addressingMode, cl_filter_mode filterMode);

View File

@ -895,25 +895,23 @@ bool RendererCL<T, bucketT>::BuildIterProgramForEmber(bool doAccum)
if (b) if (b)
{ {
m_IterKernel = m_IterOpenCLKernelCreator.CreateIterKernelString(m_Ember, m_Params.first, m_GlobalShared.first, m_LockAccum, doAccum); m_IterKernel = m_IterOpenCLKernelCreator.CreateIterKernelString(m_Ember, m_Params.first, m_GlobalShared.first, m_LockAccum, doAccum);
//cout << "Building: " << endl << iterProgram << endl; //cout << "Building: " << "\n" << iterProgram << "\n";
vector<std::thread> threads; vector<std::thread> threads;
std::function<void(RendererClDevice*)> func = [&](RendererClDevice * dev) std::function<void(RendererClDevice*)> func = [&](RendererClDevice * dev)
{ {
if (!dev->m_Wrapper.AddProgram(m_IterOpenCLKernelCreator.IterEntryPoint(), m_IterKernel, m_IterOpenCLKernelCreator.IterEntryPoint(), m_DoublePrecision)) if (!dev->m_Wrapper.AddProgram(m_IterOpenCLKernelCreator.IterEntryPoint(), m_IterKernel, m_IterOpenCLKernelCreator.IterEntryPoint(), m_DoublePrecision))
{ {
m_ResizeCs.Enter();//Just use the resize CS for lack of a better one. rlg l(m_ResizeCs);//Just use the resize CS for lack of a better one.
b = false; b = false;
AddToReport(string(loc) + "()\n" + dev->m_Wrapper.DeviceName() + ":\nBuilding the following program failed: \n" + m_IterKernel + "\n"); AddToReport(string(loc) + "()\n" + dev->m_Wrapper.DeviceName() + ":\nBuilding the following program failed: \n" + m_IterKernel + "\n");
m_ResizeCs.Leave();
} }
else if (!m_GlobalShared.second.empty()) else if (!m_GlobalShared.second.empty())
{ {
if (!dev->m_Wrapper.AddAndWriteBuffer(m_GlobalSharedBufferName, m_GlobalShared.second.data(), m_GlobalShared.second.size() * sizeof(m_GlobalShared.second[0]))) if (!dev->m_Wrapper.AddAndWriteBuffer(m_GlobalSharedBufferName, m_GlobalShared.second.data(), m_GlobalShared.second.size() * sizeof(m_GlobalShared.second[0])))
{ {
m_ResizeCs.Enter();//Just use the resize CS for lack of a better one. rlg l(m_ResizeCs);//Just use the resize CS for lack of a better one.
b = false; b = false;
AddToReport(string(loc) + "()\n" + dev->m_Wrapper.DeviceName() + ":\nAdding global shared buffer failed.\n"); AddToReport(string(loc) + "()\n" + dev->m_Wrapper.DeviceName() + ":\nAdding global shared buffer failed.\n");
m_ResizeCs.Leave();
} }
} }
}; };
@ -934,7 +932,7 @@ bool RendererCL<T, bucketT>::BuildIterProgramForEmber(bool doAccum)
if (b) if (b)
{ {
//t.Toc(__FUNCTION__ " program build"); //t.Toc(__FUNCTION__ " program build");
//cout << string(loc) << "():\nBuilding the following program succeeded: \n" << iterProgram << endl; //cout << string(loc) << "():\nBuilding the following program succeeded: \n" << iterProgram << "\n";
m_LastBuiltEmber = m_Ember; m_LastBuiltEmber = m_Ember;
} }
} }
@ -988,7 +986,7 @@ bool RendererCL<T, bucketT>::RunIter(size_t iterCount, size_t temporalSample, si
{ {
bool b = true; bool b = true;
auto& wrapper = m_Devices[dev]->m_Wrapper; auto& wrapper = m_Devices[dev]->m_Wrapper;
intmax_t itersRemaining; intmax_t itersRemaining = 0;
while (atomLaunchesRan.fetch_add(1), (b && (atomLaunchesRan.load() <= launches) && ((itersRemaining = atomItersRemaining.load()) > 0) && !m_Abort)) while (atomLaunchesRan.fetch_add(1), (b && (atomLaunchesRan.load() <= launches) && ((itersRemaining = atomItersRemaining.load()) > 0) && !m_Abort))
{ {
@ -1002,7 +1000,7 @@ bool RendererCL<T, bucketT>::RunIter(size_t iterCount, size_t temporalSample, si
//The number of iters per thread must be adjusted if they've requested less iters than is normally ran in a grid (256 * 256 * 64 * 2 = 32,768). //The number of iters per thread must be adjusted if they've requested less iters than is normally ran in a grid (256 * 256 * 64 * 2 = 32,768).
uint iterCountPerKernel = std::min<uint>(uint(adjustedIterCountPerKernel), uint(ceil(double(itersRemaining) / IterGridKernelCount()))); uint iterCountPerKernel = std::min<uint>(uint(adjustedIterCountPerKernel), uint(ceil(double(itersRemaining) / IterGridKernelCount())));
size_t iterCountThisLaunch = iterCountPerKernel * IterGridKernelWidth() * IterGridKernelHeight(); size_t iterCountThisLaunch = iterCountPerKernel * IterGridKernelWidth() * IterGridKernelHeight();
//cout << "itersRemaining " << itersRemaining << ", iterCountPerKernel " << iterCountPerKernel << ", iterCountThisLaunch " << iterCountThisLaunch << endl; //cout << "itersRemaining " << itersRemaining << ", iterCountPerKernel " << iterCountPerKernel << ", iterCountThisLaunch " << iterCountThisLaunch << "\n";
if (b && !(b = wrapper.SetArg (kernelIndex, argIndex++, iterCountPerKernel))) { AddToReport(loc); }//Number of iters for each thread to run. if (b && !(b = wrapper.SetArg (kernelIndex, argIndex++, iterCountPerKernel))) { AddToReport(loc); }//Number of iters for each thread to run.

View File

@ -222,7 +222,7 @@ private:
cl::ImageFormat m_PaletteFormat; cl::ImageFormat m_PaletteFormat;
cl::ImageFormat m_FinalFormat; cl::ImageFormat m_FinalFormat;
cl::Image2D m_Palette; cl::Image2D m_Palette;
IMAGEGL2D m_AccumImage; cl::ImageGL m_AccumImage;
GLuint m_OutputTexID; GLuint m_OutputTexID;
EmberCL<T> m_EmberCL; EmberCL<T> m_EmberCL;
vector<XformCL<T>> m_XformsCL; vector<XformCL<T>> m_XformsCL;

View File

@ -439,7 +439,7 @@ public:
case eOptionIDs::OPT_VERSION: case eOptionIDs::OPT_VERSION:
{ {
cout << EmberVersion() << endl; cout << EmberVersion() << "\n";
return true; return true;
} }
@ -540,8 +540,8 @@ public:
} }
else else
{ {
cout << "Invalid argument: " << args.OptionText() << endl; cout << "Invalid argument: " << args.OptionText() << "\n";
cout << "\tReason: " << GetLastErrorText(errorCode) << endl; cout << "\tReason: " << GetLastErrorText(errorCode) << "\n";
} }
} }
@ -608,15 +608,15 @@ public:
{ {
ostringstream os; ostringstream os;
for (auto entry : m_BoolArgs) if (et(entry->m_OptionUse) & et(optUsage)) os << entry->m_DocString << endl; for (auto entry : m_BoolArgs) if (et(entry->m_OptionUse) & et(optUsage)) os << entry->m_DocString << "\n";
for (auto entry : m_IntArgs) if (et(entry->m_OptionUse) & et(optUsage)) os << entry->m_DocString << endl; for (auto entry : m_IntArgs) if (et(entry->m_OptionUse) & et(optUsage)) os << entry->m_DocString << "\n";
for (auto entry : m_UintArgs) if (et(entry->m_OptionUse) & et(optUsage)) os << entry->m_DocString << endl; for (auto entry : m_UintArgs) if (et(entry->m_OptionUse) & et(optUsage)) os << entry->m_DocString << "\n";
for (auto entry : m_DoubleArgs) if (et(entry->m_OptionUse) & et(optUsage)) os << entry->m_DocString << endl; for (auto entry : m_DoubleArgs) if (et(entry->m_OptionUse) & et(optUsage)) os << entry->m_DocString << "\n";
for (auto entry : m_StringArgs) if (et(entry->m_OptionUse) & et(optUsage)) os << entry->m_DocString << endl; for (auto entry : m_StringArgs) if (et(entry->m_OptionUse) & et(optUsage)) os << entry->m_DocString << "\n";
return os.str(); return os.str();
} }
@ -631,15 +631,15 @@ public:
ostringstream os; ostringstream os;
os << std::boolalpha; os << std::boolalpha;
for (auto entry : m_BoolArgs) if (et(entry->m_OptionUse) & et(optUsage)) os << entry->m_NameWithoutDashes << ": " << (*entry)() << endl; for (auto entry : m_BoolArgs) if (et(entry->m_OptionUse) & et(optUsage)) os << entry->m_NameWithoutDashes << ": " << (*entry)() << "\n";
for (auto entry : m_IntArgs) if (et(entry->m_OptionUse) & et(optUsage)) os << entry->m_NameWithoutDashes << ": " << (*entry)() << endl; for (auto entry : m_IntArgs) if (et(entry->m_OptionUse) & et(optUsage)) os << entry->m_NameWithoutDashes << ": " << (*entry)() << "\n";
for (auto entry : m_UintArgs) if (et(entry->m_OptionUse) & et(optUsage)) os << entry->m_NameWithoutDashes << ": " << (*entry)() << endl; for (auto entry : m_UintArgs) if (et(entry->m_OptionUse) & et(optUsage)) os << entry->m_NameWithoutDashes << ": " << (*entry)() << "\n";
for (auto entry : m_DoubleArgs) if (et(entry->m_OptionUse) & et(optUsage)) os << entry->m_NameWithoutDashes << ": " << (*entry)() << endl; for (auto entry : m_DoubleArgs) if (et(entry->m_OptionUse) & et(optUsage)) os << entry->m_NameWithoutDashes << ": " << (*entry)() << "\n";
for (auto entry : m_StringArgs) if (et(entry->m_OptionUse) & et(optUsage)) os << entry->m_NameWithoutDashes << ": " << (*entry)() << endl; for (auto entry : m_StringArgs) if (et(entry->m_OptionUse) & et(optUsage)) os << entry->m_NameWithoutDashes << ": " << (*entry)() << "\n";
return os.str(); return os.str();
} }
@ -650,25 +650,25 @@ public:
/// <param name="optUsage">The specified program usage</param> /// <param name="optUsage">The specified program usage</param>
void ShowUsage(eOptionUse optUsage) void ShowUsage(eOptionUse optUsage)
{ {
cout << DescriptionString << " version " << EmberVersion() << endl << endl; cout << DescriptionString << " version " << EmberVersion() << "\n\n";
if (optUsage == eOptionUse::OPT_USE_RENDER) if (optUsage == eOptionUse::OPT_USE_RENDER)
{ {
cout << "Usage:\n" cout << "Usage:\n"
"\tEmberRender.exe --in=test.flam3 [--out=outfile --format=png --verbose --progress --opencl]\n" << endl; "\tEmberRender.exe --in=test.flam3 [--out=outfile --format=png --verbose --progress --opencl]\n\n";
} }
else if (optUsage == eOptionUse::OPT_USE_ANIMATE) else if (optUsage == eOptionUse::OPT_USE_ANIMATE)
{ {
cout << "Usage:\n" cout << "Usage:\n"
"\tEmberAnimate.exe --in=sequence.flam3 [--format=png --verbose --progress --opencl]\n" << endl; "\tEmberAnimate.exe --in=sequence.flam3 [--format=png --verbose --progress --opencl]\n\n";
} }
else if (optUsage == eOptionUse::OPT_USE_GENOME) else if (optUsage == eOptionUse::OPT_USE_GENOME)
{ {
cout << "Usage:\n" cout << "Usage:\n"
"\tEmberGenome.exe --sequence=test.flam3 > sequenceout.flam3\n" << endl; "\tEmberGenome.exe --sequence=test.flam3 > sequenceout.flam3\n\n";
} }
cout << GetUsage(optUsage) << endl; cout << GetUsage(optUsage) << "\n";
} }
/// <summary> /// <summary>

View File

@ -55,11 +55,11 @@ bool EmberGenome(EmberOptions& opt)
std::cout.imbue(std::locale("")); std::cout.imbue(std::locale(""));
if (opt.DumpArgs()) if (opt.DumpArgs())
cerr << opt.GetValues(eOptionUse::OPT_USE_GENOME) << endl; cerr << opt.GetValues(eOptionUse::OPT_USE_GENOME) << "\n";
if (opt.OpenCLInfo()) if (opt.OpenCLInfo())
{ {
cerr << "\nOpenCL Info: " << endl; cerr << "\nOpenCL Info: \n";
cerr << info->DumpInfo(); cerr << info->DumpInfo();
return true; return true;
} }
@ -98,7 +98,7 @@ bool EmberGenome(EmberOptions& opt)
if (!renderer.get()) if (!renderer.get())
{ {
cerr << "Renderer creation failed, exiting." << endl; cerr << "Renderer creation failed, exiting.\n";
return false; return false;
} }
@ -112,14 +112,14 @@ bool EmberGenome(EmberOptions& opt)
} }
else else
{ {
cerr << "Using OpenCL to render." << endl; cerr << "Using OpenCL to render.\n";
if (opt.Verbose()) if (opt.Verbose())
{ {
for (auto& device : devices) for (auto& device : devices)
{ {
cerr << "Platform: " << info->PlatformName(device.first) << endl; cerr << "Platform: " << info->PlatformName(device.first) << "\n";
cerr << "Device: " << info->DeviceName(device.first, device.second) << endl; cerr << "Device: " << info->DeviceName(device.first, device.second) << "\n";
} }
} }
} }
@ -139,7 +139,7 @@ bool EmberGenome(EmberOptions& opt)
if (opt.UseVars() != "" && opt.DontUseVars() != "") if (opt.UseVars() != "" && opt.DontUseVars() != "")
{ {
cerr << "use_vars and dont_use_vars cannot both be specified. Returning without executing." << endl; cerr << "use_vars and dont_use_vars cannot both be specified. Returning without executing.\n";
return false; return false;
} }
@ -231,19 +231,19 @@ bool EmberGenome(EmberOptions& opt)
if (count > 1) if (count > 1)
{ {
cerr << "Can only specify one of mutate, clone, cross, rotate, strip, or inter. Returning without executing." << endl; cerr << "Can only specify one of mutate, clone, cross, rotate, strip, or inter. Returning without executing.\n";
return false; return false;
} }
if (doCross0 != doCross1)//Must both be either true or false. if (doCross0 != doCross1)//Must both be either true or false.
{ {
cerr << "Must specify both crossover arguments. Returning without executing." << endl; cerr << "Must specify both crossover arguments. Returning without executing.\n";
return false; return false;
} }
if (opt.Method() != "" && (!doCross0 && !doMutate)) if (opt.Method() != "" && (!doCross0 && !doMutate))
{ {
cerr << "Cannot specify method unless doing crossover or mutate. Returning without executing." << endl; cerr << "Cannot specify method unless doing crossover or mutate. Returning without executing.\n";
return false; return false;
} }
@ -253,7 +253,7 @@ bool EmberGenome(EmberOptions& opt)
return false; return false;
if (templateEmbers.size() > 1) if (templateEmbers.size() > 1)
cerr << "More than one control point in template, ignoring all but first." << endl; cerr << "More than one control point in template, ignoring all but first.\n";
pTemplate = &templateEmbers[0]; pTemplate = &templateEmbers[0];
} }
@ -297,7 +297,7 @@ bool EmberGenome(EmberOptions& opt)
if (opt.CloneAll() != "") if (opt.CloneAll() != "")
{ {
cout << "<clone_all version=\"Ember-" << EmberVersion() << "\">" << endl; cout << "<clone_all version=\"Ember-" << EmberVersion() << "\">\n";
for (i = 0; i < embers.size(); i++) for (i = 0; i < embers.size(); i++)
{ {
@ -308,7 +308,7 @@ bool EmberGenome(EmberOptions& opt)
cout << emberToXml.ToString(embers[i], opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), false, opt.HexPalette()); cout << emberToXml.ToString(embers[i], opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), false, opt.HexPalette());
} }
cout << "</clone_all>" << endl; cout << "</clone_all>\n";
return true; return true;
} }
@ -318,7 +318,7 @@ bool EmberGenome(EmberOptions& opt)
{ {
if (i > 0 && embers[i].m_Time <= embers[i - 1].m_Time) if (i > 0 && embers[i].m_Time <= embers[i - 1].m_Time)
{ {
cerr << "Error: control points must be sorted by time, but " << embers[i].m_Time << " <= " << embers[i - 1].m_Time << ", index " << i << "." << endl; cerr << "Error: control points must be sorted by time, but " << embers[i].m_Time << " <= " << embers[i - 1].m_Time << ", index " << i << ".\n";
return false; return false;
} }
@ -331,7 +331,7 @@ bool EmberGenome(EmberOptions& opt)
if (lastFrame < firstFrame) if (lastFrame < firstFrame)
lastFrame = firstFrame; lastFrame = firstFrame;
cout << "<animate version=\"EMBER-" << EmberVersion() << "\">" << endl; cout << "<animate version=\"EMBER-" << EmberVersion() << "\">\n";
for (ftime = firstFrame; ftime <= lastFrame; ftime++) for (ftime = firstFrame; ftime <= lastFrame; ftime++)
{ {
@ -370,7 +370,7 @@ bool EmberGenome(EmberOptions& opt)
cout << emberToXml.ToString(interpolated, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), false, opt.HexPalette()); cout << emberToXml.ToString(interpolated, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), false, opt.HexPalette());
} }
cout << "</animate>" << endl; cout << "</animate>\n";
return true; return true;
} }
@ -380,12 +380,12 @@ bool EmberGenome(EmberOptions& opt)
if (opt.Frames() == 0) if (opt.Frames() == 0)
{ {
cerr << "nframes must be positive and non-zero, not " << opt.Frames() << "." << endl; cerr << "nframes must be positive and non-zero, not " << opt.Frames() << ".\n";
return false; return false;
} }
if (opt.Enclosed()) if (opt.Enclosed())
cout << "<sequence version=\"EMBER-" << EmberVersion() << "\">" << endl; cout << "<sequence version=\"EMBER-" << EmberVersion() << "\">\n";
spread = 1 / T(opt.Frames()); spread = 1 / T(opt.Frames());
frameCount = 0; frameCount = 0;
@ -437,7 +437,7 @@ bool EmberGenome(EmberOptions& opt)
cout << emberToXml.ToString(result, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), false, opt.HexPalette()); cout << emberToXml.ToString(result, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), false, opt.HexPalette());
if (opt.Enclosed()) if (opt.Enclosed())
cout << "</sequence>" << endl; cout << "</sequence>\n";
return true; return true;
} }
@ -448,7 +448,7 @@ bool EmberGenome(EmberOptions& opt)
if (opt.Frames() == 0) if (opt.Frames() == 0)
{ {
cerr << "nframes must be positive and non-zero, not " << opt.Frames() << "." << endl; cerr << "nframes must be positive and non-zero, not " << opt.Frames() << ".\n";
return false; return false;
} }
@ -456,13 +456,13 @@ bool EmberGenome(EmberOptions& opt)
spread = 1 / T(opt.Frames()); spread = 1 / T(opt.Frames());
if (opt.Enclosed()) if (opt.Enclosed())
cout << "<pick version=\"EMBER-" << EmberVersion() << "\">" << endl; cout << "<pick version=\"EMBER-" << EmberVersion() << "\">\n";
if (doRotate) if (doRotate)
{ {
if (embers.size() != 1) if (embers.size() != 1)
{ {
cerr << "rotation requires one control point, not " << embers.size() << "." << endl; cerr << "rotation requires one control point, not " << embers.size() << ".\n";
return false; return false;
} }
@ -477,7 +477,7 @@ bool EmberGenome(EmberOptions& opt)
{ {
if (embers.size() != 2) if (embers.size() != 2)
{ {
cerr << "interpolation requires two control points, not " << embers.size() << "." << endl; cerr << "interpolation requires two control points, not " << embers.size() << ".\n";
return false; return false;
} }
@ -490,7 +490,7 @@ bool EmberGenome(EmberOptions& opt)
} }
if (opt.Enclosed()) if (opt.Enclosed())
cout << "</pick>" << endl; cout << "</pick>\n";
return true; return true;
} }
@ -498,7 +498,7 @@ bool EmberGenome(EmberOptions& opt)
if (doStrip) if (doStrip)
{ {
if (opt.Enclosed()) if (opt.Enclosed())
cout << "<pick version=\"EMBER-" << EmberVersion() << "\">" << endl; cout << "<pick version=\"EMBER-" << EmberVersion() << "\">\n";
for (i = 0; i < embers.size(); i++) for (i = 0; i < embers.size(); i++)
{ {
@ -520,7 +520,7 @@ bool EmberGenome(EmberOptions& opt)
} }
if (opt.Enclosed()) if (opt.Enclosed())
cout << "</pick>" << endl; cout << "</pick>\n";
return true; return true;
} }
@ -534,12 +534,12 @@ bool EmberGenome(EmberOptions& opt)
if (opt.Repeat() == 0) if (opt.Repeat() == 0)
{ {
cerr << "Repeat must be positive, not " << opt.Repeat() << endl; cerr << "Repeat must be positive, not " << opt.Repeat() << "\n";
return false; return false;
} }
if (opt.Enclosed()) if (opt.Enclosed())
cout << "<pick version=\"EMBER-" << EmberVersion() << "\">" << endl; cout << "<pick version=\"EMBER-" << EmberVersion() << "\">\n";
for (rep = 0; rep < opt.Repeat(); rep++) for (rep = 0; rep < opt.Repeat(); rep++)
{ {
@ -596,7 +596,7 @@ bool EmberGenome(EmberOptions& opt)
mutMeth = eMutateMode::MUTATE_ALL_COEFS; mutMeth = eMutateMode::MUTATE_ALL_COEFS;
else else
{ {
cerr << "method " << opt.Method() << " not defined for mutate. Defaulting to random." << endl; cerr << "method " << opt.Method() << " not defined for mutate. Defaulting to random.\n";
mutMeth = eMutateMode::MUTATE_NOT_SPECIFIED; mutMeth = eMutateMode::MUTATE_NOT_SPECIFIED;
} }
@ -632,7 +632,7 @@ bool EmberGenome(EmberOptions& opt)
crossMeth = eCrossMode::CROSS_ALTERNATE; crossMeth = eCrossMode::CROSS_ALTERNATE;
else else
{ {
cerr << "method '" << opt.Method() << "' not defined for cross. Defaulting to random." << endl; cerr << "method '" << opt.Method() << "' not defined for cross. Defaulting to random.\n";
crossMeth = eCrossMode::CROSS_NOT_SPECIFIED; crossMeth = eCrossMode::CROSS_NOT_SPECIFIED;
} }
@ -699,7 +699,7 @@ bool EmberGenome(EmberOptions& opt)
if (!didColor && rand.RandBit()) if (!didColor && rand.RandBit())
{ {
if (opt.Debug()) if (opt.Debug())
cerr << "improving colors..." << endl; cerr << "improving colors...\n";
tools.ImproveColors(orig, 100, false, 10); tools.ImproveColors(orig, 100, false, 10);
os << " improved colors"; os << " improved colors";
@ -712,7 +712,7 @@ bool EmberGenome(EmberOptions& opt)
if (renderer->Run(finalImage) != eRenderStatus::RENDER_OK) if (renderer->Run(finalImage) != eRenderStatus::RENDER_OK)
{ {
cerr << "Error: test image rendering failed, aborting." << endl; cerr << "Error: test image rendering failed, aborting.\n";
return false; return false;
} }
@ -733,7 +733,7 @@ bool EmberGenome(EmberOptions& opt)
fractionWhite = totw / T(n); fractionWhite = totw / T(n);
if (opt.Debug()) if (opt.Debug())
cerr << "avgPix = " << avgPix << " fractionBlack = " << fractionBlack << " fractionWhite = " << fractionWhite << " n = " << n << endl; cerr << "avgPix = " << avgPix << " fractionBlack = " << fractionBlack << " fractionWhite = " << fractionWhite << " n = " << n << "\n";
orig.Clear(); orig.Clear();
count++; count++;
@ -744,7 +744,7 @@ bool EmberGenome(EmberOptions& opt)
count < opt.Tries()); count < opt.Tries());
if (count == opt.Tries()) if (count == opt.Tries())
cerr << "Warning: reached maximum attempts, giving up." << endl; cerr << "Warning: reached maximum attempts, giving up.\n";
} }
if (pTemplate) if (pTemplate)
@ -806,7 +806,7 @@ int _tmain(int argc, _TCHAR* argv[])
} }
else if (opt.Bits() == 32) else if (opt.Bits() == 32)
{ {
cerr << "Bits 32/int histogram no longer supported. Using bits == 33 (float)." << endl; cerr << "Bits 32/int histogram no longer supported. Using bits == 33 (float).\n";
b = EmberGenome<float>(opt); b = EmberGenome<float>(opt);
} }
} }

View File

@ -17,11 +17,11 @@ bool EmberRender(EmberOptions& opt)
std::cout.imbue(std::locale("")); std::cout.imbue(std::locale(""));
if (opt.DumpArgs()) if (opt.DumpArgs())
cout << opt.GetValues(eOptionUse::OPT_USE_RENDER) << endl; cout << opt.GetValues(eOptionUse::OPT_USE_RENDER) << "\n";
if (opt.OpenCLInfo()) if (opt.OpenCLInfo())
{ {
cout << "\nOpenCL Info: " << endl; cout << "\nOpenCL Info: \n";
cout << info->DumpInfo(); cout << info->DumpInfo();
return true; return true;
} }
@ -55,7 +55,7 @@ bool EmberRender(EmberOptions& opt)
if (!renderer.get()) if (!renderer.get())
{ {
cout << "Renderer creation failed, exiting." << endl; cout << "Renderer creation failed, exiting.\n" ;
return false; return false;
} }
@ -72,38 +72,38 @@ bool EmberRender(EmberOptions& opt)
{ {
if (opt.ThreadCount() == 0) if (opt.ThreadCount() == 0)
{ {
cout << "Using " << Timing::ProcessorCount() << " automatically detected threads." << endl; cout << "Using " << Timing::ProcessorCount() << " automatically detected threads.\n";
opt.ThreadCount(Timing::ProcessorCount()); opt.ThreadCount(Timing::ProcessorCount());
} }
else else
{ {
cout << "Using " << opt.ThreadCount() << " manually specified threads." << endl; cout << "Using " << opt.ThreadCount() << " manually specified threads.\n";
} }
renderer->ThreadCount(opt.ThreadCount(), opt.IsaacSeed() != "" ? opt.IsaacSeed().c_str() : nullptr); renderer->ThreadCount(opt.ThreadCount(), opt.IsaacSeed() != "" ? opt.IsaacSeed().c_str() : nullptr);
} }
else else
{ {
cout << "Using OpenCL to render." << endl; cout << "Using OpenCL to render.\n";
if (opt.Verbose()) if (opt.Verbose())
{ {
for (auto& device : devices) for (auto& device : devices)
{ {
cout << "Platform: " << info->PlatformName(device.first) << endl; cout << "Platform: " << info->PlatformName(device.first) << "\n";
cout << "Device: " << info->DeviceName(device.first, device.second) << endl; cout << "Device: " << info->DeviceName(device.first, device.second) << "\n";
} }
} }
if (opt.ThreadCount() > 1) if (opt.ThreadCount() > 1)
cout << "Cannot specify threads with OpenCL, using 1 thread." << endl; cout << "Cannot specify threads with OpenCL, using 1 thread.\n";
opt.ThreadCount(1); opt.ThreadCount(1);
renderer->ThreadCount(opt.ThreadCount(), opt.IsaacSeed() != "" ? opt.IsaacSeed().c_str() : nullptr); renderer->ThreadCount(opt.ThreadCount(), opt.IsaacSeed() != "" ? opt.IsaacSeed().c_str() : nullptr);
if (opt.BitsPerChannel() != 8) if (opt.BitsPerChannel() != 8)
{ {
cout << "Bits per channel cannot be anything other than 8 with OpenCL, setting to 8." << endl; cout << "Bits per channel cannot be anything other than 8 with OpenCL, setting to 8.\n";
opt.BitsPerChannel(8); opt.BitsPerChannel(8);
} }
} }
@ -113,37 +113,37 @@ bool EmberRender(EmberOptions& opt)
opt.Format() != "ppm" && opt.Format() != "ppm" &&
opt.Format() != "bmp") opt.Format() != "bmp")
{ {
cout << "Format must be jpg, png, ppm, or bmp not " << opt.Format() << ". Setting to jpg." << endl; cout << "Format must be jpg, png, ppm, or bmp not " << opt.Format() << ". Setting to jpg.\n";
} }
channels = opt.Format() == "png" ? 4 : 3; channels = opt.Format() == "png" ? 4 : 3;
if (opt.BitsPerChannel() == 16 && opt.Format() != "png") if (opt.BitsPerChannel() == 16 && opt.Format() != "png")
{ {
cout << "Support for 16 bits per channel images is only present for the png format. Setting to 8." << endl; cout << "Support for 16 bits per channel images is only present for the png format. Setting to 8.\n";
opt.BitsPerChannel(8); opt.BitsPerChannel(8);
} }
else if (opt.BitsPerChannel() != 8 && opt.BitsPerChannel() != 16) else if (opt.BitsPerChannel() != 8 && opt.BitsPerChannel() != 16)
{ {
cout << "Unexpected bits per channel specified " << opt.BitsPerChannel() << ". Setting to 8." << endl; cout << "Unexpected bits per channel specified " << opt.BitsPerChannel() << ". Setting to 8.\n";
opt.BitsPerChannel(8); opt.BitsPerChannel(8);
} }
if (opt.InsertPalette() && opt.BitsPerChannel() != 8) if (opt.InsertPalette() && opt.BitsPerChannel() != 8)
{ {
cout << "Inserting palette only supported with 8 bits per channel, insertion will not take place." << endl; cout << "Inserting palette only supported with 8 bits per channel, insertion will not take place.\n";
opt.InsertPalette(false); opt.InsertPalette(false);
} }
if (opt.AspectRatio() < 0) if (opt.AspectRatio() < 0)
{ {
cout << "Invalid pixel aspect ratio " << opt.AspectRatio() << endl << ". Must be positive, setting to 1." << endl; cout << "Invalid pixel aspect ratio " << opt.AspectRatio() << "\n. Must be positive, setting to 1.\n";
opt.AspectRatio(1); opt.AspectRatio(1);
} }
if (!opt.Out().empty() && (embers.size() > 1)) if (!opt.Out().empty() && (embers.size() > 1))
{ {
cout << "Single output file " << opt.Out() << " specified for multiple images. Changing to use prefix of badname-changethis instead. Always specify prefixes when reading a file with multiple embers." << endl; cout << "Single output file " << opt.Out() << " specified for multiple images. Changing to use prefix of badname-changethis instead. Always specify prefixes when reading a file with multiple embers.\n";
opt.Out(""); opt.Out("");
opt.Prefix("badname-changethis"); opt.Prefix("badname-changethis");
} }
@ -165,9 +165,9 @@ bool EmberRender(EmberOptions& opt)
for (i = 0; i < embers.size(); i++) for (i = 0; i < embers.size(); i++)
{ {
if (opt.Verbose() && embers.size() > 1) if (opt.Verbose() && embers.size() > 1)
cout << "\nFlame = " << i + 1 << "/" << embers.size() << endl; cout << "\nFlame = " << i + 1 << "/" << embers.size() << "\n";
else if (embers.size() > 1) else if (embers.size() > 1)
VerbosePrint(endl); VerbosePrint("\n");
if (opt.Supersample() > 0) if (opt.Supersample() > 0)
embers[i].m_Supersample = opt.Supersample(); embers[i].m_Supersample = opt.Supersample();
@ -192,7 +192,7 @@ bool EmberRender(EmberOptions& opt)
if (embers[i].m_FinalRasW == 0 || embers[i].m_FinalRasH == 0) if (embers[i].m_FinalRasW == 0 || embers[i].m_FinalRasH == 0)
{ {
cout << "Output image " << i << " has dimension 0: " << embers[i].m_FinalRasW << ", " << embers[i].m_FinalRasH << ". Setting to 1920 x 1080." << endl; cout << "Output image " << i << " has dimension 0: " << embers[i].m_FinalRasW << ", " << embers[i].m_FinalRasH << ". Setting to 1920 x 1080.\n";
embers[i].m_FinalRasW = 1920; embers[i].m_FinalRasW = 1920;
embers[i].m_FinalRasH = 1080; embers[i].m_FinalRasH = 1080;
} }
@ -204,7 +204,7 @@ bool EmberRender(EmberOptions& opt)
if (imageMem > maxMem)//Ensure the max amount of memory for a process is not exceeded. if (imageMem > maxMem)//Ensure the max amount of memory for a process is not exceeded.
{ {
cout << "Image " << i << " size > " << maxMem << ". Setting to 1920 x 1080." << endl; cout << "Image " << i << " size > " << maxMem << ". Setting to 1920 x 1080.\n";
embers[i].m_FinalRasW = 1920; embers[i].m_FinalRasW = 1920;
embers[i].m_FinalRasH = 1080; embers[i].m_FinalRasH = 1080;
} }
@ -227,9 +227,9 @@ bool EmberRender(EmberOptions& opt)
} }
strips = VerifyStrips(embers[i].m_FinalRasH, strips, strips = VerifyStrips(embers[i].m_FinalRasH, strips,
[&](const string & s) { cout << s << endl; }, //Greater than height. [&](const string & s) { cout << s << "\n"; }, //Greater than height.
[&](const string & s) { cout << s << endl; }, //Mod height != 0. [&](const string & s) { cout << s << "\n"; }, //Mod height != 0.
[&](const string & s) { cout << s << endl; }); //Final strips value to be set. [&](const string & s) { cout << s << "\n"; }); //Final strips value to be set.
//For testing incremental renderer. //For testing incremental renderer.
//int sb = 1; //int sb = 1;
//bool resume = false, success = false; //bool resume = false, success = false;
@ -244,7 +244,7 @@ bool EmberRender(EmberOptions& opt)
[&](size_t strip)//Pre strip. [&](size_t strip)//Pre strip.
{ {
if (opt.Verbose() && (strips > 1) && strip > 0) if (opt.Verbose() && (strips > 1) && strip > 0)
cout << endl; cout << "\n";
if (strips > 1) if (strips > 1)
VerbosePrint("Strip = " << (strip + 1) << "/" << strips); VerbosePrint("Strip = " << (strip + 1) << "/" << strips);
@ -256,7 +256,7 @@ bool EmberRender(EmberOptions& opt)
}, },
[&](size_t strip)//Error. [&](size_t strip)//Error.
{ {
cout << "Error: image rendering failed, skipping to next image." << endl; cout << "Error: image rendering failed, skipping to next image.\n";
renderer->DumpErrorReport();//Something went wrong, print errors. renderer->DumpErrorReport();//Something went wrong, print errors.
}, },
//Final strip. //Final strip.
@ -291,7 +291,7 @@ bool EmberRender(EmberOptions& opt)
VerbosePrint("Render time: " + t.Format(stats.m_RenderMs)); VerbosePrint("Render time: " + t.Format(stats.m_RenderMs));
VerbosePrint("Pure iter time: " + t.Format(stats.m_IterMs)); VerbosePrint("Pure iter time: " + t.Format(stats.m_IterMs));
VerbosePrint("Iters/sec: " << size_t(stats.m_Iters / (stats.m_IterMs / 1000.0)) << endl); VerbosePrint("Iters/sec: " << size_t(stats.m_Iters / (stats.m_IterMs / 1000.0)) << "\n");
VerbosePrint("Writing " + filename); VerbosePrint("Writing " + filename);
if ((opt.Format() == "jpg" || opt.Format() == "bmp") && renderer->NumChannels() == 4) if ((opt.Format() == "jpg" || opt.Format() == "bmp") && renderer->NumChannels() == 4)
@ -310,7 +310,7 @@ bool EmberRender(EmberOptions& opt)
writeSuccess = WriteBmp(filename.c_str(), finalImagep, finalEmber.m_FinalRasW, finalEmber.m_FinalRasH); writeSuccess = WriteBmp(filename.c_str(), finalImagep, finalEmber.m_FinalRasW, finalEmber.m_FinalRasH);
if (!writeSuccess) if (!writeSuccess)
cout << "Error writing " << filename << endl; cout << "Error writing " << filename << "\n";
}); });
if (opt.EmberCL() && opt.DumpKernel()) if (opt.EmberCL() && opt.DumpKernel())
@ -322,7 +322,7 @@ bool EmberRender(EmberOptions& opt)
"Density filter kernel:\n" << "Density filter kernel:\n" <<
rendererCL->DEKernel() << "\n\n" << rendererCL->DEKernel() << "\n\n" <<
"Final accumulation kernel:\n" << "Final accumulation kernel:\n" <<
rendererCL->FinalAccumKernel() << endl; rendererCL->FinalAccumKernel() << "\n";
} }
} }
@ -368,7 +368,7 @@ int _tmain(int argc, _TCHAR* argv[])
} }
else if (opt.Bits() == 32) else if (opt.Bits() == 32)
{ {
cout << "Bits 32/int histogram no longer supported. Using bits == 33 (float)." << endl; cout << "Bits 32/int histogram no longer supported. Using bits == 33 (float).\n";
b = EmberRender<float>(opt); b = EmberRender<float>(opt);
} }
} }

View File

@ -1962,6 +1962,28 @@ void DistribTester()
} }
} }
template <typename T>
void TestAffine()
{
v2T x(1, 0), y(0, 1), t(1, 0);
Affine2D<T> af(x, y, t);
auto af2 = af;
cout << af.ToString() << "\n\n";
af.RotateTrans(90);
cout << af.ToString() << "\n\n";
af2.RotateTrans(-90);
cout << af2.ToString() << "\n\n";
}
template <typename T>
void TestRotate()
{
T angle = 45;
v3T x(1, 0, 0), y(0, 1, 0), xy(1, 1, 0);
auto xtrans = glm::translate(m4T(1), xy);
auto xrot = glm::rotate(xtrans, angle * DEG_2_RAD_T, v3T(0, 0, 1));
}
#define DO_NVIDIA 1 #define DO_NVIDIA 1
int _tmain(int argc, _TCHAR* argv[]) int _tmain(int argc, _TCHAR* argv[])
@ -1971,7 +1993,12 @@ int _tmain(int argc, _TCHAR* argv[])
Timing t(4); Timing t(4);
QTIsaac<ISAAC_SIZE, ISAAC_INT> rand(1, 2, 3); QTIsaac<ISAAC_SIZE, ISAAC_INT> rand(1, 2, 3);
mt19937 meow(1729); mt19937 meow(1729);
/* MakeTestAllVarsRegPrePostComboFile("testallvarsout.flame"); /* TestAffine<float>();
TestAffine<double>();*/
/* TestRotate<float>();
TestRotate<double>();
return 1;
MakeTestAllVarsRegPrePostComboFile("testallvarsout.flame");
return 0; return 0;
@ -2175,28 +2202,28 @@ int _tmain(int argc, _TCHAR* argv[])
#endif #endif
} }
#ifdef DO_DOUBLE //#ifdef DO_DOUBLE
//
// //t.Tic();
// //TestCpuGpuResults<double>();
// //t.Toc("TestCpuGpuResults<double>()");
// if (b)
// {
// t.Tic(); // t.Tic();
//TestCpuGpuResults<double>(); // TestAllVarsCLBuild<double>(0, 0, true);
//t.Toc("TestCpuGpuResults<double>()"); // t.Toc("TestAllVarsCLBuild<double>()");
if (b) //
{ // if (b)
t.Tic(); // {
TestAllVarsCLBuild<double>(0, 0, true); //#ifdef DO_NVIDIA
t.Toc("TestAllVarsCLBuild<double>()"); // t.Tic();
// TestAllVarsCLBuild<double>(1, 0, true);
if (b) // t.Toc("TestAllVarsCLBuild<double>()");
{ //#endif
#ifdef DO_NVIDIA // }
t.Tic(); // }
TestAllVarsCLBuild<double>(1, 0, true); //
t.Toc("TestAllVarsCLBuild<double>()"); //#endif
#endif
}
}
#endif
#endif #endif
//PrintAllVars(); //PrintAllVars();
//_CrtDumpMemoryLeaks(); //_CrtDumpMemoryLeaks();

View File

@ -1,7 +1,7 @@
#include "FractoriumPch.h" #include "FractoriumPch.h"
#include "DoubleSpinBox.h" #include "DoubleSpinBox.h"
QTimer DoubleSpinBox::m_Timer; QTimer DoubleSpinBox::s_Timer;
/// <summary> /// <summary>
/// Constructor that passes parent to the base and sets up height and step. /// Constructor that passes parent to the base and sets up height and step.
@ -154,7 +154,6 @@ void DoubleSpinBox::OnTimeout()
val = d + (distance * amount * scale); val = d + (distance * amount * scale);
setValue(val); setValue(val);
//qDebug() << "Timer on, orig val: " << d << ", new val: " << val << ", distance " << distance; //qDebug() << "Timer on, orig val: " << d << ", new val: " << val << ", distance " << distance;
} }
@ -299,9 +298,9 @@ void DoubleSpinBox::leaveEvent(QEvent* e)
/// </summary> /// </summary>
void DoubleSpinBox::StartTimer() void DoubleSpinBox::StartTimer()
{ {
m_Timer.stop(); s_Timer.stop();
connect(&m_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout())); connect(&s_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout()));
m_Timer.start(300); s_Timer.start(300);
} }
/// <summary> /// <summary>
@ -309,6 +308,6 @@ void DoubleSpinBox::StartTimer()
/// </summary> /// </summary>
void DoubleSpinBox::StopTimer() void DoubleSpinBox::StopTimer()
{ {
m_Timer.stop(); s_Timer.stop();
disconnect(&m_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout())); disconnect(&s_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout()));
} }

View File

@ -51,7 +51,7 @@ private:
double m_SmallStep; double m_SmallStep;
QPoint m_MouseDownPoint; QPoint m_MouseDownPoint;
QPoint m_MouseMovePoint; QPoint m_MouseMovePoint;
static QTimer m_Timer; static QTimer s_Timer;
}; };
/// <summary> /// <summary>

View File

@ -15,7 +15,6 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(FractoriumSettings* set
{ {
ui.setupUi(this); ui.setupUi(this);
int row = 0, spinHeight = 20; int row = 0, spinHeight = 20;
uint i;
double dmax = numeric_limits<double>::max(); double dmax = numeric_limits<double>::max();
QTableWidget* table = ui.FinalRenderParamsTable; QTableWidget* table = ui.FinalRenderParamsTable;
QTableWidgetItem* item = nullptr; QTableWidgetItem* item = nullptr;

View File

@ -110,7 +110,7 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
m_FinalPreviewRenderer->NumChannels(4); m_FinalPreviewRenderer->NumChannels(4);
m_FinalPreviewRenderFunc = [&]() m_FinalPreviewRenderFunc = [&]()
{ {
m_PreviewCs.Enter();//Thread prep. rlg l(m_PreviewCs);//Thread prep.
m_PreviewRun = true; m_PreviewRun = true;
m_FinalPreviewRenderer->Abort(); m_FinalPreviewRenderer->Abort();
T scalePercentage; T scalePercentage;
@ -144,11 +144,10 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
{ {
QImage image(finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, QImage::Format_RGBA8888);//The label wants RGBA. QImage image(finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, QImage::Format_RGBA8888);//The label wants RGBA.
memcpy(image.scanLine(0), m_PreviewFinalImage.data(), finalEmber.m_FinalRasW * finalEmber.m_FinalRasH * 4);//Memcpy the data in. memcpy(image.scanLine(0), m_PreviewFinalImage.data(), finalEmber.m_FinalRasW * finalEmber.m_FinalRasH * 4);//Memcpy the data in.
QPixmap pixmap = QPixmap::fromImage(image); QPixmap pixmap(QPixmap::fromImage(image));
QMetaObject::invokeMethod(widget, "setPixmap", Qt::QueuedConnection, Q_ARG(QPixmap, pixmap)); QMetaObject::invokeMethod(widget, "setPixmap", Qt::QueuedConnection, Q_ARG(QPixmap, pixmap));
}); });
m_PreviewRun = false; m_PreviewRun = false;
m_PreviewCs.Leave();
}; };
//The main rendering function which will be called in a Qt thread. //The main rendering function which will be called in a Qt thread.
//A backup Xml is made before the rendering process starts just in case it crashes before finishing. //A backup Xml is made before the rendering process starts just in case it crashes before finishing.
@ -837,7 +836,7 @@ void FinalRenderEmberController<T>::HandleFinishedProgress()
template<typename T> template<typename T>
void FinalRenderEmberController<T>::RenderComplete(Ember<T>& ember, const EmberStats& stats, Timing& renderTimer) void FinalRenderEmberController<T>::RenderComplete(Ember<T>& ember, const EmberStats& stats, Timing& renderTimer)
{ {
m_ProgressCs.Enter(); rlg l(m_ProgressCs);
string renderTimeString = renderTimer.Format(renderTimer.Toc()), totalTimeString; string renderTimeString = renderTimer.Format(renderTimer.Toc()), totalTimeString;
QString status, filename = ComposePath(QString::fromStdString(ember.m_Name)); QString status, filename = ComposePath(QString::fromStdString(ember.m_Name));
QString itersString = ToString<qulonglong>(stats.m_Iters); QString itersString = ToString<qulonglong>(stats.m_Iters);
@ -885,7 +884,6 @@ void FinalRenderEmberController<T>::RenderComplete(Ember<T>& ember, const EmberS
} }
QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderTextOutput, "update", Qt::QueuedConnection); QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderTextOutput, "update", Qt::QueuedConnection);
m_ProgressCs.Leave();
} }
/// <summary> /// <summary>

View File

@ -86,7 +86,7 @@ protected:
FractoriumSettings* m_Settings; FractoriumSettings* m_Settings;
FractoriumFinalRenderDialog* m_FinalRenderDialog; FractoriumFinalRenderDialog* m_FinalRenderDialog;
FinalRenderGuiState m_GuiState; FinalRenderGuiState m_GuiState;
CriticalSection m_PreviewCs, m_ProgressCs; std::recursive_mutex m_PreviewCs, m_ProgressCs;
Timing m_RenderTimer; Timing m_RenderTimer;
Timing m_TotalTimer; Timing m_TotalTimer;
}; };

View File

@ -2780,7 +2780,7 @@
<enum>QTabWidget::Triangular</enum> <enum>QTabWidget::Triangular</enum>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>1</number> <number>2</number>
</property> </property>
<widget class="QWidget" name="XformColorTab"> <widget class="QWidget" name="XformColorTab">
<property name="sizePolicy"> <property name="sizePolicy">
@ -3470,8 +3470,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>263</width> <width>118</width>
<height>700</height> <height>618</height>
</rect> </rect>
</property> </property>
<property name="autoFillBackground"> <property name="autoFillBackground">
@ -5485,8 +5485,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>259</width> <width>133</width>
<height>652</height> <height>52</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -6768,6 +6768,9 @@
<property name="toolTip"> <property name="toolTip">
<string>Clear any existing flames and create a new file with 10 random flames in it</string> <string>Clear any existing flames and create a new file with 10 random flames in it</string>
</property> </property>
<property name="shortcut">
<string>Ctrl+N</string>
</property>
</action> </action>
<action name="ActionOpen"> <action name="ActionOpen">
<property name="icon"> <property name="icon">
@ -6777,6 +6780,9 @@
<property name="text"> <property name="text">
<string>&amp;Open</string> <string>&amp;Open</string>
</property> </property>
<property name="shortcut">
<string>Ctrl+O</string>
</property>
</action> </action>
<action name="ActionExit"> <action name="ActionExit">
<property name="icon"> <property name="icon">
@ -6798,6 +6804,9 @@
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;body&gt;&lt;p&gt;Save the currently displayed flame back to the opened file in memory.&lt;/p&gt;&lt;p&gt;This overwrites the original flame but does not store the file back to disk.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;body&gt;&lt;p&gt;Save the currently displayed flame back to the opened file in memory.&lt;/p&gt;&lt;p&gt;This overwrites the original flame but does not store the file back to disk.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="shortcut">
<string>Ctrl+B</string>
</property>
</action> </action>
<action name="ActionSaveCurrentAsXml"> <action name="ActionSaveCurrentAsXml">
<property name="icon"> <property name="icon">
@ -6810,6 +6819,9 @@
<property name="toolTip"> <property name="toolTip">
<string>Save the current flame as an xml file</string> <string>Save the current flame as an xml file</string>
</property> </property>
<property name="shortcut">
<string>Ctrl+S</string>
</property>
</action> </action>
<action name="ActionAbout"> <action name="ActionAbout">
<property name="icon"> <property name="icon">
@ -6861,6 +6873,9 @@
<property name="toolTip"> <property name="toolTip">
<string>Add a new random flame to the end of the current file</string> <string>Add a new random flame to the end of the current file</string>
</property> </property>
<property name="shortcut">
<string>Ctrl+R</string>
</property>
</action> </action>
<action name="ActionSaveEntireFileAsXml"> <action name="ActionSaveEntireFileAsXml">
<property name="icon"> <property name="icon">
@ -6876,6 +6891,9 @@
<property name="toolTip"> <property name="toolTip">
<string>Save all flames as a single xml file</string> <string>Save all flames as a single xml file</string>
</property> </property>
<property name="shortcut">
<string>Ctrl+Shift+S</string>
</property>
</action> </action>
<action name="ActionAddReflectiveSymmetry"> <action name="ActionAddReflectiveSymmetry">
<property name="icon"> <property name="icon">
@ -6920,6 +6938,9 @@
<property name="toolTip"> <property name="toolTip">
<string>Add a new empty flame to the end of the current file</string> <string>Add a new empty flame to the end of the current file</string>
</property> </property>
<property name="shortcut">
<string>Ctrl+E</string>
</property>
</action> </action>
<action name="ActionCopyFlameInCurrentFile"> <action name="ActionCopyFlameInCurrentFile">
<property name="icon"> <property name="icon">
@ -6927,7 +6948,7 @@
<normaloff>:/Fractorium/Icons/layers.png</normaloff>:/Fractorium/Icons/layers.png</iconset> <normaloff>:/Fractorium/Icons/layers.png</normaloff>:/Fractorium/Icons/layers.png</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>Co&amp;py Flame</string> <string>Add Co&amp;py of Flame</string>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Add a copy of the current flame to the end of the current file</string> <string>Add a copy of the current flame to the end of the current file</string>
@ -7069,11 +7090,6 @@
<string>Remove the flatten variation from each xform</string> <string>Remove the flatten variation from each xform</string>
</property> </property>
</action> </action>
<action name="ActionFlip">
<property name="text">
<string>Fl&amp;ip</string>
</property>
</action>
<action name="ActionCopySelectedXforms"> <action name="ActionCopySelectedXforms">
<property name="text"> <property name="text">
<string>Copy Selected &amp;Xforms</string> <string>Copy Selected &amp;Xforms</string>
@ -7082,7 +7098,7 @@
<string>Copy selected xforms to the clipboard</string> <string>Copy selected xforms to the clipboard</string>
</property> </property>
<property name="shortcut"> <property name="shortcut">
<string>Ctrl+D</string> <string>Ctrl+C, X</string>
</property> </property>
</action> </action>
<action name="ActionPasteSelectedXforms"> <action name="ActionPasteSelectedXforms">
@ -7093,7 +7109,7 @@
<string>Paste copied xforms into the current flame</string> <string>Paste copied xforms into the current flame</string>
</property> </property>
<property name="shortcut"> <property name="shortcut">
<string>Ctrl+S</string> <string>Ctrl+V, X</string>
</property> </property>
</action> </action>
<action name="ActionResetWorkspace"> <action name="ActionResetWorkspace">
@ -7192,7 +7208,7 @@
<string>Stop Renderer</string> <string>Stop Renderer</string>
</property> </property>
<property name="shortcut"> <property name="shortcut">
<string>Ctrl+R</string> <string>Ctrl+P</string>
</property> </property>
</action> </action>
</widget> </widget>

View File

@ -20,15 +20,13 @@ FractoriumEmberControllerBase::FractoriumEmberControllerBase(Fractorium* fractor
m_OutputTexID = 0; m_OutputTexID = 0;
m_SubBatchCount = 1;//Will be ovewritten by the options on first render. m_SubBatchCount = 1;//Will be ovewritten by the options on first render.
m_Fractorium = fractorium; m_Fractorium = fractorium;
m_RenderTimer = nullptr;
m_RenderRestartTimer = nullptr;
m_Info = OpenCLInfo::Instance(); m_Info = OpenCLInfo::Instance();
m_Rand = QTIsaac<ISAAC_SIZE, ISAAC_INT>(ISAAC_INT(t.Tic()), ISAAC_INT(t.Tic() * 2), ISAAC_INT(t.Tic() * 3));//Ensure a different rand seed on each instance. m_Rand = QTIsaac<ISAAC_SIZE, ISAAC_INT>(ISAAC_INT(t.Tic()), ISAAC_INT(t.Tic() * 2), ISAAC_INT(t.Tic() * 3));//Ensure a different rand seed on each instance.
m_RenderTimer = new QTimer(m_Fractorium); m_RenderTimer = std::unique_ptr<QTimer>(new QTimer(m_Fractorium));
m_RenderTimer->setInterval(0); m_RenderTimer->setInterval(0);
m_Fractorium->connect(m_RenderTimer, SIGNAL(timeout()), SLOT(IdleTimer())); m_Fractorium->connect(m_RenderTimer.get(), SIGNAL(timeout()), SLOT(IdleTimer()));
m_RenderRestartTimer = new QTimer(m_Fractorium); m_RenderRestartTimer = std::unique_ptr<QTimer>(new QTimer(m_Fractorium));
m_Fractorium->connect(m_RenderRestartTimer, SIGNAL(timeout()), SLOT(StartRenderTimer())); m_Fractorium->connect(m_RenderRestartTimer.get(), SIGNAL(timeout()), SLOT(StartRenderTimer()));
} }
/// <summary> /// <summary>
@ -38,20 +36,8 @@ FractoriumEmberControllerBase::FractoriumEmberControllerBase(Fractorium* fractor
FractoriumEmberControllerBase::~FractoriumEmberControllerBase() FractoriumEmberControllerBase::~FractoriumEmberControllerBase()
{ {
StopRenderTimer(true); StopRenderTimer(true);
if (m_RenderTimer)
{
m_RenderTimer->stop(); m_RenderTimer->stop();
delete m_RenderTimer;
m_RenderTimer = nullptr;
}
if (m_RenderRestartTimer)
{
m_RenderRestartTimer->stop(); m_RenderRestartTimer->stop();
delete m_RenderRestartTimer;
m_RenderRestartTimer = nullptr;
}
} }
/// <summary> /// <summary>
@ -64,25 +50,34 @@ template <typename T>
FractoriumEmberController<T>::FractoriumEmberController(Fractorium* fractorium) FractoriumEmberController<T>::FractoriumEmberController(Fractorium* fractorium)
: FractoriumEmberControllerBase(fractorium) : FractoriumEmberControllerBase(fractorium)
{ {
bool b = false;
m_PreviewRun = false; m_PreviewRun = false;
m_PreviewRunning = false; m_PreviewRunning = false;
m_SheepTools = unique_ptr<SheepTools<T, float>>(new SheepTools<T, float>(
QString(QApplication::applicationDirPath() + "flam3-palettes.xml").toLocal8Bit().data(),
new EmberNs::Renderer<T, float>()));
m_GLController = unique_ptr<GLEmberController<T>>(new GLEmberController<T>(fractorium, fractorium->ui.GLDisplay, this)); m_GLController = unique_ptr<GLEmberController<T>>(new GLEmberController<T>(fractorium, fractorium->ui.GLDisplay, this));
m_PreviewRenderer = unique_ptr<EmberNs::Renderer<T, float>>(new EmberNs::Renderer<T, float>()); m_PreviewRenderer = unique_ptr<EmberNs::Renderer<T, float>>(new EmberNs::Renderer<T, float>());
//Initial combo change event to fill the palette table will be called automatically later. //Initial combo change event to fill the palette table will be called automatically later.
//Look hard for a palette. //Look hard for a palette.
if (!(InitPaletteList(QDir::currentPath().toLocal8Bit().data()) || static vector<string> paths =
InitPaletteList(QDir::homePath().toLocal8Bit().data()) ||
InitPaletteList(QCoreApplication::applicationDirPath().toLocal8Bit().data()) ||
InitPaletteList(QString("/usr/local/share/fractorium").toLocal8Bit().data()) ||
InitPaletteList(QString("/usr/share/fractorium").toLocal8Bit().data())) )
{ {
throw "No palettes found, exiting."; QDir::currentPath().toLocal8Bit().data(),
QDir::homePath().toLocal8Bit().data(),
QCoreApplication::applicationDirPath().toLocal8Bit().data(),
QString("/usr/local/share/fractorium").toLocal8Bit().data(),
QString("/usr/share/fractorium").toLocal8Bit().data()
};
for (auto& path : paths)
{
if (b = InitPaletteList(path))
{
m_SheepTools = unique_ptr<SheepTools<T, float>>(new SheepTools<T, float>(
m_PaletteList.Name(0), new EmberNs::Renderer<T, float>()));
break;
} }
}
if (!b)
throw "No palettes found, exiting.";
BackgroundChanged(QColor(0, 0, 0));//Default to black. BackgroundChanged(QColor(0, 0, 0));//Default to black.
ClearUndo(); ClearUndo();
@ -101,9 +96,9 @@ FractoriumEmberController<T>::FractoriumEmberController(Fractorium* fractorium)
m_PreviewRun = true; m_PreviewRun = true;
m_PreviewRunning = true; m_PreviewRunning = true;
m_PreviewRenderer->ThreadCount(std::max(1u, Timing::ProcessorCount() - 1));//Leave one processor free so the GUI can breathe. m_PreviewRenderer->ThreadCount(std::max(1u, Timing::ProcessorCount() - 1));//Leave one processor free so the GUI can breathe.
QTreeWidget* tree = m_Fractorium->ui.LibraryTree; auto tree = m_Fractorium->ui.LibraryTree;
if (QTreeWidgetItem* top = tree->topLevelItem(0)) if (auto top = tree->topLevelItem(0))
{ {
for (size_t i = start; m_PreviewRun && i < end && i < m_EmberFile.Size(); i++) for (size_t i = start; m_PreviewRun && i < end && i < m_EmberFile.Size(); i++)
{ {
@ -117,7 +112,7 @@ FractoriumEmberController<T>::FractoriumEmberController(Fractorium* fractorium)
if (m_PreviewRenderer->Run(m_PreviewFinalImage) == eRenderStatus::RENDER_OK) if (m_PreviewRenderer->Run(m_PreviewFinalImage) == eRenderStatus::RENDER_OK)
{ {
if (EmberTreeWidgetItem<T>* treeItem = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(i))) if (auto treeItem = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(i)))
{ {
//It is critical that Qt::BlockingQueuedConnection is passed because this is running on a different thread than the UI. //It is critical that Qt::BlockingQueuedConnection is passed because this is running on a different thread than the UI.
//This ensures the events are processed in order as each preview is updated, and that control does not return here //This ensures the events are processed in order as each preview is updated, and that control does not return here
@ -193,11 +188,11 @@ void FractoriumEmberController<T>::SetEmber(size_t index)
{ {
if (index < m_EmberFile.Size()) if (index < m_EmberFile.Size())
{ {
if (QTreeWidgetItem* top = m_Fractorium->ui.LibraryTree->topLevelItem(0)) if (auto top = m_Fractorium->ui.LibraryTree->topLevelItem(0))
{ {
for (uint i = 0; i < top->childCount(); i++) for (uint i = 0; i < top->childCount(); i++)
{ {
if (EmberTreeWidgetItem<T>* emberItem = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(i))) if (auto emberItem = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(i)))
emberItem->setSelected(i == index); emberItem->setSelected(i == index);
} }
} }

View File

@ -194,7 +194,6 @@ public:
//Xaos. //Xaos.
virtual void FillXaos() { } virtual void FillXaos() { }
virtual QString MakeXaosNameString(uint i) { return ""; }
virtual void XaosChanged(int x, int y, double val) { } virtual void XaosChanged(int x, int y, double val) { }
virtual void ClearXaos() { } virtual void ClearXaos() { }
virtual void RandomXaos() { } virtual void RandomXaos() { }
@ -254,7 +253,7 @@ protected:
QString m_LastSaveAll; QString m_LastSaveAll;
QString m_LastSaveCurrent; QString m_LastSaveCurrent;
string m_CurrentPaletteFilePath; string m_CurrentPaletteFilePath;
CriticalSection m_Cs; std::recursive_mutex m_Cs;
std::thread m_WriteThread; std::thread m_WriteThread;
vector<byte> m_FinalImage; vector<byte> m_FinalImage;
vector<byte> m_PreviewFinalImage; vector<byte> m_PreviewFinalImage;
@ -263,8 +262,8 @@ protected:
unique_ptr<EmberNs::RendererBase> m_Renderer; unique_ptr<EmberNs::RendererBase> m_Renderer;
QTIsaac<ISAAC_SIZE, ISAAC_INT> m_Rand; QTIsaac<ISAAC_SIZE, ISAAC_INT> m_Rand;
Fractorium* m_Fractorium; Fractorium* m_Fractorium;
QTimer* m_RenderTimer; std::unique_ptr<QTimer> m_RenderTimer;
QTimer* m_RenderRestartTimer; std::unique_ptr<QTimer> m_RenderRestartTimer;
shared_ptr<OpenCLInfo> m_Info; shared_ptr<OpenCLInfo> m_Info;
}; };
@ -439,7 +438,6 @@ public:
//Xforms Xaos. //Xforms Xaos.
virtual void FillXaos() override; virtual void FillXaos() override;
virtual QString MakeXaosNameString(uint i) override;
virtual void XaosChanged(int x, int y, double val) override; virtual void XaosChanged(int x, int y, double val) override;
virtual void ClearXaos() override; virtual void ClearXaos() override;
virtual void RandomXaos() override; virtual void RandomXaos() override;
@ -475,7 +473,6 @@ private:
bool IsFinal(Xform<T>* xform); bool IsFinal(Xform<T>* xform);
//Xforms Color. //Xforms Color.
void SetCurrentXformColorIndex(double d, bool updateRender);
void FillCurvesControl(); void FillCurvesControl();
//Xforms Selection. //Xforms Selection.

View File

@ -32,7 +32,7 @@ void Fractorium::InitInfoUI()
/// <param name="newSize">Ignored</param> /// <param name="newSize">Ignored</param>
void Fractorium::OnSummaryTableHeaderResized(int logicalIndex, int oldSize, int newSize) void Fractorium::OnSummaryTableHeaderResized(int logicalIndex, int oldSize, int newSize)
{ {
QPixmap pixmap = QPixmap::fromImage(m_Controller->FinalPaletteImage());//Create a QPixmap out of the QImage, will be empty on startup. QPixmap pixmap(QPixmap::fromImage(m_Controller->FinalPaletteImage()));//Create a QPixmap out of the QImage, will be empty on startup.
SetPaletteTableItem(&pixmap, ui.SummaryTable, m_InfoPaletteItem, 1, 0); SetPaletteTableItem(&pixmap, ui.SummaryTable, m_InfoPaletteItem, 1, 0);
} }
@ -57,7 +57,7 @@ void Fractorium::OnSummaryTreeHeaderSectionClicked(int logicalIndex)
/// values from the ember. /// values from the ember.
/// It's also meant to be used in a fire-and-forget way. Once the tree is filled /// It's also meant to be used in a fire-and-forget way. Once the tree is filled
/// individual nodes are never referenced again. /// individual nodes are never referenced again.
/// The entire tree is cleared and refilled for every field change. /// The entire tree is cleared and refilled whenever a render is completed.
/// This would seem inefficient, but it appears to update with no flicker. /// This would seem inefficient, but it appears to update with no flicker.
/// If this ever presents a problem in the future, revisit with a more /// If this ever presents a problem in the future, revisit with a more
/// intelligent design. /// intelligent design.
@ -74,17 +74,6 @@ void FractoriumEmberController<T>::FillSummary()
QColor color; QColor color;
auto table = m_Fractorium->ui.SummaryTable; auto table = m_Fractorium->ui.SummaryTable;
auto tree = m_Fractorium->ui.SummaryTree; auto tree = m_Fractorium->ui.SummaryTree;
QVariantList states;
QTreeWidgetItemIterator it(tree);
while (*it)
{
if (!(*it)->parent())//Top level only.
states += (*it)->isExpanded();
++it;
}
tree->blockSignals(true); tree->blockSignals(true);
tree->clear(); tree->clear();
m_Fractorium->m_InfoNameItem->setText(m_Ember.m_Name.c_str()); m_Fractorium->m_InfoNameItem->setText(m_Ember.m_Name.c_str());
@ -92,7 +81,7 @@ void FractoriumEmberController<T>::FillSummary()
m_Fractorium->m_InfoXaosItem->setText(m_Ember.XaosPresent() ? "Yes" : "No"); m_Fractorium->m_InfoXaosItem->setText(m_Ember.XaosPresent() ? "Yes" : "No");
m_Fractorium->m_InfoXformCountItem->setText(QString::number(m_Ember.XformCount())); m_Fractorium->m_InfoXformCountItem->setText(QString::number(m_Ember.XformCount()));
m_Fractorium->m_InfoFinalXformItem->setText(m_Ember.UseFinalXform() ? "Yes" : "No"); m_Fractorium->m_InfoFinalXformItem->setText(m_Ember.UseFinalXform() ? "Yes" : "No");
QPixmap pixmap = QPixmap::fromImage(m_FinalPaletteImage);//Create a QPixmap out of the QImage. QPixmap pixmap(QPixmap::fromImage(m_FinalPaletteImage));//Create a QPixmap out of the QImage.
QSize size(table->columnWidth(0), table->rowHeight(1) + 1); QSize size(table->columnWidth(0), table->rowHeight(1) + 1);
m_Fractorium->m_InfoPaletteItem->setData(Qt::DecorationRole, pixmap.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); m_Fractorium->m_InfoPaletteItem->setData(Qt::DecorationRole, pixmap.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
@ -178,26 +167,7 @@ void FractoriumEmberController<T>::FillSummary()
auto item2 = new QTreeWidgetItem(tree);//Empty item in between xforms. auto item2 = new QTreeWidgetItem(tree);//Empty item in between xforms.
} }
QTreeWidgetItemIterator it2(tree);
if (!states.isEmpty())
{
while (*it2)
{
if (!(*it2)->parent())//Top level only.
{
if (!states.isEmpty())
(*it2)->setExpanded(states.takeFirst().toBool());
else
(*it2)->setExpanded(true);//Expand any remainder when going from lesser to greater number of xforms.
}
++it2;
}
}
else
tree->expandAll(); tree->expandAll();
tree->blockSignals(false); tree->blockSignals(false);
} }

View File

@ -20,9 +20,9 @@ pair<size_t, QTreeWidgetItem*> Fractorium::GetCurrentEmberIndex()
{ {
size_t index = 0; size_t index = 0;
QTreeWidgetItem* item = nullptr; QTreeWidgetItem* item = nullptr;
QTreeWidget* tree = ui.LibraryTree; auto tree = ui.LibraryTree;
if (QTreeWidgetItem* top = tree->topLevelItem(0)) if (auto top = tree->topLevelItem(0))
{ {
for (int i = 0; i < top->childCount(); i++)//Iterate through all of the children, which will represent the open embers. for (int i = 0; i < top->childCount(); i++)//Iterate through all of the children, which will represent the open embers.
{ {
@ -35,7 +35,7 @@ pair<size_t, QTreeWidgetItem*> Fractorium::GetCurrentEmberIndex()
} }
} }
return pair<size_t, QTreeWidgetItem*>(index, item); return make_pair(index, item);
} }
/// <summary> /// <summary>
@ -57,11 +57,10 @@ template <typename T>
void FractoriumEmberController<T>::SyncNames() void FractoriumEmberController<T>::SyncNames()
{ {
EmberTreeWidgetItem<T>* item; EmberTreeWidgetItem<T>* item;
QTreeWidget* tree = m_Fractorium->ui.LibraryTree; auto tree = m_Fractorium->ui.LibraryTree;
tree->blockSignals(true); tree->blockSignals(true);
if (QTreeWidgetItem* top = tree->topLevelItem(0)) if (auto top = tree->topLevelItem(0))
{ {
for (int i = 0; i < top->childCount(); i++)//Iterate through all of the children, which will represent the open embers. for (int i = 0; i < top->childCount(); i++)//Iterate through all of the children, which will represent the open embers.
{ {
@ -80,11 +79,10 @@ template <typename T>
void FractoriumEmberController<T>::SyncPointers() void FractoriumEmberController<T>::SyncPointers()
{ {
EmberTreeWidgetItem<T>* item; EmberTreeWidgetItem<T>* item;
QTreeWidget* tree = m_Fractorium->ui.LibraryTree; auto tree = m_Fractorium->ui.LibraryTree;
tree->blockSignals(true); tree->blockSignals(true);
if (QTreeWidgetItem* top = tree->topLevelItem(0)) if (auto top = tree->topLevelItem(0))
{ {
size_t childCount = top->childCount(); size_t childCount = top->childCount();
@ -107,28 +105,23 @@ void FractoriumEmberController<T>::SyncPointers()
template <typename T> template <typename T>
void FractoriumEmberController<T>::FillLibraryTree(int selectIndex) void FractoriumEmberController<T>::FillLibraryTree(int selectIndex)
{ {
uint i, j, size = 64; uint j, size = 64;
QTreeWidget* tree = m_Fractorium->ui.LibraryTree; auto tree = m_Fractorium->ui.LibraryTree;
vector<byte> v(size * size * 4); vector<byte> v(size * size * 4);
StopPreviewRender(); StopPreviewRender();
tree->clear(); tree->clear();
QCoreApplication::flush(); QCoreApplication::flush();
tree->blockSignals(true); tree->blockSignals(true);
auto fileItem = new QTreeWidgetItem(tree);
QTreeWidgetItem* fileItem = new QTreeWidgetItem(tree);
QFileInfo info(m_EmberFile.m_Filename); QFileInfo info(m_EmberFile.m_Filename);
fileItem->setText(0, info.fileName()); fileItem->setText(0, info.fileName());
fileItem->setToolTip(0, m_EmberFile.m_Filename); fileItem->setToolTip(0, m_EmberFile.m_Filename);
fileItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable); fileItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable);
for (j = 0; j < m_EmberFile.Size(); j++) for (j = 0; j < m_EmberFile.Size(); j++)
{ {
Ember<T>* ember = &m_EmberFile.m_Embers[j]; auto ember = &m_EmberFile.m_Embers[j];
EmberTreeWidgetItem<T>* emberItem = new EmberTreeWidgetItem<T>(ember, fileItem); auto emberItem = new EmberTreeWidgetItem<T>(ember, fileItem);
emberItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable); emberItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable);
if (ember->m_Name.empty()) if (ember->m_Name.empty())
@ -143,8 +136,8 @@ void FractoriumEmberController<T>::FillLibraryTree(int selectIndex)
tree->blockSignals(false); tree->blockSignals(false);
if (selectIndex != -1) if (selectIndex != -1)
if (QTreeWidgetItem* top = tree->topLevelItem(0)) if (auto top = tree->topLevelItem(0))
if (EmberTreeWidgetItem<T>* emberItem = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(selectIndex))) if (auto emberItem = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(selectIndex)))
emberItem->setSelected(true); emberItem->setSelected(true);
QCoreApplication::flush(); QCoreApplication::flush();
@ -160,20 +153,18 @@ template <typename T>
void FractoriumEmberController<T>::UpdateLibraryTree() void FractoriumEmberController<T>::UpdateLibraryTree()
{ {
uint i, size = 64; uint i, size = 64;
QTreeWidget* tree = m_Fractorium->ui.LibraryTree; auto tree = m_Fractorium->ui.LibraryTree;
vector<byte> v(size * size * 4); vector<byte> v(size * size * 4);
if (QTreeWidgetItem* top = tree->topLevelItem(0)) if (auto top = tree->topLevelItem(0))
{ {
int childCount = top->childCount(); int childCount = top->childCount();
tree->blockSignals(true); tree->blockSignals(true);
for (i = childCount; i < m_EmberFile.Size(); i++) for (i = childCount; i < m_EmberFile.Size(); i++)
{ {
Ember<T>* ember = &m_EmberFile.m_Embers[i]; Ember<T>* ember = &m_EmberFile.m_Embers[i];
EmberTreeWidgetItem<T>* emberItem = new EmberTreeWidgetItem<T>(ember, top); auto emberItem = new EmberTreeWidgetItem<T>(ember, top);
emberItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable); emberItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable);
if (ember->m_Name.empty()) if (ember->m_Name.empty())
@ -208,8 +199,8 @@ void FractoriumEmberController<T>::EmberTreeItemChanged(QTreeWidgetItem* item, i
{ {
try try
{ {
QTreeWidget* tree = m_Fractorium->ui.LibraryTree; auto tree = m_Fractorium->ui.LibraryTree;
EmberTreeWidgetItem<T>* emberItem = dynamic_cast<EmberTreeWidgetItem<T>*>(item); auto emberItem = dynamic_cast<EmberTreeWidgetItem<T>*>(item);
if (emberItem) if (emberItem)
{ {
@ -220,7 +211,6 @@ void FractoriumEmberController<T>::EmberTreeItemChanged(QTreeWidgetItem* item, i
} }
string oldName = emberItem->GetEmber()->m_Name;//First preserve the previous name. string oldName = emberItem->GetEmber()->m_Name;//First preserve the previous name.
tree->blockSignals(true); tree->blockSignals(true);
emberItem->UpdateEmberName();//Copy edit text to the ember's name variable. emberItem->UpdateEmberName();//Copy edit text to the ember's name variable.
m_EmberFile.MakeNamesUnique();//Ensure all names remain unique. m_EmberFile.MakeNamesUnique();//Ensure all names remain unique.
@ -267,7 +257,7 @@ void Fractorium::OnEmberTreeItemChanged(QTreeWidgetItem* item, int col) { m_Cont
template <typename T> template <typename T>
void FractoriumEmberController<T>::EmberTreeItemDoubleClicked(QTreeWidgetItem* item, int col) void FractoriumEmberController<T>::EmberTreeItemDoubleClicked(QTreeWidgetItem* item, int col)
{ {
if (EmberTreeWidgetItem<T>* emberItem = dynamic_cast<EmberTreeWidgetItem<T>*>(item)) if (auto emberItem = dynamic_cast<EmberTreeWidgetItem<T>*>(item))
{ {
ClearUndo(); ClearUndo();
SetEmber(*emberItem->GetEmber()); SetEmber(*emberItem->GetEmber());
@ -285,8 +275,7 @@ void Fractorium::OnEmberTreeItemDoubleClicked(QTreeWidgetItem* item, int col) {
template <typename T> template <typename T>
void FractoriumEmberController<T>::Delete(const pair<size_t, QTreeWidgetItem*>& p) void FractoriumEmberController<T>::Delete(const pair<size_t, QTreeWidgetItem*>& p)
{ {
QTreeWidget* tree = m_Fractorium->ui.LibraryTree; auto tree = m_Fractorium->ui.LibraryTree;
tree->blockSignals(true); tree->blockSignals(true);
if (m_EmberFile.Delete(p.first)) if (m_EmberFile.Delete(p.first))
@ -298,7 +287,7 @@ void FractoriumEmberController<T>::Delete(const pair<size_t, QTreeWidgetItem*>&
tree->blockSignals(false); tree->blockSignals(false);
//If there is now only one item left and it wasn't selected, select it. //If there is now only one item left and it wasn't selected, select it.
if (QTreeWidgetItem* top = tree->topLevelItem(0)) if (auto top = tree->topLevelItem(0))
{ {
if (top->childCount() == 1) if (top->childCount() == 1)
if (auto item = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(0))) if (auto item = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(0)))
@ -331,17 +320,16 @@ void FractoriumEmberController<T>::RenderPreviews(uint start, uint end)
if (start == UINT_MAX && end == UINT_MAX) if (start == UINT_MAX && end == UINT_MAX)
{ {
QTreeWidget* tree = m_Fractorium->ui.LibraryTree; auto tree = m_Fractorium->ui.LibraryTree;
tree->blockSignals(true); tree->blockSignals(true);
if (QTreeWidgetItem* top = tree->topLevelItem(0)) if (auto top = tree->topLevelItem(0))
{ {
int childCount = top->childCount(); int childCount = top->childCount();
vector<byte> emptyPreview(PREVIEW_SIZE * PREVIEW_SIZE * 3); vector<byte> emptyPreview(PREVIEW_SIZE * PREVIEW_SIZE * 3);
for (int i = 0; i < childCount; i++) for (int i = 0; i < childCount; i++)
if (EmberTreeWidgetItem<T>* treeItem = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(i))) if (auto treeItem = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(i)))
treeItem->SetImage(emptyPreview, PREVIEW_SIZE, PREVIEW_SIZE); treeItem->SetImage(emptyPreview, PREVIEW_SIZE, PREVIEW_SIZE);
} }
@ -359,6 +347,7 @@ template <typename T>
void FractoriumEmberController<T>::StopPreviewRender() void FractoriumEmberController<T>::StopPreviewRender()
{ {
m_PreviewRun = false; m_PreviewRun = false;
m_PreviewRenderer->Abort();
while (m_PreviewRunning) while (m_PreviewRunning)
QApplication::processEvents(); QApplication::processEvents();

View File

@ -139,7 +139,7 @@ void Fractorium::OnActionNewRandomFlameInCurrentFile(bool checked) { m_Controlle
template <typename T> template <typename T>
void FractoriumEmberController<T>::CopyFlameInCurrentFile() void FractoriumEmberController<T>::CopyFlameInCurrentFile()
{ {
Ember<T> ember = m_Ember; auto ember = m_Ember;
StopPreviewRender(); StopPreviewRender();
ember.m_Name = EmberFile<T>::DefaultEmberName(m_EmberFile.Size() + 1).toStdString(); ember.m_Name = EmberFile<T>::DefaultEmberName(m_EmberFile.Size() + 1).toStdString();
ember.m_Index = m_EmberFile.Size(); ember.m_Index = m_EmberFile.Size();
@ -199,7 +199,7 @@ void FractoriumEmberController<T>::OpenAndPrepFiles(const QStringList& filenames
} }
else else
{ {
vector<string> errors = parser.ErrorReport(); auto errors = parser.ErrorReport();
m_Fractorium->ErrorReportToQTextEdit(errors, m_Fractorium->ui.InfoFileOpeningTextEdit); m_Fractorium->ErrorReportToQTextEdit(errors, m_Fractorium->ui.InfoFileOpeningTextEdit);
m_Fractorium->ShowCritical("Open Failed", "Could not open file, see info tab for details."); m_Fractorium->ShowCritical("Open Failed", "Could not open file, see info tab for details.");
} }
@ -246,7 +246,7 @@ template <typename T>
void FractoriumEmberController<T>::SaveCurrentAsXml() void FractoriumEmberController<T>::SaveCurrentAsXml()
{ {
QString filename; QString filename;
FractoriumSettings* s = m_Fractorium->m_Settings; auto s = m_Fractorium->m_Settings;
if (s->SaveAutoUnique() && m_LastSaveCurrent != "") if (s->SaveAutoUnique() && m_LastSaveCurrent != "")
{ {
@ -266,10 +266,10 @@ void FractoriumEmberController<T>::SaveCurrentAsXml()
if (filename != "") if (filename != "")
{ {
Ember<T> ember = m_Ember; auto ember = m_Ember;
EmberToXml<T> writer; EmberToXml<T> writer;
QFileInfo fileInfo(filename); QFileInfo fileInfo(filename);
xmlDocPtr tempEdit = ember.m_Edits; auto tempEdit = ember.m_Edits;
SaveCurrentToOpenedFile();//Save the current ember back to the opened file before writing to disk. SaveCurrentToOpenedFile();//Save the current ember back to the opened file before writing to disk.
ApplyXmlSavingTemplate(ember); ApplyXmlSavingTemplate(ember);
ember.m_Edits = writer.CreateNewEditdoc(&ember, nullptr, "edit", s->Nick().toStdString(), s->Url().toStdString(), s->Id().toStdString(), "", 0, 0); ember.m_Edits = writer.CreateNewEditdoc(&ember, nullptr, "edit", s->Nick().toStdString(), s->Url().toStdString(), s->Id().toStdString(), "", 0, 0);
@ -300,7 +300,7 @@ template <typename T>
void FractoriumEmberController<T>::SaveEntireFileAsXml() void FractoriumEmberController<T>::SaveEntireFileAsXml()
{ {
QString filename; QString filename;
FractoriumSettings* s = m_Fractorium->m_Settings; auto s = m_Fractorium->m_Settings;
if (s->SaveAutoUnique() && m_LastSaveAll != "") if (s->SaveAutoUnique() && m_LastSaveAll != "")
filename = EmberFile<T>::UniqueFilename(m_LastSaveAll); filename = EmberFile<T>::UniqueFilename(m_LastSaveAll);
@ -340,12 +340,12 @@ void Fractorium::OnActionSaveEntireFileAsXml(bool checked) { m_Controller->SaveE
/// <param name="checked">Ignored</param> /// <param name="checked">Ignored</param>
void Fractorium::OnActionSaveCurrentScreen(bool checked) void Fractorium::OnActionSaveCurrentScreen(bool checked)
{ {
QString filename = SetupSaveImageDialog(m_Controller->Name()); auto filename = SetupSaveImageDialog(m_Controller->Name());
auto renderer = m_Controller->Renderer(); auto renderer = m_Controller->Renderer();
auto& pixels = *m_Controller->FinalImage(); auto& pixels = *m_Controller->FinalImage();
RendererCLBase* rendererCL = dynamic_cast<RendererCLBase*>(m_Controller->Renderer()); auto rendererCL = dynamic_cast<RendererCLBase*>(m_Controller->Renderer());
auto stats = m_Controller->Stats(); auto stats = m_Controller->Stats();
EmberImageComments comments = renderer->ImageComments(stats, 0, false, true); auto comments = renderer->ImageComments(stats, 0, false, true);
if (rendererCL && renderer->PrepFinalAccumVector(pixels)) if (rendererCL && renderer->PrepFinalAccumVector(pixels))
{ {
@ -460,9 +460,9 @@ void Fractorium::OnActionRedo(bool checked) { m_Controller->Redo(); }
template <typename T> template <typename T>
void FractoriumEmberController<T>::CopyXml() void FractoriumEmberController<T>::CopyXml()
{ {
Ember<T> ember = m_Ember; auto ember = m_Ember;
EmberToXml<T> emberToXml; EmberToXml<T> emberToXml;
FractoriumSettings* settings = m_Fractorium->m_Settings; auto settings = m_Fractorium->m_Settings;
ember.m_Quality = settings->XmlQuality(); ember.m_Quality = settings->XmlQuality();
ember.m_Supersample = settings->XmlSupersample(); ember.m_Supersample = settings->XmlSupersample();
ember.m_TemporalSamples = settings->XmlTemporalSamples(); ember.m_TemporalSamples = settings->XmlTemporalSamples();
@ -480,7 +480,7 @@ void FractoriumEmberController<T>::CopyAllXml()
{ {
ostringstream os; ostringstream os;
EmberToXml<T> emberToXml; EmberToXml<T> emberToXml;
FractoriumSettings* settings = m_Fractorium->m_Settings; auto settings = m_Fractorium->m_Settings;
os << "<flames>\n"; os << "<flames>\n";
for (auto& e : m_EmberFile.m_Embers) for (auto& e : m_EmberFile.m_Embers)
@ -510,8 +510,8 @@ void FractoriumEmberController<T>::PasteXmlAppend()
string s, errors; string s, errors;
XmlToEmber<T> parser; XmlToEmber<T> parser;
vector<Ember<T>> embers; vector<Ember<T>> embers;
QTextCodec* codec = QTextCodec::codecForName("UTF-8"); auto codec = QTextCodec::codecForName("UTF-8");
QByteArray b = codec->fromUnicode(QApplication::clipboard()->text()); auto b = codec->fromUnicode(QApplication::clipboard()->text());
s.reserve(b.size()); s.reserve(b.size());
for (i = 0; i < b.size(); i++) for (i = 0; i < b.size(); i++)
@ -563,9 +563,9 @@ void FractoriumEmberController<T>::PasteXmlOver()
uint i; uint i;
string s, errors; string s, errors;
XmlToEmber<T> parser; XmlToEmber<T> parser;
Ember<T> backupEmber = m_EmberFile.m_Embers[0]; auto backupEmber = m_EmberFile.m_Embers[0];
QTextCodec* codec = QTextCodec::codecForName("UTF-8"); auto codec = QTextCodec::codecForName("UTF-8");
QByteArray b = codec->fromUnicode(QApplication::clipboard()->text()); auto b = codec->fromUnicode(QApplication::clipboard()->text());
s.reserve(b.size()); s.reserve(b.size());
for (i = 0; i < b.size(); i++) for (i = 0; i < b.size(); i++)
@ -810,6 +810,7 @@ void Fractorium::OnActionFinalRender(bool checked)
{ {
//First completely stop what the current rendering process is doing. //First completely stop what the current rendering process is doing.
m_Controller->DeleteRenderer();//Delete the renderer, but not the controller. m_Controller->DeleteRenderer();//Delete the renderer, but not the controller.
m_Controller->StopPreviewRender();
OnActionSaveCurrentToOpenedFile(true);//Save whatever was edited back to the current open file. OnActionSaveCurrentToOpenedFile(true);//Save whatever was edited back to the current open file.
m_RenderStatusLabel->setText("Renderer stopped."); m_RenderStatusLabel->setText("Renderer stopped.");
m_FinalRenderDialog->show(); m_FinalRenderDialog->show();

View File

@ -139,7 +139,7 @@ void Fractorium::OnPaletteFilenameComboChanged(const QString& text)
template <typename T> template <typename T>
void FractoriumEmberController<T>::ApplyPaletteToEmber() void FractoriumEmberController<T>::ApplyPaletteToEmber()
{ {
int i, rot = 0; int rot = 0;
uint blur = m_Fractorium->m_PaletteBlurSpin->value(); uint blur = m_Fractorium->m_PaletteBlurSpin->value();
uint freq = m_Fractorium->m_PaletteFrequencySpin->value(); uint freq = m_Fractorium->m_PaletteFrequencySpin->value();
double sat = double(m_Fractorium->m_PaletteSaturationSpin->value() / 100.0); double sat = double(m_Fractorium->m_PaletteSaturationSpin->value() / 100.0);
@ -170,7 +170,7 @@ void FractoriumEmberController<T>::UpdateAdjustedPaletteGUI(Palette<T>& palette)
vector<byte> v = palette.MakeRgbPaletteBlock(PALETTE_CELL_HEIGHT);//Make the palette repeat for PALETTE_CELL_HEIGHT rows. vector<byte> v = palette.MakeRgbPaletteBlock(PALETTE_CELL_HEIGHT);//Make the palette repeat for PALETTE_CELL_HEIGHT rows.
m_FinalPaletteImage = QImage(palette.Size(), PALETTE_CELL_HEIGHT, QImage::Format_RGB888);//Create a QImage out of it. m_FinalPaletteImage = QImage(palette.Size(), PALETTE_CELL_HEIGHT, QImage::Format_RGB888);//Create a QImage out of it.
memcpy(m_FinalPaletteImage.scanLine(0), v.data(), v.size() * sizeof(v[0]));//Memcpy the data in. memcpy(m_FinalPaletteImage.scanLine(0), v.data(), v.size() * sizeof(v[0]));//Memcpy the data in.
auto pixmap = QPixmap::fromImage(m_FinalPaletteImage);//Create a QPixmap out of the QImage. QPixmap pixmap(QPixmap::fromImage(m_FinalPaletteImage));//Create a QPixmap out of the QImage.
previewPaletteItem->setData(Qt::DecorationRole, pixmap.scaled(QSize(pixmap.width(), palettePreviewTable->rowHeight(0) + 2), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));//Set the pixmap on the palette tab. previewPaletteItem->setData(Qt::DecorationRole, pixmap.scaled(QSize(pixmap.width(), palettePreviewTable->rowHeight(0) + 2), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));//Set the pixmap on the palette tab.
m_Fractorium->SetPaletteTableItem(&pixmap, m_Fractorium->ui.XformPaletteRefTable, m_Fractorium->m_PaletteRefItem, 0, 0);//Set the palette ref table on the xforms | color tab. m_Fractorium->SetPaletteTableItem(&pixmap, m_Fractorium->ui.XformPaletteRefTable, m_Fractorium->m_PaletteRefItem, 0, 0);//Set the palette ref table on the xforms | color tab.
auto previewNameItem = palettePreviewTable->item(0, 0); auto previewNameItem = palettePreviewTable->item(0, 0);
@ -287,7 +287,7 @@ void Fractorium::OnPaletteRandomSelectButtonClicked(bool checked)
/// </summary> /// </summary>
void Fractorium::OnPaletteRandomAdjustButtonClicked(bool checked) void Fractorium::OnPaletteRandomAdjustButtonClicked(bool checked)
{ {
QTIsaac<ISAAC_SIZE, ISAAC_INT>* gRand = QTIsaac<ISAAC_SIZE, ISAAC_INT>::GlobalRand.get(); auto gRand = QTIsaac<ISAAC_SIZE, ISAAC_INT>::GlobalRand.get();
m_PaletteHueSpin->setValue(-180 + gRand->Rand(361)); m_PaletteHueSpin->setValue(-180 + gRand->Rand(361));
m_PaletteSaturationSpin->setValue(-50 + gRand->Rand(101));//Full range of these leads to bad palettes, so clamp range. m_PaletteSaturationSpin->setValue(-50 + gRand->Rand(101));//Full range of these leads to bad palettes, so clamp range.
m_PaletteBrightnessSpin->setValue(-50 + gRand->Rand(101)); m_PaletteBrightnessSpin->setValue(-50 + gRand->Rand(101));

View File

@ -565,7 +565,7 @@ void FractoriumEmberController<T>::FillParamTablesAndPalette()
template <typename T> template <typename T>
void FractoriumEmberController<T>::ParamsToEmber(Ember<T>& ember) void FractoriumEmberController<T>::ParamsToEmber(Ember<T>& ember)
{ {
QColor color = m_Fractorium->ui.ColorTable->item(5, 1)->backgroundColor(); auto color = m_Fractorium->ui.ColorTable->item(5, 1)->backgroundColor();
ember.m_Brightness = m_Fractorium->m_BrightnessSpin->value();//Color. ember.m_Brightness = m_Fractorium->m_BrightnessSpin->value();//Color.
ember.m_Gamma = m_Fractorium->m_GammaSpin->value(); ember.m_Gamma = m_Fractorium->m_GammaSpin->value();
ember.m_GammaThresh = m_Fractorium->m_GammaThresholdSpin->value(); ember.m_GammaThresh = m_Fractorium->m_GammaThresholdSpin->value();

View File

@ -7,7 +7,7 @@
/// <returns>True if running, else false.</returns> /// <returns>True if running, else false.</returns>
bool FractoriumEmberControllerBase::RenderTimerRunning() bool FractoriumEmberControllerBase::RenderTimerRunning()
{ {
return m_RenderTimer && m_RenderTimer->isActive(); return m_RenderTimer->isActive();
} }
/// <summary> /// <summary>
@ -15,14 +15,11 @@ bool FractoriumEmberControllerBase::RenderTimerRunning()
/// If a renderer has not been created yet, it will be created from the options. /// If a renderer has not been created yet, it will be created from the options.
/// </summary> /// </summary>
void FractoriumEmberControllerBase::StartRenderTimer() void FractoriumEmberControllerBase::StartRenderTimer()
{
if (m_RenderTimer)
{ {
UpdateRender(); UpdateRender();
m_RenderTimer->start(); m_RenderTimer->start();
m_RenderElapsedTimer.Tic(); m_RenderElapsedTimer.Tic();
} }
}
/// <summary> /// <summary>
/// Start the render timer after a short delay. /// Start the render timer after a short delay.
@ -33,13 +30,9 @@ void FractoriumEmberControllerBase::StartRenderTimer()
void FractoriumEmberControllerBase::DelayedStartRenderTimer() void FractoriumEmberControllerBase::DelayedStartRenderTimer()
{ {
DeleteRenderer(); DeleteRenderer();
if (m_RenderRestartTimer)
{
m_RenderRestartTimer->setSingleShot(true); m_RenderRestartTimer->setSingleShot(true);
m_RenderRestartTimer->start(300);//Will stop the timer if it's already running, and start again. m_RenderRestartTimer->start(300);//Will stop the timer if it's already running, and start again.
} }
}
/// <summary> /// <summary>
/// Stop the render timer and abort the rendering process. /// Stop the render timer and abort the rendering process.
@ -48,7 +41,6 @@ void FractoriumEmberControllerBase::DelayedStartRenderTimer()
/// <param name="wait">True to block, else false.</param> /// <param name="wait">True to block, else false.</param>
void FractoriumEmberControllerBase::StopRenderTimer(bool wait) void FractoriumEmberControllerBase::StopRenderTimer(bool wait)
{ {
if (m_RenderTimer)
m_RenderTimer->stop(); m_RenderTimer->stop();
if (m_Renderer.get()) if (m_Renderer.get())
@ -130,12 +122,11 @@ void FractoriumEmberControllerBase::SaveCurrentRender(const QString& filename, c
if (filename != "") if (filename != "")
{ {
bool b = false; bool b = false;
uint i, j;
byte* data = nullptr; byte* data = nullptr;
vector<byte> vecRgb; vector<byte> vecRgb;
QFileInfo fileInfo(filename); QFileInfo fileInfo(filename);
QString suffix = fileInfo.suffix(); QString suffix = fileInfo.suffix();
FractoriumSettings* settings = m_Fractorium->m_Settings; auto settings = m_Fractorium->m_Settings;
//Ensure dimensions are valid. //Ensure dimensions are valid.
if (pixels.size() < (width * height * channels * bpc)) if (pixels.size() < (width * height * channels * bpc))
@ -183,13 +174,11 @@ void FractoriumEmberControllerBase::SaveCurrentRender(const QString& filename, c
/// <param name="action">The action for the renderer to take</param> /// <param name="action">The action for the renderer to take</param>
void FractoriumEmberControllerBase::AddProcessAction(eProcessAction action) void FractoriumEmberControllerBase::AddProcessAction(eProcessAction action)
{ {
m_Cs.Enter(); rlg l(m_Cs);
m_ProcessActions.push_back(action); m_ProcessActions.push_back(action);
if (m_Renderer.get()) if (m_Renderer.get())
m_Renderer->Abort(); m_Renderer->Abort();
m_Cs.Leave();
} }
/// <summary> /// <summary>
@ -200,7 +189,7 @@ void FractoriumEmberControllerBase::AddProcessAction(eProcessAction action)
/// <returns>The most significant processing action desired</returns> /// <returns>The most significant processing action desired</returns>
eProcessAction FractoriumEmberControllerBase::CondenseAndClearProcessActions() eProcessAction FractoriumEmberControllerBase::CondenseAndClearProcessActions()
{ {
m_Cs.Enter(); rlg l(m_Cs);
auto action = eProcessAction::NOTHING; auto action = eProcessAction::NOTHING;
for (auto a : m_ProcessActions) for (auto a : m_ProcessActions)
@ -208,7 +197,6 @@ eProcessAction FractoriumEmberControllerBase::CondenseAndClearProcessActions()
action = a; action = a;
m_ProcessActions.clear(); m_ProcessActions.clear();
m_Cs.Leave();
return action; return action;
} }
@ -266,7 +254,7 @@ template <typename T>
bool FractoriumEmberController<T>::SyncSizes() bool FractoriumEmberController<T>::SyncSizes()
{ {
bool changed = false; bool changed = false;
GLWidget* gl = m_Fractorium->ui.GLDisplay; auto gl = m_Fractorium->ui.GLDisplay;
RendererCL<T, float>* rendererCL = nullptr; RendererCL<T, float>* rendererCL = nullptr;
if (!m_GLController->SizesMatch()) if (!m_GLController->SizesMatch())
@ -296,7 +284,7 @@ bool FractoriumEmberController<T>::Render()
{ {
m_Rendering = true; m_Rendering = true;
bool success = true; bool success = true;
GLWidget* gl = m_Fractorium->ui.GLDisplay; auto gl = m_Fractorium->ui.GLDisplay;
RendererCL<T, float>* rendererCL = nullptr; RendererCL<T, float>* rendererCL = nullptr;
eProcessAction qualityAction, action; eProcessAction qualityAction, action;
//Quality is the only parameter we update inside the timer. //Quality is the only parameter we update inside the timer.
@ -403,10 +391,10 @@ bool FractoriumEmberController<T>::Render()
//Rendering has finished, update final stats. //Rendering has finished, update final stats.
if (ProcessState() == eProcessState::ACCUM_DONE) if (ProcessState() == eProcessState::ACCUM_DONE)
{ {
EmberStats stats = m_Renderer->Stats(); auto stats = m_Renderer->Stats();
QString iters = ToString<qulonglong>(stats.m_Iters); auto iters = ToString<qulonglong>(stats.m_Iters);
QString scaledQuality = ToString(uint(m_Renderer->ScaledQuality())); auto scaledQuality = ToString(uint(m_Renderer->ScaledQuality()));
string renderTime = m_RenderElapsedTimer.Format(m_RenderElapsedTimer.Toc()); auto renderTime = m_RenderElapsedTimer.Format(m_RenderElapsedTimer.Toc());
m_Fractorium->m_ProgressBar->setValue(100); m_Fractorium->m_ProgressBar->setValue(100);
//Only certain stats can be reported with OpenCL. //Only certain stats can be reported with OpenCL.
@ -417,8 +405,8 @@ bool FractoriumEmberController<T>::Render()
else else
{ {
double percent = double(stats.m_Badvals) / double(stats.m_Iters); double percent = double(stats.m_Badvals) / double(stats.m_Iters);
QString badVals = ToString<qulonglong>(stats.m_Badvals); auto badVals = ToString<qulonglong>(stats.m_Badvals);
QString badPercent = QLocale::system().toString(percent * 100, 'f', 2); auto badPercent = QLocale::system().toString(percent * 100, 'f', 2);
m_Fractorium->m_RenderStatusLabel->setText("Iters: " + iters + ". Scaled quality: " + scaledQuality + ". Bad values: " + badVals + " (" + badPercent + "%). Total time: " + QString::fromStdString(renderTime) + "."); m_Fractorium->m_RenderStatusLabel->setText("Iters: " + iters + ". Scaled quality: " + scaledQuality + ". Bad values: " + badVals + " (" + badPercent + "%). Total time: " + QString::fromStdString(renderTime) + ".");
} }
@ -427,6 +415,10 @@ bool FractoriumEmberController<T>::Render()
m_EditState = eEditUndoState::REGULAR_EDIT; m_EditState = eEditUndoState::REGULAR_EDIT;
} }
else if (m_EditState == eEditUndoState::REGULAR_EDIT)//Regular edit, just add to the end of the undo list. else if (m_EditState == eEditUndoState::REGULAR_EDIT)//Regular edit, just add to the end of the undo list.
{
auto btn = QApplication::mouseButtons();
if (!btn.testFlag(Qt::LeftButton) && !btn.testFlag(Qt::RightButton) && !btn.testFlag(Qt::MiddleButton))
{ {
m_UndoList.push_back(m_Ember); m_UndoList.push_back(m_Ember);
m_UndoIndex = m_UndoList.size() - 1; m_UndoIndex = m_UndoList.size() - 1;
@ -436,6 +428,7 @@ bool FractoriumEmberController<T>::Render()
if (m_UndoList.size() >= UNDO_SIZE) if (m_UndoList.size() >= UNDO_SIZE)
m_UndoList.pop_front(); m_UndoList.pop_front();
} }
}
else if (!m_LastEditWasUndoRedo && m_UndoIndex < m_UndoList.size() - 1)//They were anywhere but the end of the undo list, then did a manual edit, so clear the undo list. else if (!m_LastEditWasUndoRedo && m_UndoIndex < m_UndoList.size() - 1)//They were anywhere but the end of the undo list, then did a manual edit, so clear the undo list.
{ {
Ember<T> ember(m_UndoList[m_UndoIndex]); Ember<T> ember(m_UndoList[m_UndoIndex]);
@ -459,9 +452,6 @@ bool FractoriumEmberController<T>::Render()
if (m_FinalImage.size() == m_Renderer->FinalBufferSize())//Make absolutely sure the correct amount of data is passed. if (m_FinalImage.size() == m_Renderer->FinalBufferSize())//Make absolutely sure the correct amount of data is passed.
gl->update(); gl->update();
//gl->repaint();
//m_Fractorium->update();
//m_Fractorium->ui.GLParentScrollArea->update();
//Uncomment for debugging kernel build and execution errors. //Uncomment for debugging kernel build and execution errors.
//m_Fractorium->ui.InfoRenderingTextEdit->setText(QString::fromStdString(m_Fractorium->m_Wrapper.DumpInfo())); //m_Fractorium->ui.InfoRenderingTextEdit->setText(QString::fromStdString(m_Fractorium->m_Wrapper.DumpInfo()));
//if (rendererCL) //if (rendererCL)
@ -474,7 +464,7 @@ bool FractoriumEmberController<T>::Render()
} }
else//Something went very wrong, show error report. else//Something went very wrong, show error report.
{ {
vector<string> errors = m_Renderer->ErrorReport(); auto errors = m_Renderer->ErrorReport();
success = false; success = false;
m_FailedRenders++; m_FailedRenders++;
m_Fractorium->m_RenderStatusLabel->setText("Rendering failed, see info tab. Try changing parameters."); m_Fractorium->m_RenderStatusLabel->setText("Rendering failed, see info tab. Try changing parameters.");
@ -503,7 +493,6 @@ bool FractoriumEmberController<T>::Render()
if (ProcessState() == eProcessState::ACCUM_DONE) if (ProcessState() == eProcessState::ACCUM_DONE)
QThread::msleep(1); QThread::msleep(1);
//QApplication::processEvents();
m_Rendering = false; m_Rendering = false;
return success; return success;
} }
@ -520,8 +509,8 @@ template <typename T>
bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool shared) bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool shared)
{ {
bool ok = true; bool ok = true;
FractoriumSettings* s = m_Fractorium->m_Settings; auto s = m_Fractorium->m_Settings;
GLWidget* gl = m_Fractorium->ui.GLDisplay; auto gl = m_Fractorium->ui.GLDisplay;
if (!m_Renderer.get() || (m_Renderer->RendererType() != renderType) || !Equal(m_Devices, devices)) if (!m_Renderer.get() || (m_Renderer->RendererType() != renderType) || !Equal(m_Devices, devices))
{ {
@ -691,6 +680,7 @@ bool Fractorium::CreateControllerFromOptions()
//First check if a controller has already been created, and if so, save its embers and gracefully shut it down. //First check if a controller has already been created, and if so, save its embers and gracefully shut it down.
if (m_Controller.get()) if (m_Controller.get())
{ {
m_Controller->StopPreviewRender();//Must stop any previews first, else changing controllers will crash the program.
m_Controller->CopyTempPalette(tempPalette);//Convert float to double or save double verbatim; m_Controller->CopyTempPalette(tempPalette);//Convert float to double or save double verbatim;
//Replace below with this once LLVM fixes a crash in their compiler with default lambda parameters.//TODO //Replace below with this once LLVM fixes a crash in their compiler with default lambda parameters.//TODO
//m_Controller->CopyEmber(ed); //m_Controller->CopyEmber(ed);

View File

@ -48,35 +48,6 @@ void FractoriumEmberController<T>::FillXaos()
m_Fractorium->ui.XaosTableView->resizeColumnsToContents(); m_Fractorium->ui.XaosTableView->resizeColumnsToContents();
} }
/// <summary>
/// Create and return a xaos name string.
/// </summary>
/// <param name="i">The index of the xform whose xaos will be used</param>
/// <returns>The xaos name string</returns>
template <typename T>
QString FractoriumEmberController<T>::MakeXaosNameString(uint i)
{
auto xform = m_Ember.GetXform(i);
QString name;
//if (xform)
//{
// int indexPlus1 = m_Ember.GetXformIndex(xform) + 1;//GUI is 1 indexed to avoid confusing the user.
// int curr = m_Fractorium->ui.CurrentXformCombo->currentIndex() + 1;
//
// if (indexPlus1 != -1)
// {
// if (m_Fractorium->ui.XaosToRadio->isChecked())
// name = QString("From ") + ToString(curr) + QString(" To ") + ToString(indexPlus1);
// else
// name = QString("From ") + ToString(indexPlus1) + QString(" To ") + ToString(curr);
//
// //if (xform->m_Name != "")
// // name = name + " (" + QString::fromStdString(xform->m_Name) + ")";
// }
//}
return name;
}
/// <summary> /// <summary>
/// Set the xaos value. /// Set the xaos value.
/// Called when any xaos spinner is changed. /// Called when any xaos spinner is changed.
@ -93,13 +64,13 @@ void FractoriumEmberController<T>::XaosChanged(int x, int y, double val)
auto newVal = TruncPrecision(val, XAOS_PREC);//Sometimes 0 comes in as a very small number, so round. auto newVal = TruncPrecision(val, XAOS_PREC);//Sometimes 0 comes in as a very small number, so round.
if (auto xform = m_Ember.GetXform(x)) if (auto xform = m_Ember.GetXform(x))
if (!IsClose<T>(newVal, xform->Xaos(y), 1e-7)) if (!IsClose<T>(newVal, xform->Xaos(y), T(1e-7)))
Update([&] { xform->SetXaos(y, newVal); }); Update([&] { xform->SetXaos(y, newVal); });
} }
void Fractorium::OnXaosChanged(double d) void Fractorium::OnXaosChanged(double d)
{ {
if (auto* senderSpinBox = qobject_cast<DoubleSpinBox*>(this->sender())) if (auto senderSpinBox = qobject_cast<DoubleSpinBox*>(this->sender()))
{ {
auto p = senderSpinBox->property("tableindex").toPoint(); auto p = senderSpinBox->property("tableindex").toPoint();
m_Controller->XaosChanged(p.x(), p.y(), d); m_Controller->XaosChanged(p.x(), p.y(), d);

View File

@ -364,7 +364,7 @@ void FractoriumEmberController<T>::RotateXformsByAngle(double angle, bool pre)
UpdateXform([&] (Xform<T>* xform) UpdateXform([&] (Xform<T>* xform)
{ {
auto affine = pre ? &xform->m_Affine : &xform->m_Post; auto affine = pre ? &xform->m_Affine : &xform->m_Post;
affine->Rotate(angle); affine->Rotate(angle * DEG_2_RAD_T);
}, eXformUpdate::UPDATE_SELECTED); }, eXformUpdate::UPDATE_SELECTED);
FillAffineWithXform(CurrentXform(), pre); FillAffineWithXform(CurrentXform(), pre);
} }
@ -595,7 +595,7 @@ template <typename T>
void FractoriumEmberController<T>::FillAffineWithXform(Xform<T>* xform, bool pre) void FractoriumEmberController<T>::FillAffineWithXform(Xform<T>* xform, bool pre)
{ {
DoubleSpinBox** spinners = pre ? m_Fractorium->m_PreSpins : m_Fractorium->m_PostSpins; DoubleSpinBox** spinners = pre ? m_Fractorium->m_PreSpins : m_Fractorium->m_PostSpins;
const Affine2D<T>& affine = pre ? xform->m_Affine : xform->m_Post; auto& affine = pre ? xform->m_Affine : xform->m_Post;
if (m_Fractorium->ui.PolarAffineCheckBox->isChecked()) if (m_Fractorium->ui.PolarAffineCheckBox->isChecked())
{ {

View File

@ -47,7 +47,15 @@ void FractoriumEmberController<T>::XformColorIndexChanged(double d, bool updateR
scroll->blockSignals(true); scroll->blockSignals(true);
scroll->setValue(scrollVal); scroll->setValue(scrollVal);
scroll->blockSignals(false); scroll->blockSignals(false);
SetCurrentXformColorIndex(d, updateRender); m_Fractorium->ui.XformColorIndexTable->item(0, 0)->setBackgroundColor(ColorIndexToQColor(d));//Grab the current color from the index and assign it to the first cell of the first table.
if (updateRender)//False when just updating GUI, true when in response to a GUI change so update values and reset renderer.
{
UpdateXform([&](Xform<T>* xform)
{
xform->m_ColorX = Clamp<T>(d, 0, 1);
}, eXformUpdate::UPDATE_SELECTED, updateRender);
}
} }
void Fractorium::OnXformColorIndexChanged(double d) { OnXformColorIndexChanged(d, true); } void Fractorium::OnXformColorIndexChanged(double d) { OnXformColorIndexChanged(d, true); }
@ -135,7 +143,7 @@ void Fractorium::OnSoloXformCheckBoxStateChanged(int state)
/// <param name="newSize">Ignored</param> /// <param name="newSize">Ignored</param>
void Fractorium::OnXformRefPaletteResized(int logicalIndex, int oldSize, int newSize) void Fractorium::OnXformRefPaletteResized(int logicalIndex, int oldSize, int newSize)
{ {
QPixmap pixmap = QPixmap::fromImage(m_Controller->FinalPaletteImage()); QPixmap pixmap(QPixmap::fromImage(m_Controller->FinalPaletteImage()));
SetPaletteTableItem(&pixmap, ui.XformPaletteRefTable, m_PaletteRefItem, 0, 0); SetPaletteTableItem(&pixmap, ui.XformPaletteRefTable, m_PaletteRefItem, 0, 0);
} }
@ -204,22 +212,6 @@ QColor FractoriumEmberController<T>::ColorIndexToQColor(double d)
return QColor::fromRgb(rgb); return QColor::fromRgb(rgb);
} }
/// <summary>
/// Set the selected xforms color index to the passed in value.
/// Set the color cell in the palette ref table.
/// </summary>
/// <param name="d">The index value to set, 0-1.</param>
template <typename T>
void FractoriumEmberController<T>::SetCurrentXformColorIndex(double d, bool updateRender)
{
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);
}
/// <summary> /// <summary>
/// Set the points in the curves control to the values of the curve points in the current ember. /// Set the points in the curves control to the values of the curve points in the current ember.
/// </summary> /// </summary>

View File

@ -9,7 +9,6 @@ void Fractorium::InitXformsSelectUI()
m_XformsSelectionLayout = (QFormLayout*)ui.XformsSelectGroupBoxScrollAreaWidget->layout(); m_XformsSelectionLayout = (QFormLayout*)ui.XformsSelectGroupBoxScrollAreaWidget->layout();
connect(ui.XformsSelectAllButton, SIGNAL(clicked(bool)), this, SLOT(OnXformsSelectAllButtonClicked(bool)), Qt::QueuedConnection); connect(ui.XformsSelectAllButton, SIGNAL(clicked(bool)), this, SLOT(OnXformsSelectAllButtonClicked(bool)), Qt::QueuedConnection);
connect(ui.XformsSelectNoneButton, SIGNAL(clicked(bool)), this, SLOT(OnXformsSelectNoneButtonClicked(bool)), Qt::QueuedConnection); connect(ui.XformsSelectNoneButton, SIGNAL(clicked(bool)), this, SLOT(OnXformsSelectNoneButtonClicked(bool)), Qt::QueuedConnection);
ClearXformsSelections(); ClearXformsSelections();
} }
@ -31,7 +30,6 @@ void Fractorium::OnXformsSelectNoneButtonClicked(bool checked) { ForEachXformChe
void Fractorium::ClearXformsSelections() void Fractorium::ClearXformsSelections()
{ {
QLayoutItem* child = nullptr; QLayoutItem* child = nullptr;
m_XformSelections.clear(); m_XformSelections.clear();
m_XformsSelectionLayout->blockSignals(true); m_XformsSelectionLayout->blockSignals(true);
@ -95,9 +93,9 @@ void Fractorium::ForEachXformCheckbox(std::function<void(int, QCheckBox*)> func)
template <typename T> template <typename T>
bool FractoriumEmberController<T>::XformCheckboxAt(int i, std::function<void(QCheckBox*)> func) bool FractoriumEmberController<T>::XformCheckboxAt(int i, std::function<void(QCheckBox*)> func)
{ {
if (QLayoutItem* child = m_Fractorium->m_XformsSelectionLayout->itemAt(i)) if (auto child = m_Fractorium->m_XformsSelectionLayout->itemAt(i))
{ {
if (auto* w = qobject_cast<QCheckBox*>(child->widget())) if (auto w = qobject_cast<QCheckBox*>(child->widget()))
{ {
func(w); func(w);
return true; return true;

View File

@ -171,11 +171,11 @@ void FractoriumEmberController<T>::SetupVariationTree()
template <typename T> template <typename T>
void FractoriumEmberController<T>::ClearVariationsTree() void FractoriumEmberController<T>::ClearVariationsTree()
{ {
QTreeWidget* tree = m_Fractorium->ui.VariationsTree; auto tree = m_Fractorium->ui.VariationsTree;
for (int i = 0; i < tree->topLevelItemCount(); i++) for (int i = 0; i < tree->topLevelItemCount(); i++)
{ {
QTreeWidgetItem* item = tree->topLevelItem(i); auto item = tree->topLevelItem(i);
auto* spinBox = dynamic_cast<VariationTreeDoubleSpinBox*>(tree->itemWidget(item, 1)); auto* spinBox = dynamic_cast<VariationTreeDoubleSpinBox*>(tree->itemWidget(item, 1));
spinBox->SetValueStealth(0); spinBox->SetValueStealth(0);
@ -189,7 +189,7 @@ void FractoriumEmberController<T>::ClearVariationsTree()
/// <summary> /// <summary>
/// Copy the value of a variation or param spinner to its corresponding value /// Copy the value of a variation or param spinner to its corresponding value
/// in the currently selected xform. /// in the selected xforms.
/// Called when any spinner in the variations tree is changed. /// Called when any spinner in the variations tree is changed.
/// Resets the rendering process. /// Resets the rendering process.
/// </summary> /// </summary>
@ -197,12 +197,15 @@ void FractoriumEmberController<T>::ClearVariationsTree()
template <typename T> template <typename T>
void FractoriumEmberController<T>::VariationSpinBoxValueChanged(double d)//Would be awesome to make this work for all.//TODO void FractoriumEmberController<T>::VariationSpinBoxValueChanged(double d)//Would be awesome to make this work for all.//TODO
{ {
bool update = false;
auto objSender = m_Fractorium->sender(); auto objSender = m_Fractorium->sender();
auto tree = m_Fractorium->ui.VariationsTree; auto tree = m_Fractorium->ui.VariationsTree;
auto sender = dynamic_cast<VariationTreeDoubleSpinBox*>(objSender); auto sender = dynamic_cast<VariationTreeDoubleSpinBox*>(objSender);
auto xform = m_Ember.GetTotalXform(m_Fractorium->ui.CurrentXformCombo->currentIndex());//Will retrieve normal xform or final if needed. auto xform = m_Ember.GetTotalXform(m_Fractorium->ui.CurrentXformCombo->currentIndex());//Will retrieve normal xform or final if needed.
if (sender && xform) if (sender)
{
UpdateXform([&](Xform<T>* xform)
{ {
auto var = m_VariationList.GetVariation(sender->GetVariationId());//The variation attached to the sender, for reference only. auto var = m_VariationList.GetVariation(sender->GetVariationId());//The variation attached to the sender, for reference only.
auto parVar = dynamic_cast<const ParametricVariation<T>*>(var);//The parametric cast of that variation. auto parVar = dynamic_cast<const ParametricVariation<T>*>(var);//The parametric cast of that variation.
@ -214,12 +217,8 @@ void FractoriumEmberController<T>::VariationSpinBoxValueChanged(double d)//Would
{ {
//Do not take action if the xform doesn't contain the variation which this param is part of. //Do not take action if the xform doesn't contain the variation which this param is part of.
if (ParametricVariation<T>* xformParVar = dynamic_cast<ParametricVariation<T>*>(xformVar))//The parametric cast of the xform's variation. if (ParametricVariation<T>* xformParVar = dynamic_cast<ParametricVariation<T>*>(xformVar))//The parametric cast of the xform's variation.
{
if (xformParVar->SetParamVal(sender->ParamName().c_str(), d)) if (xformParVar->SetParamVal(sender->ParamName().c_str(), d))
{ update = true;
UpdateRender();
}
}
} }
else else
{ {
@ -268,8 +267,12 @@ void FractoriumEmberController<T>::VariationSpinBoxValueChanged(double d)//Would
} }
} }
UpdateRender(); update = true;
} }
}, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);
if (update)
UpdateRender();
} }
} }

View File

@ -103,6 +103,20 @@ T GLEmberController<T>::CalcRotation()
return rotStart - rot; return rotStart - rot;
} }
/// <summary>
/// Snap the passed in world cartesian coordinate to the grid for rotation, scale or translation.
/// </summary>
/// <param name="vec">The world cartesian coordinate to be snapped</param>
/// <returns>The snapped world cartesian coordinate</returns>
template <typename T>
typename v2T GLEmberController<T>::SnapToGrid(v2T& vec)
{
v2T ret;
ret.x = glm::round(vec.x / GridStep) * GridStep;
ret.y = glm::round(vec.y / GridStep) * GridStep;
return ret;
}
/// <summary> /// <summary>
/// Snap the passed in world cartesian coordinate to the grid for rotation, scale or translation. /// Snap the passed in world cartesian coordinate to the grid for rotation, scale or translation.
/// </summary> /// </summary>
@ -135,8 +149,8 @@ typename v3T GLEmberController<T>::SnapToNormalizedAngle(v3T& vec, uint division
for (uint i = 0; i < divisions; i++) for (uint i = 0; i < divisions; i++)
{ {
theta = 2.0 * M_PI * T(i) / T(divisions); theta = 2.0 * M_PI * T(i) / T(divisions);
c.x = cos(theta); c.x = std::cos(theta);
c.y = sin(theta); c.y = std::sin(theta);
rsq = glm::distance(vec, c); rsq = glm::distance(vec, c);
if (rsq < bestRsq) if (rsq < bestRsq)
@ -220,7 +234,7 @@ void GLEmberController<double>::MultMatrix(tmat4x4<double, glm::defaultp>& mat)
template <typename T> template <typename T>
void GLEmberController<T>::QueryMatrices(bool print) void GLEmberController<T>::QueryMatrices(bool print)
{ {
RendererBase* renderer = m_FractoriumEmberController->Renderer(); auto renderer = m_FractoriumEmberController->Renderer();
if (renderer) if (renderer)
{ {
@ -242,13 +256,13 @@ void GLEmberController<T>::QueryMatrices(bool print)
if (print) if (print)
{ {
for (size_t i = 0; i < 4; i++) for (size_t i = 0; i < 4; i++)
qDebug() << "Viewport[" << i << "] = " << m_Viewport[i] << endl; qDebug() << "Viewport[" << i << "] = " << m_Viewport[i] << "\n";
for (size_t i = 0; i < 16; i++) for (size_t i = 0; i < 16; i++)
qDebug() << "Modelview[" << i << "] = " << glm::value_ptr(m_Modelview)[i] << endl; qDebug() << "Modelview[" << i << "] = " << glm::value_ptr(m_Modelview)[i] << "\n";
for (size_t i = 0; i < 16; i++) for (size_t i = 0; i < 16; i++)
qDebug() << "Projection[" << i << "] = " << glm::value_ptr(m_Projection)[i] << endl; qDebug() << "Projection[" << i << "] = " << glm::value_ptr(m_Projection)[i] << "\n";
} }
} }
} }

View File

@ -109,9 +109,9 @@ public:
T CalcScale(); T CalcScale();
T CalcRotation(); T CalcRotation();
Affine2D<T> CalcDragXAxis(); void CalcDragXAxis();
Affine2D<T> CalcDragYAxis(); void CalcDragYAxis();
Affine2D<T> CalcDragTranslation(); void CalcDragTranslation();
void SetEmber(Ember<T>* ember); void SetEmber(Ember<T>* ember);
void SetSelectedXform(Xform<T>* xform); void SetSelectedXform(Xform<T>* xform);
@ -120,6 +120,7 @@ public:
bool CheckXformHover(Xform<T>* xform, v3T& glCoords, T& bestDist, bool pre, bool post); bool CheckXformHover(Xform<T>* xform, v3T& glCoords, T& bestDist, bool pre, bool post);
private: private:
v2T SnapToGrid(v2T& vec);
v3T SnapToGrid(v3T& vec); v3T SnapToGrid(v3T& vec);
v3T SnapToNormalizedAngle(v3T& vec, uint divisions); v3T SnapToNormalizedAngle(v3T& vec, uint divisions);
v3T WindowToWorld(v3T& v, bool flip); v3T WindowToWorld(v3T& v, bool flip);

View File

@ -63,8 +63,8 @@ void GLWidget::DrawQuad()
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
RendererBase* renderer = m_Fractorium->m_Controller->Renderer(); auto renderer = m_Fractorium->m_Controller->Renderer();
vector<byte>* finalImage = m_Fractorium->m_Controller->FinalImage(); auto finalImage = m_Fractorium->m_Controller->FinalImage();
//Ensure all allocation has taken place first. //Ensure all allocation has taken place first.
if (m_OutputTexID != 0 && finalImage && !finalImage->empty()) if (m_OutputTexID != 0 && finalImage && !finalImage->empty())
@ -214,9 +214,9 @@ void GLWidget::paintGL()
//Ensure there is a renderer and that it's supposed to be drawing, signified by the running timer. //Ensure there is a renderer and that it's supposed to be drawing, signified by the running timer.
if (controller && controller->Renderer()) if (controller && controller->Renderer())
{ {
RendererBase* renderer = controller->Renderer(); auto renderer = controller->Renderer();
m_Drawing = true; m_Drawing = true;
controller->GLController()->DrawImage(); GLController()->DrawImage();
//Affine drawing. //Affine drawing.
bool pre = m_Fractorium->ui.PreAffineGroupBox->isChecked(); bool pre = m_Fractorium->ui.PreAffineGroupBox->isChecked();
bool post = m_Fractorium->ui.PostAffineGroupBox->isChecked(); bool post = m_Fractorium->ui.PostAffineGroupBox->isChecked();
@ -431,7 +431,7 @@ void GLEmberController<T>::MousePress(QMouseEvent* e)
m_BoundsDown.x = renderer->LowerLeftY(false); m_BoundsDown.x = renderer->LowerLeftY(false);
m_BoundsDown.y = renderer->UpperRightX(false); m_BoundsDown.y = renderer->UpperRightX(false);
m_BoundsDown.z = renderer->UpperRightY(false); m_BoundsDown.z = renderer->UpperRightY(false);
Qt::KeyboardModifiers mod = e->modifiers(); auto mod = e->modifiers();
if (mod.testFlag(Qt::ShiftModifier)) if (mod.testFlag(Qt::ShiftModifier))
SetShift(); SetShift();
@ -455,11 +455,11 @@ void GLEmberController<T>::MousePress(QMouseEvent* e)
m_DragSrcTransform = Affine2D<T>(m_AffineType == eAffineType::AffinePre ? m_SelectedXform->m_Affine : m_SelectedXform->m_Post);//Copy the affine of the xform that was selected. m_DragSrcTransform = Affine2D<T>(m_AffineType == eAffineType::AffinePre ? m_SelectedXform->m_Affine : m_SelectedXform->m_Post);//Copy the affine of the xform that was selected.
//The user has selected an xform by clicking on it, so update the main GUI by selecting this xform in the combo box. //The user has selected an xform by clicking on it, so update the main GUI by selecting this xform in the combo box.
m_Fractorium->CurrentXform(xformIndex);//Must do this first so UpdateXform() below properly grabs the current plus any selected. m_Fractorium->CurrentXform(xformIndex);//Must do this first so UpdateXform() below properly grabs the current plus any selected.
//m_DragSrcTransforms.clear(); m_DragSrcTransforms.clear();
//m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform) m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
//{ {
// m_DragSrcTransforms.push_back(m_AffineType == eAffineType::AffinePre ? xform->m_Affine : xform->m_Post); m_DragSrcTransforms.push_back(m_AffineType == eAffineType::AffinePre ? xform->m_Affine : xform->m_Post);
//}, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);//Don't update renderer here. }, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);//Don't update renderer here.
m_DragHandlePos = m_HoverHandlePos;//The location in local coordinates of the point selected on the spinner, x, y or center. m_DragHandlePos = m_HoverHandlePos;//The location in local coordinates of the point selected on the spinner, x, y or center.
m_DragHandleOffset = m_DragHandlePos - m_MouseWorldPos;//The distance in world coordinates from the point selected to the center of the spinner. m_DragHandleOffset = m_DragHandlePos - m_MouseWorldPos;//The distance in world coordinates from the point selected to the center of the spinner.
m_DragState = eDragState::DragDragging; m_DragState = eDragState::DragDragging;
@ -505,7 +505,7 @@ void GLWidget::mousePressEvent(QMouseEvent* e)
{ {
setFocus();//Must do this so that this window gets keyboard events. setFocus();//Must do this so that this window gets keyboard events.
if (GLEmberControllerBase* controller = GLController()) if (auto controller = GLController())
controller->MousePress(e); controller->MousePress(e);
QOpenGLWidget::mousePressEvent(e); QOpenGLWidget::mousePressEvent(e);
@ -538,7 +538,7 @@ void GLWidget::mouseReleaseEvent(QMouseEvent* e)
{ {
setFocus();//Must do this so that this window gets keyboard events. setFocus();//Must do this so that this window gets keyboard events.
if (GLEmberControllerBase* controller = GLController()) if (auto controller = GLController())
controller->MouseRelease(e); controller->MouseRelease(e);
QOpenGLWidget::mouseReleaseEvent(e); QOpenGLWidget::mouseReleaseEvent(e);
@ -571,22 +571,13 @@ void GLEmberController<T>::MouseMove(QMouseEvent* e)
if (m_SelectedXform && m_DragState == eDragState::DragDragging)//Dragging and affine. if (m_SelectedXform && m_DragState == eDragState::DragDragging)//Dragging and affine.
{ {
bool pre = m_AffineType == eAffineType::AffinePre; bool pre = m_AffineType == eAffineType::AffinePre;
Affine2D<T>* affine = pre ? &m_SelectedXform->m_Affine : &m_SelectedXform->m_Post;//Determine pre or post affine.
if (m_HoverType == eHoverType::HoverTranslation) if (m_HoverType == eHoverType::HoverTranslation)
{ CalcDragTranslation();
//m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
//{
// affine = pre ? &xform->m_Affine : &xform->m_Post;//Determine pre or post affine.
// *affine = CalcDragTranslation();
//}, eXformUpdate::UPDATE_ALL, false);//Don't need to update render for every xform, just do it once below.
*affine = CalcDragTranslation();
//CalcDragTranslation();
}
else if (m_HoverType == eHoverType::HoverXAxis) else if (m_HoverType == eHoverType::HoverXAxis)
*affine = CalcDragXAxis(); CalcDragXAxis();
else if (m_HoverType == eHoverType::HoverYAxis) else if (m_HoverType == eHoverType::HoverYAxis)
*affine = CalcDragYAxis(); CalcDragYAxis();
m_FractoriumEmberController->FillAffineWithXform(m_SelectedXform, pre);//Update the spinners in the affine tab of the main window. m_FractoriumEmberController->FillAffineWithXform(m_SelectedXform, pre);//Update the spinners in the affine tab of the main window.
m_FractoriumEmberController->UpdateRender();//Restart the rendering process. m_FractoriumEmberController->UpdateRender();//Restart the rendering process.
@ -598,7 +589,7 @@ void GLEmberController<T>::MouseMove(QMouseEvent* e)
Affine2D<T> rotMat; Affine2D<T> rotMat;
rotMat.C(m_CenterDownX); rotMat.C(m_CenterDownX);
rotMat.F(m_CenterDownY); rotMat.F(m_CenterDownY);
rotMat.Rotate(ember->m_Rotate); rotMat.Rotate(ember->m_Rotate * DEG_2_RAD_T);
v2T v1(x, y); v2T v1(x, y);
v2T v2 = rotMat.TransformVector(v1); v2T v2 = rotMat.TransformVector(v1);
ember->m_CenterX = v2.x; ember->m_CenterX = v2.x;
@ -611,8 +602,7 @@ void GLEmberController<T>::MouseMove(QMouseEvent* e)
T scale = CalcScale(); T scale = CalcScale();
ember->m_Rotate = NormalizeDeg180<T>(m_RotationDown + rot); ember->m_Rotate = NormalizeDeg180<T>(m_RotationDown + rot);
m_Fractorium->SetRotation(ember->m_Rotate, true); m_Fractorium->SetRotation(ember->m_Rotate, true);
ember->m_PixelsPerUnit = m_ScaleDown + scale; m_Fractorium->SetScale(m_ScaleDown + scale);//Will restart the rendering process.
m_Fractorium->SetScale(ember->m_PixelsPerUnit);//Will restart the rendering process.
} }
else else
{ {
@ -625,22 +615,12 @@ void GLEmberController<T>::MouseMove(QMouseEvent* e)
//In that case, nothing needs to be done. //In that case, nothing needs to be done.
if (UpdateHover(mouseFlipped) == -1) if (UpdateHover(mouseFlipped) == -1)
draw = false; draw = false;
//auto previousHover = m_HoverXform;
//
//if (UpdateHover(mouseFlipped) == -1)
// m_HoverXform = m_SelectedXform;
//
//if (m_HoverXform == previousHover)
// draw = false;
} }
//Only update if the user was dragging or hovered over a point. //Only update if the user was dragging or hovered over a point.
//Use repaint() to update immediately for a more responsive feel. //Use repaint() to update immediately for a more responsive feel.
if ((m_DragState != eDragState::DragNone) || draw) if ((m_DragState != eDragState::DragNone) || draw)
m_GL->update(); m_GL->update();
//m_GL->repaint();
} }
/// <summary> /// <summary>
@ -651,7 +631,7 @@ void GLWidget::mouseMoveEvent(QMouseEvent* e)
{ {
setFocus();//Must do this so that this window gets keyboard events. setFocus();//Must do this so that this window gets keyboard events.
if (GLEmberControllerBase* controller = GLController()) if (auto controller = GLController())
controller->MouseMove(e); controller->MouseMove(e);
QOpenGLWidget::mouseMoveEvent(e); QOpenGLWidget::mouseMoveEvent(e);
@ -679,28 +659,12 @@ void GLEmberController<T>::Wheel(QWheelEvent* e)
/// <param name="e">The event</param> /// <param name="e">The event</param>
void GLWidget::wheelEvent(QWheelEvent* e) void GLWidget::wheelEvent(QWheelEvent* e)
{ {
if (GLEmberControllerBase* controller = GLController()) if (auto controller = GLController())
controller->Wheel(e); controller->Wheel(e);
//Do not call QOpenGLWidget::wheelEvent(e) because this should only affect the scale and not the position of the scroll bars. //Do not call QOpenGLWidget::wheelEvent(e) because this should only affect the scale and not the position of the scroll bars.
} }
/// <summary>
/// Respond to a resize event which will set the double click default value
/// in the width and height spinners.
/// Note, this does not change the size of the ember being rendered or
/// the OpenGL texture it's being drawn on.
/// </summary>
/// <param name="e">The event</param>
//void GLWidget::resizeEvent(QResizeEvent* e)
//{
// if (m_Fractorium)
// {
// }
//
// QOpenGLWidget::resizeEvent(e);
//}
/// <summary> /// <summary>
/// Set the dimensions of the drawing area. /// Set the dimensions of the drawing area.
/// This will be called from the main window's SyncSizes() function. /// This will be called from the main window's SyncSizes() function.
@ -710,8 +674,6 @@ void GLWidget::wheelEvent(QWheelEvent* e)
void GLWidget::SetDimensions(int w, int h) void GLWidget::SetDimensions(int w, int h)
{ {
setFixedSize(w, h); setFixedSize(w, h);
//resize(w, h);
//m_Fractorium->ui.GLParentScrollAreaContents->setFixedSize(w, h);
} }
/// <summary> /// <summary>
@ -817,7 +779,7 @@ bool GLEmberController<T>::SizesMatch()
/// <param name="scale">A value to scale by, used when locking the affine scale</param> /// <param name="scale">A value to scale by, used when locking the affine scale</param>
void GLWidget::DrawGrid(double scale) void GLWidget::DrawGrid(double scale)
{ {
RendererBase* renderer = m_Fractorium->m_Controller->Renderer(); auto renderer = m_Fractorium->m_Controller->Renderer();
float unitX = std::abs(renderer->UpperRightX(false) - renderer->LowerLeftX(false)) / 2.0f; float unitX = std::abs(renderer->UpperRightX(false) - renderer->LowerLeftX(false)) / 2.0f;
float unitY = std::abs(renderer->UpperRightY(false) - renderer->LowerLeftY(false)) / 2.0f; float unitY = std::abs(renderer->UpperRightY(false) - renderer->LowerLeftY(false)) / 2.0f;
float rad = std::max(unitX * scale, unitY * scale); float rad = std::max(unitX * scale, unitY * scale);
@ -916,10 +878,10 @@ template <typename T>
void GLEmberController<T>::DrawAffine(Xform<T>* xform, bool pre, bool selected) void GLEmberController<T>::DrawAffine(Xform<T>* xform, bool pre, bool selected)
{ {
auto ember = m_FractoriumEmberController->CurrentEmber(); auto ember = m_FractoriumEmberController->CurrentEmber();
bool final = ember->IsFinalXform(xform); auto final = ember->IsFinalXform(xform);
int index = ember->GetXformIndex(xform); auto index = ember->GetXformIndex(xform);
size_t size = ember->m_Palette.m_Entries.size(); auto size = ember->m_Palette.m_Entries.size();
v4T color = ember->m_Palette.m_Entries[Clamp<T>(xform->m_ColorX * size, 0, size - 1)]; auto color = ember->m_Palette.m_Entries[Clamp<T>(xform->m_ColorX * size, 0, size - 1)];
auto affine = pre ? &xform->m_Affine : &xform->m_Post; auto affine = pre ? &xform->m_Affine : &xform->m_Post;
//For some incredibly strange reason, even though glm and OpenGL use matrices with a column-major //For some incredibly strange reason, even though glm and OpenGL use matrices with a column-major
//data layout, nothing will work here unless they are flipped to row major order. This is how it was //data layout, nothing will work here unless they are flipped to row major order. This is how it was
@ -968,7 +930,7 @@ void GLWidget::DrawAffineHelper(int index, bool selected, bool pre, bool final,
{ {
float px = 1.0f; float px = 1.0f;
float py = 0.0f; float py = 0.0f;
QColor col = final ? m_Fractorium->m_FinalXformComboColor : m_Fractorium->m_XformComboColors[index % XFORM_COLOR_COUNT]; auto col = final ? m_Fractorium->m_FinalXformComboColor : m_Fractorium->m_XformComboColors[index % XFORM_COLOR_COUNT];
glBegin(GL_LINES); glBegin(GL_LINES);
//Circle part. //Circle part.
@ -986,8 +948,8 @@ void GLWidget::DrawAffineHelper(int index, bool selected, bool pre, bool final,
for (size_t i = 1; i <= 64; i++)//The circle. for (size_t i = 1; i <= 64; i++)//The circle.
{ {
float theta = float(M_PI) * 2.0f * float(i % 64) / 64.0f; float theta = float(M_PI) * 2.0f * float(i % 64) / 64.0f;
float fx = float(cos(theta)); float fx = std::cos(theta);
float fy = float(sin(theta)); float fy = std::sin(theta);
glVertex2f(px, py); glVertex2f(px, py);
glVertex2f(fx, fy); glVertex2f(fx, fy);
px = fx; px = fx;
@ -1214,56 +1176,73 @@ bool GLEmberController<T>::CheckXformHover(Xform<T>* xform, v3T& glCoords, T& be
/// </summary> /// </summary>
/// <returns>The new affine transform to be assigned to the selected xform</returns> /// <returns>The new affine transform to be assigned to the selected xform</returns>
template <typename T> template <typename T>
Affine2D<T> GLEmberController<T>::CalcDragXAxis() void GLEmberController<T>::CalcDragXAxis()
{ {
v3T t3, newAxis, newPos; size_t index = 0;
auto scale = m_FractoriumEmberController->AffineScaleLockedToCurrent(); auto scale = m_FractoriumEmberController->AffineScaleLockedToCurrent();
auto result = m_DragSrcTransform; auto scaleBack = m_FractoriumEmberController->AffineScaleCurrentToLocked();
bool pre = m_AffineType == eAffineType::AffinePre;
bool worldPivotShiftAlt = !m_Fractorium->LocalPivot() && GetShift() && GetAlt(); bool worldPivotShiftAlt = !m_Fractorium->LocalPivot() && GetShift() && GetAlt();
if (worldPivotShiftAlt)
t3 = v3T(0, 0, 0);
else
t3 = v3T(m_DragSrcTransform.O(), 0);
if (GetShift()) if (GetShift())
{ {
v3T targetAxis = (m_MouseWorldPos * scale) - t3; v3T snapped = GetControl() ? SnapToNormalizedAngle(m_MouseWorldPos + m_DragHandleOffset, 24) : m_MouseWorldPos + m_DragHandleOffset;
v3T norm = glm::normalize(targetAxis); auto startDiff = (v2T(m_MouseDownWorldPos) * scale) - m_DragSrcTransform.O();
auto endDiff = (v2T(snapped) * scale) - m_DragSrcTransform.O();
if (GetControl()) T startAngle = std::atan2(startDiff.y, startDiff.x);
norm = SnapToNormalizedAngle(norm, 24); T endAngle = std::atan2(endDiff.y, endDiff.x);
T angle = startAngle - endAngle;
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
{
auto affine = pre ? &xform->m_Affine : &xform->m_Post;
auto srcRotated = m_DragSrcTransforms[index++];
if (worldPivotShiftAlt) if (worldPivotShiftAlt)
newAxis = norm * glm::length(m_DragSrcTransform.O() + m_DragSrcTransform.X()); {
else srcRotated.X(srcRotated.O() + srcRotated.X());
newAxis = norm * glm::length(m_DragSrcTransform.X()); srcRotated.O(v2T(0));
srcRotated.Rotate(angle);
affine->X(srcRotated.X() - affine->O());
}
else if (GetAlt())
{
srcRotated.Rotate(angle);
affine->X(srcRotated.X());
} }
else else
{ {
if (GetControl()) srcRotated.Rotate(angle);
newPos = SnapToGrid(m_MouseWorldPos); *affine = srcRotated;
else
newPos = m_MouseWorldPos + m_DragHandleOffset;
newAxis = (newPos * scale) - t3;
} }
if (xform == m_FractoriumEmberController->CurrentXform())
m_DragHandlePos = v3T((affine->O() + affine->X()) * scaleBack, 0);
}, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);//Calling code will update renderer.
}
else
{
v3T diff;
if (GetControl())
diff = SnapToGrid(m_MouseWorldPos + m_DragHandleOffset) - m_MouseDownWorldPos;
else
diff = (m_MouseWorldPos + m_DragHandleOffset) - m_MouseDownWorldPos;
auto origXPlusOff = v3T(m_DragSrcTransform.X(), 0) + (diff * scale);
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
{
auto affine = pre ? &xform->m_Affine : &xform->m_Post;
auto axis = v3T(m_DragSrcTransforms[index++].X(), 0) + (diff * scale);
if (GetAlt()) if (GetAlt())
{ affine->X(v2T(origXPlusOff));//Absolute, not ratio.
if (worldPivotShiftAlt)
result.X(v2T(newAxis) - m_DragSrcTransform.O());
else else
result.X(v2T(newAxis)); affine->RotateScaleXTo(v2T(axis));
}
else
{
result.RotateScaleXTo(v2T(newAxis));
}
T scaleBack = m_FractoriumEmberController->AffineScaleCurrentToLocked(); if (xform == m_FractoriumEmberController->CurrentXform())
m_DragHandlePos = v3T((result.O() + result.X()) * scaleBack, 0); m_DragHandlePos = v3T((affine->O() + affine->X()) * scaleBack, 0);
return result; }, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);
}
} }
/// <summary> /// <summary>
@ -1285,56 +1264,73 @@ Affine2D<T> GLEmberController<T>::CalcDragXAxis()
/// </summary> /// </summary>
/// <returns>The new affine transform to be assigned to the selected xform</returns> /// <returns>The new affine transform to be assigned to the selected xform</returns>
template <typename T> template <typename T>
Affine2D<T> GLEmberController<T>::CalcDragYAxis() void GLEmberController<T>::CalcDragYAxis()
{ {
v3T t3, newAxis, newPos; size_t index = 0;
auto scale = m_FractoriumEmberController->AffineScaleLockedToCurrent(); auto scale = m_FractoriumEmberController->AffineScaleLockedToCurrent();
auto result = m_DragSrcTransform; auto scaleBack = m_FractoriumEmberController->AffineScaleCurrentToLocked();
bool pre = m_AffineType == eAffineType::AffinePre;
bool worldPivotShiftAlt = !m_Fractorium->LocalPivot() && GetShift() && GetAlt(); bool worldPivotShiftAlt = !m_Fractorium->LocalPivot() && GetShift() && GetAlt();
if (worldPivotShiftAlt)
t3 = v3T(0, 0, 0);
else
t3 = v3T(m_DragSrcTransform.O(), 0);
if (GetShift()) if (GetShift())
{ {
v3T targetAxis = (m_MouseWorldPos * scale) - t3; v3T snapped = GetControl() ? SnapToNormalizedAngle(m_MouseWorldPos + m_DragHandleOffset, 24) : m_MouseWorldPos + m_DragHandleOffset;
v3T norm = glm::normalize(targetAxis); auto startDiff = (v2T(m_MouseDownWorldPos) * scale) - m_DragSrcTransform.O();
auto endDiff = (v2T(snapped) * scale) - m_DragSrcTransform.O();
if (GetControl()) T startAngle = std::atan2(startDiff.y, startDiff.x);
norm = SnapToNormalizedAngle(norm, 24); T endAngle = std::atan2(endDiff.y, endDiff.x);
T angle = startAngle - endAngle;
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
{
auto affine = pre ? &xform->m_Affine : &xform->m_Post;
auto srcRotated = m_DragSrcTransforms[index++];
if (worldPivotShiftAlt) if (worldPivotShiftAlt)
newAxis = norm * glm::length(m_DragSrcTransform.O() + m_DragSrcTransform.Y()); {
else srcRotated.Y(srcRotated.O() + srcRotated.Y());
newAxis = norm * glm::length(m_DragSrcTransform.Y()); srcRotated.O(v2T(0));
srcRotated.Rotate(angle);
affine->Y(srcRotated.Y() - affine->O());
}
else if (GetAlt())
{
srcRotated.Rotate(angle);
affine->Y(srcRotated.Y());
} }
else else
{ {
if (GetControl()) srcRotated.Rotate(angle);
newPos = SnapToGrid(m_MouseWorldPos); *affine = srcRotated;
else
newPos = m_MouseWorldPos + m_DragHandleOffset;
newAxis = (newPos * scale) - t3;
} }
if (xform == m_FractoriumEmberController->CurrentXform())
m_DragHandlePos = v3T((affine->O() + affine->Y()) * scaleBack, 0);
}, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);//Calling code will update renderer.
}
else
{
v3T diff;
if (GetControl())
diff = SnapToGrid(m_MouseWorldPos + m_DragHandleOffset) - m_MouseDownWorldPos;
else
diff = (m_MouseWorldPos + m_DragHandleOffset) - m_MouseDownWorldPos;
auto origXPlusOff = v3T(m_DragSrcTransform.Y(), 0) + (diff * scale);
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
{
auto affine = pre ? &xform->m_Affine : &xform->m_Post;
auto axis = v3T(m_DragSrcTransforms[index++].Y(), 0) + (diff * scale);
if (GetAlt()) if (GetAlt())
{ affine->Y(v2T(origXPlusOff));//Absolute, not ratio.
if (worldPivotShiftAlt)
result.Y(v2T(newAxis) - m_DragSrcTransform.O());
else else
result.Y(v2T(newAxis)); affine->RotateScaleYTo(v2T(axis));
}
else
{
result.RotateScaleYTo(v2T(newAxis));
}
T scaleBack = m_FractoriumEmberController->AffineScaleCurrentToLocked(); if (xform == m_FractoriumEmberController->CurrentXform())
m_DragHandlePos = v3T((result.O() + result.Y()) * scaleBack, 0); m_DragHandlePos = v3T((affine->O() + affine->Y()) * scaleBack, 0);
return result; }, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);
}
} }
/// <summary> /// <summary>
@ -1350,58 +1346,65 @@ Affine2D<T> GLEmberController<T>::CalcDragYAxis()
/// Control + Shift: Rotate about world center, rotating orientation, snapping to grid. /// Control + Shift: Rotate about world center, rotating orientation, snapping to grid.
/// All others are the same as local pivot. /// All others are the same as local pivot.
/// </summary> /// </summary>
/// <returns>The new affine transform to be assigned to the selected xform</returns>
template <typename T> template <typename T>
Affine2D<T> GLEmberController<T>::CalcDragTranslation() void GLEmberController<T>::CalcDragTranslation()
{ {
v3T newPos; size_t index = 0;
auto scale = m_FractoriumEmberController->AffineScaleLockedToCurrent(); auto scale = m_FractoriumEmberController->AffineScaleLockedToCurrent();
auto result = m_DragSrcTransform; auto scaleBack = m_FractoriumEmberController->AffineScaleCurrentToLocked();
bool worldPivotShift = !m_Fractorium->LocalPivot() && GetShift(); bool worldPivotShift = !m_Fractorium->LocalPivot() && GetShift();
bool pre = m_AffineType == eAffineType::AffinePre;
if (GetShift()) if (GetShift())
{ {
v3T norm = glm::normalize(m_MouseWorldPos); v3T snapped = GetControl() ? SnapToNormalizedAngle(m_MouseWorldPos, 24) : m_MouseWorldPos;
T startAngle = std::atan2(m_DragSrcTransform.O().y, m_DragSrcTransform.O().x);
if (GetControl()) T endAngle = std::atan2(snapped.y, snapped.x);
norm = SnapToNormalizedAngle(norm, 12); T angle = startAngle - endAngle;
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
newPos = glm::length(m_DragSrcTransform.O()) * norm; {
auto affine = pre ? &xform->m_Affine : &xform->m_Post;
auto srcRotated = m_DragSrcTransforms[index++];
srcRotated.RotateTrans(angle);
if (worldPivotShift) if (worldPivotShift)
{ {
T startAngle = atan2(m_DragSrcTransform.O().y, m_DragSrcTransform.O().x); srcRotated.Rotate(angle);
T endAngle = atan2(newPos.y, newPos.x); affine->X(srcRotated.X());
T angle = startAngle - endAngle; affine->Y(srcRotated.Y());
result.Rotate(angle * RAD_2_DEG);
//RotateXformsByAngle
}
}
else
{
if (GetControl())
{
newPos = SnapToGrid(m_MouseWorldPos);
}
else
{
newPos = m_MouseWorldPos + m_DragHandleOffset;
//bool pre = m_AffineType == eAffineType::AffinePre;
//size_t index = 0;
//newPos = m_MouseWorldPos;
//auto diff = m_MouseWorldPos - m_MouseDownWorldPos;
//m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
//{
// auto affine = pre ? &xform->m_Affine : &xform->m_Post;//Determine pre or post affine.
// affine->O(m_DragSrcTransforms[index++].O() + v2T(diff));
//}, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);//Don't need to update render for every xform, just do it once below.
}
} }
T scaleBack = m_FractoriumEmberController->AffineScaleCurrentToLocked(); affine->O(srcRotated.O());
result.O(v2T(newPos * scale));
m_DragHandlePos = newPos; if (xform == m_FractoriumEmberController->CurrentXform())
return result; m_DragHandlePos = v3T(srcRotated.O(), 0) * scaleBack;
}, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);//Calling code will update renderer.
}
else
{
auto diff = m_MouseWorldPos - m_MouseDownWorldPos;
if (GetControl())
{
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
{
auto affine = pre ? &xform->m_Affine : &xform->m_Post;
auto offset = m_DragSrcTransforms[index++].O() + (scale * v2T(diff));
auto snapped = SnapToGrid(offset);
affine->O(v2T(snapped.x, snapped.y));
}, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);
m_DragHandlePos = SnapToGrid(m_MouseWorldPos);
}
else
{
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
{
auto affine = pre ? &xform->m_Affine : &xform->m_Post;
affine->O(m_DragSrcTransforms[index++].O() + (scale * v2T(diff)));
}, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);
m_DragHandlePos = m_MouseWorldPos;
}
}
} }
/// <summary> /// <summary>

View File

@ -62,7 +62,6 @@ protected:
virtual void mouseReleaseEvent(QMouseEvent* e) override; virtual void mouseReleaseEvent(QMouseEvent* e) override;
virtual void mouseMoveEvent(QMouseEvent* e) override; virtual void mouseMoveEvent(QMouseEvent* e) override;
virtual void wheelEvent(QWheelEvent* e) override; virtual void wheelEvent(QWheelEvent* e) override;
//virtual void resizeEvent(QResizeEvent* e) override;
private: private:
void SetDimensions(int w, int h); void SetDimensions(int w, int h);

View File

@ -1,7 +1,7 @@
#include "FractoriumPch.h" #include "FractoriumPch.h"
#include "SpinBox.h" #include "SpinBox.h"
QTimer SpinBox::m_Timer; QTimer SpinBox::s_Timer;
/// <summary> /// <summary>
/// Constructor that passes parent to the base and sets up height and step. /// Constructor that passes parent to the base and sets up height and step.
@ -128,7 +128,6 @@ void SpinBox::OnTimeout()
val = d + (distance * amount * scale); val = d + (distance * amount * scale);
setValue(int(val)); setValue(int(val));
//qDebug() << "Timer on, orig val: " << d << ", new val: " << val << ", distance " << distance; //qDebug() << "Timer on, orig val: " << d << ", new val: " << val << ", distance " << distance;
} }
@ -273,9 +272,9 @@ void SpinBox::leaveEvent(QEvent* e)
/// </summary> /// </summary>
void SpinBox::StartTimer() void SpinBox::StartTimer()
{ {
m_Timer.stop(); s_Timer.stop();
connect(&m_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout())); connect(&s_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout()));
m_Timer.start(300); s_Timer.start(300);
} }
/// <summary> /// <summary>
@ -283,6 +282,6 @@ void SpinBox::StartTimer()
/// </summary> /// </summary>
void SpinBox::StopTimer() void SpinBox::StopTimer()
{ {
m_Timer.stop(); s_Timer.stop();
disconnect(&m_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout())); disconnect(&s_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout()));
} }

View File

@ -48,5 +48,5 @@ private:
int m_SmallStep; int m_SmallStep;
QPoint m_MouseDownPoint; QPoint m_MouseDownPoint;
QPoint m_MouseMovePoint; QPoint m_MouseMovePoint;
static QTimer m_Timer; static QTimer s_Timer;
}; };

View File

@ -53,25 +53,21 @@ private:
bool operator < (const QTreeWidgetItem& other) const bool operator < (const QTreeWidgetItem& other) const
{ {
int column = treeWidget()->sortColumn(); int column = treeWidget()->sortColumn();
eVariationId index1, index2;
double weight1 = 0, weight2 = 0;
VariationTreeWidgetItem* varItemWidget;
VariationTreeDoubleSpinBox* spinBox1, *spinBox2;
auto itemWidget1 = treeWidget()->itemWidget(const_cast<VariationTreeWidgetItem*>(this), 1);//Get the widget for the second column. auto itemWidget1 = treeWidget()->itemWidget(const_cast<VariationTreeWidgetItem*>(this), 1);//Get the widget for the second column.
if ((spinBox1 = dynamic_cast<VariationTreeDoubleSpinBox*>(itemWidget1)))//Cast the widget to the VariationTreeDoubleSpinBox type. if (auto spinBox1 = dynamic_cast<VariationTreeDoubleSpinBox*>(itemWidget1))//Cast the widget to the VariationTreeDoubleSpinBox type.
{ {
auto itemWidget2 = treeWidget()->itemWidget(const_cast<QTreeWidgetItem*>(&other), 1);//Get the widget for the second column of the widget item passed in. auto itemWidget2 = treeWidget()->itemWidget(const_cast<QTreeWidgetItem*>(&other), 1);//Get the widget for the second column of the widget item passed in.
if ((spinBox2 = dynamic_cast<VariationTreeDoubleSpinBox*>(itemWidget2)))//Cast the widget to the VariationTreeDoubleSpinBox type. if (auto spinBox2 = dynamic_cast<VariationTreeDoubleSpinBox*>(itemWidget2))//Cast the widget to the VariationTreeDoubleSpinBox type.
{ {
if (spinBox1->IsParam() || spinBox2->IsParam())//Do not sort params, their order will always remain the same. if (spinBox1->IsParam() || spinBox2->IsParam())//Do not sort params, their order will always remain the same.
return false; return false;
weight1 = spinBox1->value(); auto weight1 = spinBox1->value();
weight2 = spinBox2->value(); auto weight2 = spinBox2->value();
index1 = spinBox1->GetVariationId(); auto index1 = spinBox1->GetVariationId();
index2 = spinBox2->GetVariationId(); auto index2 = spinBox2->GetVariationId();
if (column == 0)//First column clicked, sort by variation index. if (column == 0)//First column clicked, sort by variation index.
{ {