mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-06-30 21:36:33 -04:00
--User changes
-No longer constrain pitch, yaw or depth spinners to -180 - 180. --Bug fixes -Properly set color index on padded xforms. -Adding a padding final xform included a linear variation with a weight of zero to not appear empty. Made it have a weight of 1. -Always write animate tag on final xform when saving to Xml. -Motion was being applied to the wrong flame in SheepTools::Edge(), so apply it to the correct one. -Prevent divide by zero when normalizing variation weights. -Was accidentally adding the placeholder value of -9999 for motion_offset to varation weights and parameters when applying motion. Set to zero if no value present. -Clamp flame rotation values to -180 - 180 when reading a flame from Xml. -Events were not properly wired for user changes in the random rotations per blend controls in the sequencer. -Fix major UI bugs with sequencer min/max random controls which made it nearly impossible to hand type values. -Values from rotations per blend and rotations per blend max were not being saved to file between program runs. -Checking animate for an xform was not applied to all flames even if Apply All was checked. -Changing interpolation type, temporal filter width, temporal type, and affine interpolation type were not actually saving to the flame when changed. -Grid on the main window was not being drawn at the right scale initially due to some OpenGL initialization occurring in the wrong order. -Severe bugs in sequence generation code: --Improperly detected padding xforms. --When looking for specific variations during xform aligning, only presence was detected, when it should have been presence plus a weight greater than zero. --When adding specific variations during xform aligning, must first remove any variations of that type. --Two variables were unsigned when they should have been signed. This prevented large blocks of code from ever executing. --When interpolating affines, an EPS that was too small was used, causing affine values to interpolate incorrectly. Instead use 1e-10 to ensure results equal to flam3. --Code changes -Modify FractoriumEmberController::UpdateXform() to pass the selected xform index as well as the absolute index to func().
This commit is contained in:
@ -211,9 +211,12 @@ public:
|
||||
/// <param name="count">The number of xforms to add</param>
|
||||
void AddXforms(size_t count)
|
||||
{
|
||||
auto oldsize = m_Xforms.size();
|
||||
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
Xform<T> xform;
|
||||
xform.m_ColorX = T((oldsize + i) & 1);
|
||||
xform.AddVariation(m_VariationList->GetVariationCopy(eVariationId::VAR_LINEAR));
|
||||
AddXform(xform);
|
||||
}
|
||||
@ -266,15 +269,18 @@ public:
|
||||
if (UseFinalXform())//Caller wanted one and this ember has one.
|
||||
{
|
||||
ember.m_FinalXform = m_FinalXform;
|
||||
ember.m_FinalXform.m_ColorX = T(XformCount() & 1);
|
||||
}
|
||||
else//Caller wanted one and this ember doesn't have one.
|
||||
{
|
||||
//Interpolated-against final xforms need animate & color speed set to 0 and motion elements cleared.
|
||||
ember.m_FinalXform.m_Affine.MakeID();
|
||||
ember.m_FinalXform.m_Post.MakeID();
|
||||
ember.m_FinalXform.m_Animate = 0;
|
||||
ember.m_FinalXform.m_ColorSpeed = 0;
|
||||
ember.m_FinalXform.m_Motion.clear();
|
||||
ember.m_FinalXform.ClearAndDeleteVariations();
|
||||
ember.m_FinalXform.AddVariation(m_VariationList->GetVariationCopy(eVariationId::VAR_LINEAR, 0));//Do this so it doesn't appear empty.
|
||||
ember.m_FinalXform.AddVariation(m_VariationList->GetVariationCopy(eVariationId::VAR_LINEAR));//Do this so it doesn't appear empty.
|
||||
}
|
||||
}
|
||||
|
||||
@ -798,6 +804,9 @@ public:
|
||||
{
|
||||
auto thisXform = GetTotalXform(i);
|
||||
|
||||
//if (i == 10)
|
||||
// cout << i << endl;
|
||||
|
||||
if (size == 2 && stagger > 0 && thisXform != &m_FinalXform)
|
||||
{
|
||||
coefSave[0] = coefs[0];
|
||||
|
@ -37,7 +37,7 @@ static void sincos(float x, float* s, float* c)
|
||||
|
||||
namespace EmberNs
|
||||
{
|
||||
#define EMBER_VERSION "1.0.0.9"
|
||||
#define EMBER_VERSION "1.0.0.10"
|
||||
#define EPS6 T(1e-6)
|
||||
#define EPS std::numeric_limits<T>::epsilon()//Apoplugin.h uses -20, but it's more mathematically correct to do it this way.
|
||||
#define ISAAC_SIZE 4
|
||||
|
@ -508,9 +508,7 @@ string EmberToXml<T>::ToString(Xform<T>& xform, size_t xformCount, bool isFinal,
|
||||
string s = xform.m_Name;
|
||||
std::replace(s.begin(), s.end(), ' ', '_');
|
||||
os << "name=\"" << s << "\" ";//Flam3 didn't do this, but Apo does.
|
||||
|
||||
if (!isFinal)
|
||||
os << "animate=\"" << xform.m_Animate << "\" ";
|
||||
os << "animate=\"" << xform.m_Animate << "\" ";//Flam3 only did this for non-final. Ember supports animating final.
|
||||
}
|
||||
|
||||
//Variation writing order differs slightly from the original to make it a bit more readable.
|
||||
|
@ -24,6 +24,25 @@ template <typename T>
|
||||
class EMBER_API Interpolater
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Determine if the xform at a given index in an ember is a padding xform.
|
||||
/// </summary>
|
||||
/// <param name="ember">The ember whose xforms will be examined for padding</param>
|
||||
/// <param name="xf">The index of the ember to examine</param>
|
||||
/// <param name="isFinal">Whether the xform being examined is the final one</param>
|
||||
/// <returns>True the xform at index xf is a padding one, else false.</returns>
|
||||
static bool IsPadding(const Ember<T>& ember, size_t xf, bool isFinal)
|
||||
{
|
||||
if (!isFinal)//Either a final wasn't present in any ember, or if there was, this xform is a normal one, so do not include final in the index check.
|
||||
{
|
||||
return xf >= ember.XformCount();
|
||||
}
|
||||
else//There was a final present, and we are checking it, so just see if its presence differs.
|
||||
{
|
||||
return !ember.UseFinalXform();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aligns the specified array of embers and stores in the output array.
|
||||
/// This is used to prepare embers before interpolating them.
|
||||
@ -41,7 +60,7 @@ public:
|
||||
static void Align(const Ember<T>* sourceEmbers, Ember<T>* destEmbers, size_t count)
|
||||
{
|
||||
bool aligned = true;
|
||||
bool currentFinal, final = sourceEmbers[0].UseFinalXform();
|
||||
bool currentFinal, hasFinal = sourceEmbers[0].UseFinalXform();
|
||||
size_t i, xf, currentCount, maxCount = sourceEmbers[0].XformCount();
|
||||
Xform<T>* destOtherXform;
|
||||
auto variationList = VariationList<T>::Instance();
|
||||
@ -62,18 +81,18 @@ public:
|
||||
|
||||
currentFinal = sourceEmbers[i].UseFinalXform();
|
||||
|
||||
if (final != currentFinal)//Check if any used final.
|
||||
if (hasFinal != currentFinal)//Check if any used final.
|
||||
{
|
||||
aligned = false;
|
||||
final |= currentFinal;
|
||||
hasFinal |= currentFinal;
|
||||
}
|
||||
}
|
||||
|
||||
//Copy them using the max xform count, and do final if any had final.
|
||||
for (i = 0; i < count; i++)
|
||||
destEmbers[i] = sourceEmbers[i].Copy(maxCount, final);
|
||||
destEmbers[i] = sourceEmbers[i].Copy(maxCount, hasFinal);
|
||||
|
||||
if (final)
|
||||
if (hasFinal)
|
||||
maxCount++;
|
||||
|
||||
//Check to see if there's a parametric variation present in one xform
|
||||
@ -82,11 +101,13 @@ public:
|
||||
//All embers will have the same number of xforms at this point.
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
size_t ii;
|
||||
intmax_t ii;
|
||||
|
||||
for (xf = 0; xf < maxCount; xf++)//This will include both normal xforms and the final.
|
||||
{
|
||||
auto destXform = destEmbers[i].GetTotalXform(xf, final);
|
||||
bool isFinal = hasFinal && (xf == maxCount - 1);
|
||||
auto destXform = destEmbers[i].GetTotalXform(xf, hasFinal);
|
||||
Variation<T>* dummyvar = nullptr;
|
||||
|
||||
//Ensure every parametric variation contained in every xform at either position i - 1 or i + 1 is also contained in the dest xform.
|
||||
if (i > 0)
|
||||
@ -104,9 +125,9 @@ public:
|
||||
//rings2, fan2, blob, perspective, julian, juliascope, ngon, curl, super_shape, split
|
||||
//If so, can use a better starting point for these.
|
||||
//If the current xform index is greater than what the original xform count was for this ember, then it's a padding xform.
|
||||
if (xf >= sourceEmbers[i].TotalXformCount() && !aligned)
|
||||
if (IsPadding(sourceEmbers[i], xf, isFinal) && !aligned)
|
||||
{
|
||||
size_t found = 0;
|
||||
intmax_t found = 0;
|
||||
//Remove linear.
|
||||
destXform->DeleteVariationById(eVariationId::VAR_LINEAR);
|
||||
|
||||
@ -121,32 +142,36 @@ public:
|
||||
continue;
|
||||
|
||||
//Skip if this is also padding.
|
||||
if (xf >= sourceEmbers[i + ii].TotalXformCount())
|
||||
if (IsPadding(sourceEmbers[i + ii], xf, isFinal))
|
||||
continue;
|
||||
|
||||
destOtherXform = destEmbers[i + ii].GetTotalXform(xf);
|
||||
|
||||
//Spherical / Ngon (trumps all others due to holes)
|
||||
//Interpolate these against a 180 degree rotated identity
|
||||
//with weight -1.
|
||||
//Added JULIAN/JULIASCOPE to get rid of black wedges.
|
||||
if (destOtherXform->GetVariationById(eVariationId::VAR_SPHERICAL) ||
|
||||
destOtherXform->GetVariationById(eVariationId::VAR_NGON) ||
|
||||
destOtherXform->GetVariationById(eVariationId::VAR_JULIAN) ||
|
||||
destOtherXform->GetVariationById(eVariationId::VAR_JULIASCOPE) ||
|
||||
destOtherXform->GetVariationById(eVariationId::VAR_POLAR) ||
|
||||
destOtherXform->GetVariationById(eVariationId::VAR_WEDGE_SPH) ||
|
||||
destOtherXform->GetVariationById(eVariationId::VAR_WEDGE_JULIA))
|
||||
if (destOtherXform = destEmbers[i + ii].GetTotalXform(xf))
|
||||
{
|
||||
destXform->AddVariation(variationList->GetVariationCopy(eVariationId::VAR_LINEAR, -1));
|
||||
//Set the coefs appropriately.
|
||||
destXform->m_Affine.A(-1);
|
||||
destXform->m_Affine.D(0);
|
||||
destXform->m_Affine.B(0);
|
||||
destXform->m_Affine.E(-1);
|
||||
destXform->m_Affine.C(0);
|
||||
destXform->m_Affine.F(0);
|
||||
found = -1;
|
||||
//Spherical / Ngon (trumps all others due to holes)
|
||||
//Interpolate these against a 180 degree rotated identity
|
||||
//with weight -1.
|
||||
//Added JULIAN/JULIASCOPE to get rid of black wedges.
|
||||
|
||||
//Testing for variation weight > 0 is to make the behavior match flam3 exactly, even though that doesn't really make sense in the modern era
|
||||
//Because variations can use negative weights.
|
||||
if (((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_SPHERICAL) ) && dummyvar->m_Weight > 0) ||
|
||||
((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_NGON) ) && dummyvar->m_Weight > 0) ||
|
||||
((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_JULIAN) ) && dummyvar->m_Weight > 0) ||
|
||||
((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_JULIASCOPE) ) && dummyvar->m_Weight > 0) ||
|
||||
((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_POLAR) ) && dummyvar->m_Weight > 0) ||
|
||||
((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_WEDGE_SPH) ) && dummyvar->m_Weight > 0) ||
|
||||
((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_WEDGE_JULIA)) && dummyvar->m_Weight > 0))
|
||||
{
|
||||
destXform->AddVariation(variationList->GetVariationCopy(eVariationId::VAR_LINEAR, -1));
|
||||
//Set the coefs appropriately.
|
||||
destXform->m_Affine.A(-1);
|
||||
destXform->m_Affine.D(0);
|
||||
destXform->m_Affine.B(0);
|
||||
destXform->m_Affine.E(-1);
|
||||
destXform->m_Affine.C(0);
|
||||
destXform->m_Affine.F(0);
|
||||
found = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -160,79 +185,110 @@ public:
|
||||
continue;
|
||||
|
||||
//Skip if this is also padding.
|
||||
if (xf >= sourceEmbers[i + ii].TotalXformCount())
|
||||
if (IsPadding(sourceEmbers[i + ii], xf, isFinal))
|
||||
continue;
|
||||
|
||||
destOtherXform = destEmbers[i + ii].GetTotalXform(xf);
|
||||
|
||||
if (destOtherXform->GetVariationById(eVariationId::VAR_RECTANGLES))
|
||||
if (destOtherXform = destEmbers[i + ii].GetTotalXform(xf))
|
||||
{
|
||||
if (auto var = variationList->GetParametricVariationCopy(eVariationId::VAR_RECTANGLES))
|
||||
if ((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_RECTANGLES)) && dummyvar->m_Weight > 0)
|
||||
{
|
||||
var->SetParamVal("rectangles_x", 0);
|
||||
var->SetParamVal("rectangles_y", 0);
|
||||
destXform->AddVariation(var);
|
||||
destXform->DeleteVariationById(eVariationId::VAR_RECTANGLES);//In case it was there, remove it first so the add below succeeds.
|
||||
|
||||
if (auto var = variationList->GetParametricVariationCopy(eVariationId::VAR_RECTANGLES))
|
||||
{
|
||||
var->SetParamVal("rectangles_x", 0);
|
||||
var->SetParamVal("rectangles_y", 0);
|
||||
|
||||
if (!destXform->AddVariation(var))
|
||||
delete var;
|
||||
}
|
||||
|
||||
found++;
|
||||
}
|
||||
|
||||
found++;
|
||||
}
|
||||
|
||||
if (destOtherXform->GetVariationById(eVariationId::VAR_RINGS2))
|
||||
{
|
||||
if (auto var = variationList->GetParametricVariationCopy(eVariationId::VAR_RINGS2))
|
||||
if ((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_RINGS2)) && dummyvar->m_Weight > 0)
|
||||
{
|
||||
var->SetParamVal("rings2_val", 0);
|
||||
destXform->AddVariation(var);
|
||||
destXform->DeleteVariationById(eVariationId::VAR_RINGS2);
|
||||
|
||||
if (auto var = variationList->GetParametricVariationCopy(eVariationId::VAR_RINGS2))
|
||||
{
|
||||
var->SetParamVal("rings2_val", 0);
|
||||
|
||||
if (!destXform->AddVariation(var))
|
||||
delete var;
|
||||
}
|
||||
|
||||
found++;
|
||||
}
|
||||
|
||||
found++;
|
||||
}
|
||||
|
||||
if (destOtherXform->GetVariationById(eVariationId::VAR_FAN2))
|
||||
{
|
||||
destXform->AddVariation(variationList->GetVariationCopy(eVariationId::VAR_FAN2));
|
||||
found++;
|
||||
}
|
||||
|
||||
if (destOtherXform->GetVariationById(eVariationId::VAR_BLOB))
|
||||
{
|
||||
if (auto var = variationList->GetParametricVariationCopy(eVariationId::VAR_BLOB))
|
||||
if ((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_FAN2)) && dummyvar->m_Weight > 0)
|
||||
{
|
||||
var->SetParamVal("blob_low", 1);
|
||||
destXform->AddVariation(var);
|
||||
destXform->DeleteVariationById(eVariationId::VAR_FAN2);
|
||||
|
||||
if (auto var = variationList->GetVariationCopy(eVariationId::VAR_FAN2))
|
||||
if (!destXform->AddVariation(var))
|
||||
delete var;
|
||||
|
||||
found++;
|
||||
}
|
||||
|
||||
found++;
|
||||
}
|
||||
|
||||
if (destOtherXform->GetVariationById(eVariationId::VAR_PERSPECTIVE))
|
||||
{
|
||||
destXform->AddVariation(variationList->GetVariationCopy(eVariationId::VAR_PERSPECTIVE));
|
||||
found++;
|
||||
}
|
||||
|
||||
if (destOtherXform->GetVariationById(eVariationId::VAR_CURL))
|
||||
{
|
||||
if (auto var = variationList->GetParametricVariationCopy(eVariationId::VAR_CURL))
|
||||
if ((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_BLOB)) && dummyvar->m_Weight > 0)
|
||||
{
|
||||
var->SetParamVal("curl_c1", 0);
|
||||
destXform->AddVariation(var);
|
||||
destXform->DeleteVariationById(eVariationId::VAR_BLOB);
|
||||
|
||||
if (auto var = variationList->GetParametricVariationCopy(eVariationId::VAR_BLOB))
|
||||
{
|
||||
var->SetParamVal("blob_low", 1);
|
||||
|
||||
if (!destXform->AddVariation(var))
|
||||
delete var;
|
||||
}
|
||||
|
||||
found++;
|
||||
}
|
||||
|
||||
found++;
|
||||
}
|
||||
|
||||
if (destOtherXform->GetVariationById(eVariationId::VAR_SUPER_SHAPE))
|
||||
{
|
||||
if (auto var = variationList->GetParametricVariationCopy(eVariationId::VAR_SUPER_SHAPE))
|
||||
if ((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_PERSPECTIVE)) && dummyvar->m_Weight > 0)
|
||||
{
|
||||
var->SetParamVal("super_shape_n1", 2);
|
||||
var->SetParamVal("super_shape_n2", 2);
|
||||
var->SetParamVal("super_shape_n3", 2);
|
||||
destXform->AddVariation(var);
|
||||
destXform->DeleteVariationById(eVariationId::VAR_PERSPECTIVE);
|
||||
|
||||
if (auto var = variationList->GetVariationCopy(eVariationId::VAR_PERSPECTIVE))
|
||||
if (!destXform->AddVariation(var))
|
||||
delete var;
|
||||
|
||||
found++;
|
||||
}
|
||||
|
||||
found++;
|
||||
if ((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_CURL)) && dummyvar->m_Weight > 0)
|
||||
{
|
||||
destXform->DeleteVariationById(eVariationId::VAR_CURL);
|
||||
|
||||
if (auto var = variationList->GetParametricVariationCopy(eVariationId::VAR_CURL))
|
||||
{
|
||||
var->SetParamVal("curl_c1", 0);
|
||||
|
||||
if (!destXform->AddVariation(var))
|
||||
delete var;
|
||||
}
|
||||
|
||||
found++;
|
||||
}
|
||||
|
||||
if ((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_SUPER_SHAPE)) && dummyvar->m_Weight > 0)
|
||||
{
|
||||
destXform->DeleteVariationById(eVariationId::VAR_SUPER_SHAPE);
|
||||
|
||||
if (auto var = variationList->GetParametricVariationCopy(eVariationId::VAR_SUPER_SHAPE))
|
||||
{
|
||||
var->SetParamVal("super_shape_n1", 2);
|
||||
var->SetParamVal("super_shape_n2", 2);
|
||||
var->SetParamVal("super_shape_n3", 2);
|
||||
|
||||
if (!destXform->AddVariation(var))
|
||||
delete var;
|
||||
}
|
||||
|
||||
found++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -247,25 +303,36 @@ public:
|
||||
continue;
|
||||
|
||||
//Skip if this is also padding.
|
||||
if (xf >= sourceEmbers[i + ii].TotalXformCount())
|
||||
if (IsPadding(sourceEmbers[i + ii], xf, isFinal))
|
||||
continue;
|
||||
|
||||
destOtherXform = destEmbers[i + ii].GetTotalXform(xf);
|
||||
|
||||
if (destOtherXform->GetVariationById(eVariationId::VAR_FAN))
|
||||
if (destOtherXform = destEmbers[i + ii].GetTotalXform(xf))
|
||||
{
|
||||
destXform->AddVariation(variationList->GetVariationCopy(eVariationId::VAR_FAN));
|
||||
found++;
|
||||
}
|
||||
if ((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_FAN)) && dummyvar->m_Weight > 0)
|
||||
{
|
||||
destXform->DeleteVariationById(eVariationId::VAR_FAN);
|
||||
|
||||
if (destOtherXform->GetVariationById(eVariationId::VAR_RINGS))
|
||||
{
|
||||
destXform->AddVariation(variationList->GetVariationCopy(eVariationId::VAR_RINGS));
|
||||
found++;
|
||||
if (auto var = variationList->GetVariationCopy(eVariationId::VAR_FAN))
|
||||
if (!destXform->AddVariation(var))
|
||||
delete var;
|
||||
|
||||
found++;
|
||||
}
|
||||
|
||||
if ((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_RINGS)) && dummyvar->m_Weight > 0)
|
||||
{
|
||||
destXform->DeleteVariationById(eVariationId::VAR_RINGS);
|
||||
|
||||
if (auto var = variationList->GetVariationCopy(eVariationId::VAR_RINGS))
|
||||
if (!destXform->AddVariation(var))
|
||||
delete var;
|
||||
|
||||
found++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found > 0)
|
||||
if (destXform && (found > 0))
|
||||
{
|
||||
//Set the coefs appropriately.
|
||||
destXform->m_Affine.A(0);
|
||||
@ -278,14 +345,20 @@ public:
|
||||
}
|
||||
|
||||
//If there still are no matches, switch back to linear.
|
||||
if (found == 0)
|
||||
if (destXform)
|
||||
{
|
||||
destXform->AddVariation(variationList->GetVariationCopy(eVariationId::VAR_LINEAR));
|
||||
}
|
||||
else if (found > 0)
|
||||
{
|
||||
//Otherwise, normalize the weights.
|
||||
destXform->NormalizeVariationWeights();
|
||||
if (found == 0)
|
||||
{
|
||||
destXform->DeleteVariationById(eVariationId::VAR_LINEAR);
|
||||
|
||||
if (auto var = variationList->GetVariationCopy(eVariationId::VAR_LINEAR))
|
||||
if (!destXform->AddVariation(var))
|
||||
delete var;
|
||||
}
|
||||
else if (found > 0)
|
||||
{
|
||||
destXform->NormalizeVariationWeights();//Otherwise, normalize the weights.
|
||||
}
|
||||
}
|
||||
}
|
||||
}//Xforms.
|
||||
@ -448,6 +521,8 @@ public:
|
||||
Align(&embers[i1 - 1], &m_Embers[0], 4);//Should really be doing some sort of checking here to ensure the ember vectors have 4 elements.
|
||||
smoothFlag = true;
|
||||
}
|
||||
|
||||
//smoothFlag = true;
|
||||
}
|
||||
|
||||
result.m_Time = time;
|
||||
@ -602,6 +677,8 @@ public:
|
||||
/// <param name="cxTrn">The vec2 vector to store the polar translation values</param>
|
||||
static void ConvertLinearToPolar(const Ember<T>* embers, size_t size, size_t xfi, size_t cflag, vector<v2T>& cxAng, vector<v2T>& cxMag, vector<v2T>& cxTrn)
|
||||
{
|
||||
const auto LOCALEPS = T(1e-10);//Even though EPS is defined elsewhere, need this here for full compatibility with flam3.
|
||||
|
||||
if (size == cxAng.size() &&
|
||||
size == cxMag.size() &&
|
||||
size == cxTrn.size())
|
||||
@ -687,9 +764,9 @@ public:
|
||||
d = cxAng[k][col] - cxAng[k - 1][col];
|
||||
|
||||
//Adjust to avoid the -pi/pi discontinuity.
|
||||
if (d > M_PI + EPS)
|
||||
if (d > M_PI + LOCALEPS)
|
||||
cxAng[k][col] -= M_2PI;
|
||||
else if (d < -(M_PI - EPS))//Forces clockwise rotation at 180.
|
||||
else if (d < -(M_PI - LOCALEPS))//Forces clockwise rotation at 180.
|
||||
cxAng[k][col] += M_2PI;
|
||||
}
|
||||
}
|
||||
@ -709,6 +786,7 @@ public:
|
||||
/// <param name="count">The size of the embers array</param>
|
||||
static void AsymmetricRefAngles(Ember<T>* embers, size_t count)
|
||||
{
|
||||
const auto LOCALEPS = T(1e-10);//Even though EPS is defined elsewhere, need this here for full compatibility with flam3.
|
||||
size_t k, xfi;
|
||||
T cxang[4][2], c1[2], d;
|
||||
|
||||
@ -734,9 +812,9 @@ public:
|
||||
d = cxang[k][col] - cxang[k - 1][col];
|
||||
|
||||
//Adjust to avoid the -pi/pi discontinuity.
|
||||
if (d > T(M_PI + EPS))
|
||||
if (d > T(M_PI + LOCALEPS))
|
||||
cxang[k][col] -= 2 * T(M_PI);
|
||||
else if (d < -T(M_PI - EPS) )
|
||||
else if (d < -T(M_PI - LOCALEPS))
|
||||
cxang[k][col] += 2 * T(M_PI);
|
||||
|
||||
//If this is an asymmetric case, store the NON-symmetric angle
|
||||
|
@ -995,12 +995,13 @@ public:
|
||||
{
|
||||
m_EdgePrealign[si] = embers[si];
|
||||
|
||||
for (i = 0; i < embers[si].TotalXformCount(); i++)
|
||||
for (i = 0; i < m_EdgePrealign[si].TotalXformCount(); i++)
|
||||
{
|
||||
auto xform = embers[si].GetTotalXform(i);
|
||||
auto prealignxform = m_EdgePrealign[si].GetTotalXform(i);
|
||||
|
||||
if (!xform->m_Motion.empty())
|
||||
xform->ApplyMotion(*(m_EdgePrealign[si].GetTotalXform(i)), blend);//Apply motion parameters to result.xform[i] using blend parameter.
|
||||
prealignxform->ApplyMotion(*xform, blend);//Apply motion parameters to result.xform[i] using blend parameter.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -574,7 +574,7 @@ public:
|
||||
|
||||
for (auto var : variations) norm += var->m_Weight;
|
||||
|
||||
for (auto var : variations) var->m_Weight /= norm;
|
||||
for (auto var : variations) var->m_Weight /= Zeps(norm);//Ensure a divide by zero never happens.
|
||||
});
|
||||
}
|
||||
|
||||
@ -708,10 +708,11 @@ public:
|
||||
for (size_t i = 0; i < xform.m_Motion.size(); i++)
|
||||
{
|
||||
//Original only pulls these from the first motion xform which is a bug. Want to pull it from each one.
|
||||
Xform<T>& currentMot = xform.m_Motion[i];
|
||||
T freq = currentMot.m_MotionFreq;
|
||||
eMotion func = currentMot.m_MotionFunc;
|
||||
T offset = currentMot.m_MotionOffset;
|
||||
auto& currentMot = xform.m_Motion[i];
|
||||
auto freq = currentMot.m_MotionFreq;
|
||||
auto func = currentMot.m_MotionFunc;
|
||||
auto offset = currentMot.m_MotionOffset;
|
||||
auto cleanOffset = offset != EMPTYFIELD ? offset : 0;
|
||||
//Clamp these to the appropriate range after all are applied.
|
||||
APPMOT(m_Weight);
|
||||
APPMOT(m_ColorX);
|
||||
@ -730,13 +731,13 @@ public:
|
||||
if (!var)//It wasn't present, so add it and set the weight.
|
||||
{
|
||||
Variation<T>* newVar = motVar->Copy();
|
||||
newVar->m_Weight = motVar->m_Weight * Interpolater<T>::MotionFuncs(func, freq * (blend + offset));
|
||||
newVar->m_Weight = motVar->m_Weight * Interpolater<T>::MotionFuncs(func, freq * (blend + cleanOffset));
|
||||
AddVariation(newVar);
|
||||
var = newVar;//Use this below for params.
|
||||
}
|
||||
else//It was present, so apply the motion func to the weight.
|
||||
{
|
||||
var->m_Weight += motVar->m_Weight * Interpolater<T>::MotionFuncs(func, freq * (blend + offset));
|
||||
var->m_Weight += motVar->m_Weight * Interpolater<T>::MotionFuncs(func, freq * (blend + cleanOffset));
|
||||
}
|
||||
|
||||
//At this point, we've added if needed, or just applied the motion func to the weight.
|
||||
@ -750,7 +751,7 @@ public:
|
||||
for (size_t k = 0; k < motParVar->ParamCount(); k++)
|
||||
{
|
||||
if (!motParams[k].IsPrecalc())
|
||||
*(params[k].Param()) += motParams[k].ParamVal() * Interpolater<T>::MotionFuncs(func, freq * (blend + offset));
|
||||
*(params[k].Param()) += motParams[k].ParamVal() * Interpolater<T>::MotionFuncs(func, freq * (blend + cleanOffset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -547,7 +547,7 @@ bool XmlToEmber<T>::ParseEmberElement(xmlNode* emberNode, Ember<T>& currentEmber
|
||||
//First parse out simple float reads.
|
||||
if (ParseAndAssign(curAtt->name, attStr, "time", currentEmber.m_Time, ret)) {}
|
||||
else if (ParseAndAssign(curAtt->name, attStr, "scale", currentEmber.m_PixelsPerUnit, ret)) { currentEmber.m_OrigPixPerUnit = currentEmber.m_PixelsPerUnit; }
|
||||
else if (ParseAndAssign(curAtt->name, attStr, "rotate", currentEmber.m_Rotate, ret)) {}
|
||||
else if (ParseAndAssign(curAtt->name, attStr, "rotate", currentEmber.m_Rotate, ret)) { currentEmber.m_Rotate = NormalizeDeg180<T>(currentEmber.m_Rotate); }
|
||||
else if (ParseAndAssign(curAtt->name, attStr, "zoom", currentEmber.m_Zoom, ret)) { ClampGteRef<T>(currentEmber.m_Zoom, 0); }
|
||||
else if (ParseAndAssign(curAtt->name, attStr, "cam_zoom", currentEmber.m_Zoom, ret)) { ClampGteRef<T>(currentEmber.m_Zoom, 0); }//JWildfire uses cam_zoom.
|
||||
else if (ParseAndAssign(curAtt->name, attStr, "filter", currentEmber.m_SpatialFilterRadius, ret)) {}
|
||||
@ -884,6 +884,7 @@ bool XmlToEmber<T>::ParseEmberElement(xmlNode* emberNode, Ember<T>& currentEmber
|
||||
if (!Compare(childNode->name, "finalxform"))
|
||||
{
|
||||
Xform<T> finalXform;
|
||||
finalXform.m_Animate = 0;//Do not animate final by default.
|
||||
|
||||
if (!ParseXform(childNode, finalXform, false, fromEmber))
|
||||
{
|
||||
|
Reference in New Issue
Block a user