#pragma once
#include "Utils.h"
#include "Isaac.h"
#include "Curves.h"
#define CURVE_POINTS 5
///
/// Curves class.
///
namespace EmberNs
{
///
/// The b-spline curves used to adjust the colors during final accumulation.
/// This functionality was gotten inferred from Chaotica.
/// Note this is now incompatible with Apophysis, which uses Bezier curves instead.
///
template
class EMBER_API Curves
{
public:
///
/// Constructor which sets the curve and weight values to their defaults.
///
Curves(bool init = false)
{
if (init)
Init();
else
Clear();
}
///
/// Default copy constructor.
///
/// The Curves object to copy
Curves(const Curves& curves)
{
Curves::operator=(curves);
}
///
/// Copy constructor to copy a Curves object of type U.
/// Special case that must be here in the header because it has
/// a second template parameter.
///
/// The Curves object to copy
template
Curves(const Curves& curves)
{
Curves::operator=(curves);
}
///
/// Default assignment operator.
///
/// The Curves object to copy
Curves& operator = (const Curves& curves)
{
if (this != &curves)
Curves::operator=(curves);
return *this;
}
///
/// Assignment operator to assign a Curves object of type U.
///
/// The Curves object to copy
/// Reference to updated self
template
Curves& operator = (const Curves& curves)
{
int i = 0;
for (auto& pp : curves.m_Points)
{
int j = 0;
m_Points[i].clear();
for (auto& p : pp)
{
m_Points[i].push_back(p);
j++;
}
i++;
}
i = 0;
return *this;
}
///
/// Unary addition operator to add a Curves object to this one.
///
/// The Curves object to add
/// Reference to updated self
template
Curves& operator += (const Curves& curves)
{
int i = 0;
for (auto& pp : m_Points)
{
int j = 0;
for (auto& p : pp)
{
if (j < curves.m_Points[i].size())
p += curves.m_Points[i][j];
else
break;
j++;
}
i++;
}
return *this;
}
///
/// Unary multiplication operator to multiply this object by another Curves object.
///
/// The Curves object to multiply this one by
/// Reference to updated self
template
Curves& operator *= (const Curves& curves)
{
int i = 0;
for (auto& pp : m_Points)
{
int j = 0;
for (auto& p : pp)
{
if (j < curves.m_Points[i].size())
p *= curves.m_Points[i][j];
else
break;
j++;
}
i++;
}
return *this;
}
///
/// Unary multiplication operator to multiply this object by a scalar of type T.
///
/// The scalar to multiply this object by
/// Reference to updated self
template
Curves& operator *= (const U& t)
{
for (auto& pp : m_Points)
for (auto& p : pp)
p *= T(t);
return *this;
}
///
/// Set the curve and weight values to their default state.
///
void Init()
{
for (size_t i = 0; i < 4; i++)
Init(i);
}
///
/// Set a specific curve and its weight value to their default state.
///
void Init(size_t i)
{
if (i < 4)
{
m_Points[i].resize(5);
m_Points[i][0] = v2T{ 0 };
m_Points[i][1] = v2T{ static_cast(0.25) };
m_Points[i][2] = v2T{ static_cast(0.50) };
m_Points[i][3] = v2T{ static_cast(0.75) };
m_Points[i][4] = v2T{ 1 };
}
}
///
/// Set the curve and weight values to an empty state.
///
void Clear()
{
for (auto& p : m_Points)
p.clear();
}
///
/// Whether any points are not the default.
///
/// True if any point has been set to a value other than the default, else false.
bool CurvesSet()
{
bool set = false;
for (size_t i = 0; i < 4; i++)
{
if (m_Points[i].size() != CURVE_POINTS)
{
set = true;
break;
}
if ((m_Points[i][0] != v2T(0)) ||
(m_Points[i][1] != v2T(static_cast(0.25))) ||
(m_Points[i][2] != v2T(static_cast(0.50))) ||
(m_Points[i][3] != v2T(static_cast(0.75))) ||
(m_Points[i][4] != v2T(1))
)
{
set = true;
break;
}
}
return set;
}
public:
std::array, 4> m_Points;
};
//Must declare this outside of the class to provide for both orders of parameters.
///
/// Multiplication operator to multiply a Curves object by a scalar of type U.
///
/// The curves object to multiply
/// The scalar to multiply curves by by
/// Copy of new Curves
template
Curves operator * (const Curves& curves, const U& t)
{
T tt = T(t);
Curves c(curves);
for (auto& pp : c.m_Points)
for (auto& p : pp)
p *= tt;
return c;
}
///
/// Multiplication operator for reverse order.
///
/// The scalar to multiply curves by by
/// The curves object to multiply
/// Copy of new Curves
template
Curves operator * (const U& t, const Curves& curves)
{
return curves * t;
}
}