mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-01-21 13:10:04 -05:00
Merge branch 'motion-goodies' of https://github.com/gh2k/fractorium
This commit is contained in:
commit
3a9ce0928f
@ -52,5 +52,6 @@ HEADERS += \
|
||||
../../../Source/Ember/Variations05.h \
|
||||
../../../Source/Ember/VariationsDC.h \
|
||||
../../../Source/Ember/Xform.h \
|
||||
../../../Source/Ember/XmlToEmber.h
|
||||
../../../Source/Ember/XmlToEmber.h \
|
||||
../../../Source/Ember/FlameMotion.h
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "PaletteList.h"
|
||||
#include "SpatialFilter.h"
|
||||
#include "TemporalFilter.h"
|
||||
#include "FlameMotion.h"
|
||||
|
||||
/// <summary>
|
||||
/// Ember class.
|
||||
@ -183,6 +184,11 @@ public:
|
||||
if (ember.m_Edits != nullptr)
|
||||
m_Edits = xmlCopyDoc(ember.m_Edits, 1);
|
||||
|
||||
m_FlameMotionElements.clear();
|
||||
|
||||
for(int i = 0; i < ember.m_FlameMotionElements.size(); ++i)
|
||||
m_FlameMotionElements.push_back(ember.m_FlameMotionElements[i]);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -472,6 +478,8 @@ public:
|
||||
{
|
||||
for (size_t i = 0; i < TotalXformCount(); i++)
|
||||
GetTotalXform(i)->DeleteMotionElements();
|
||||
|
||||
m_FlameMotionElements.clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -1285,6 +1293,82 @@ public:
|
||||
point.m_Z -= m_CamZPos;
|
||||
}
|
||||
|
||||
#define APP_FMP(x) x += param.second * Interpolater<T>::MotionFuncs(motion.m_MotionFunc, motion.m_MotionFreq * (blend + motion.m_MotionOffset))
|
||||
/// <summary>
|
||||
/// Update ember parameters based on stored motion elements
|
||||
/// </summary>
|
||||
/// <param name="blend">The time percentage value which dictates how much of a percentage of 360 degrees it should be rotated and the time position for the motion elements</param>
|
||||
void ApplyFlameMotion(T blend)
|
||||
{
|
||||
for (size_t i = 0; i < m_FlameMotionElements.size(); ++i)
|
||||
{
|
||||
const FlameMotion<T> &motion = m_FlameMotionElements[i];
|
||||
|
||||
for (size_t j = 0; j < motion.m_MotionParams.size(); ++j)
|
||||
{
|
||||
const pair<eFlameMotionParam, T> ¶m = motion.m_MotionParams[j];
|
||||
|
||||
switch (param.first)
|
||||
{
|
||||
case FLAME_MOTION_ZOOM:
|
||||
APP_FMP(m_Zoom);
|
||||
break;
|
||||
case FLAME_MOTION_ZPOS:
|
||||
APP_FMP(m_CamZPos);
|
||||
break;
|
||||
case FLAME_MOTION_PERSPECTIVE:
|
||||
APP_FMP(m_CamPerspective);
|
||||
break;
|
||||
case FLAME_MOTION_YAW:
|
||||
APP_FMP(m_CamYaw);
|
||||
break;
|
||||
case FLAME_MOTION_PITCH:
|
||||
APP_FMP(m_CamPitch);
|
||||
break;
|
||||
case FLAME_MOTION_DEPTH_BLUR:
|
||||
APP_FMP(m_CamDepthBlur);
|
||||
break;
|
||||
case FLAME_MOTION_CENTER_X:
|
||||
APP_FMP(m_CenterX);
|
||||
break;
|
||||
case FLAME_MOTION_CENTER_Y:
|
||||
APP_FMP(m_CenterY);
|
||||
break;
|
||||
case FLAME_MOTION_ROTATE:
|
||||
APP_FMP(m_Rotate);
|
||||
break;
|
||||
case FLAME_MOTION_HUE:
|
||||
APP_FMP(m_Hue);
|
||||
break;
|
||||
case FLAME_MOTION_BRIGHTNESS:
|
||||
APP_FMP(m_Brightness);
|
||||
break;
|
||||
case FLAME_MOTION_GAMMA:
|
||||
APP_FMP(m_Gamma);
|
||||
break;
|
||||
case FLAME_MOTION_GAMMA_THRESH:
|
||||
APP_FMP(m_GammaThresh);
|
||||
break;
|
||||
case FLAME_MOTION_HIGHLIGHT_POWER:
|
||||
APP_FMP(m_HighlightPower);
|
||||
break;
|
||||
case FLAME_MOTION_BACKGROUND_R:
|
||||
APP_FMP(m_Background.r);
|
||||
break;
|
||||
case FLAME_MOTION_BACKGROUND_G:
|
||||
APP_FMP(m_Background.g);
|
||||
break;
|
||||
case FLAME_MOTION_BACKGROUND_B:
|
||||
APP_FMP(m_Background.b);
|
||||
break;
|
||||
case FLAME_MOTION_VIBRANCY:
|
||||
APP_FMP(m_Vibrancy);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear this ember and set to either reasonable or unreasonable default values.
|
||||
/// </summary>
|
||||
@ -1683,6 +1767,9 @@ public:
|
||||
//The 0-based position of this ember in the file it was contained in.
|
||||
size_t m_Index;
|
||||
|
||||
//The list of motion elements for the top-level flame params
|
||||
vector<FlameMotion<T>> m_FlameMotionElements;
|
||||
|
||||
private:
|
||||
/// <summary>
|
||||
/// The type of scaling used when resizing.
|
||||
|
@ -114,10 +114,16 @@ enum eInterp : uint { EMBER_INTERP_LINEAR = 0, EMBER_INTERP_SMOOTH = 1 };
|
||||
enum eAffineInterp : uint { INTERP_LINEAR = 0, INTERP_LOG = 1, INTERP_COMPAT = 2, INTERP_OLDER = 3 };
|
||||
enum ePaletteMode : uint { PALETTE_STEP = 0, PALETTE_LINEAR = 1 };
|
||||
enum ePaletteInterp : uint { INTERP_HSV = 0, INTERP_SWEEP = 1 };
|
||||
enum eMotion : uint { MOTION_SIN = 1, MOTION_TRIANGLE = 2, MOTION_HILL = 3 };
|
||||
enum eMotion : uint { MOTION_SIN = 1, MOTION_TRIANGLE = 2, MOTION_HILL = 3, MOTION_SAW = 4 };
|
||||
enum eProcessAction : uint { NOTHING = 0, ACCUM_ONLY = 1, FILTER_AND_ACCUM = 2, KEEP_ITERATING = 3, FULL_RENDER = 4 };
|
||||
enum eProcessState : uint { NONE = 0, ITER_STARTED = 1, ITER_DONE = 2, FILTER_DONE = 3, ACCUM_DONE = 4 };
|
||||
enum eInteractiveFilter : uint { FILTER_LOG = 0, FILTER_DE = 1 };
|
||||
enum eScaleType : uint { SCALE_NONE = 0, SCALE_WIDTH = 1, SCALE_HEIGHT = 2 };
|
||||
enum eRenderStatus : uint { RENDER_OK = 0, RENDER_ERROR = 1, RENDER_ABORT = 2 };
|
||||
enum eFlameMotionParam : uint {
|
||||
FLAME_MOTION_NONE = 0, FLAME_MOTION_ZOOM = 1, FLAME_MOTION_ZPOS = 2, FLAME_MOTION_PERSPECTIVE = 3, FLAME_MOTION_YAW = 4, FLAME_MOTION_PITCH = 5, FLAME_MOTION_DEPTH_BLUR = 6,
|
||||
FLAME_MOTION_CENTER_X = 7, FLAME_MOTION_CENTER_Y = 8, FLAME_MOTION_ROTATE = 9, FLAME_MOTION_HUE = 10, FLAME_MOTION_BRIGHTNESS = 11, FLAME_MOTION_GAMMA = 12,
|
||||
FLAME_MOTION_GAMMA_THRESH = 13, FLAME_MOTION_HIGHLIGHT_POWER = 14, FLAME_MOTION_BACKGROUND_R = 15, FLAME_MOTION_BACKGROUND_G = 16,
|
||||
FLAME_MOTION_BACKGROUND_B = 17, FLAME_MOTION_VIBRANCY = 18
|
||||
};
|
||||
}
|
||||
|
@ -221,6 +221,9 @@ public:
|
||||
|
||||
os << "\">\n";
|
||||
|
||||
for (i = 0; i < ember.m_FlameMotionElements.size(); ++i)
|
||||
os << " " << ToString(ember.m_FlameMotionElements[i]);
|
||||
|
||||
//This is a grey area, what to do about symmetry to avoid duplicating the symmetry xforms when reading back?//TODO//BUG.
|
||||
//if (ember.m_Symmetry)
|
||||
// os << " <symmetry kind=\"" << ember.m_Symmetry << "\"/>\n";
|
||||
@ -488,6 +491,11 @@ private:
|
||||
os << "motion_function=\"triangle\" ";
|
||||
else if (xform.m_MotionFunc== MOTION_HILL)
|
||||
os << "motion_function=\"hill\" ";
|
||||
else if (xform.m_MotionFunc== MOTION_SAW)
|
||||
os << "motion_function=\"saw\" ";
|
||||
|
||||
if (xform.m_MotionOffset != 0)
|
||||
os << "motion_offset=\"" << xform.m_MotionOffset << "\" ";
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -717,6 +725,113 @@ private:
|
||||
return os.str();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a FlameMotion element to an xml string
|
||||
/// </summary>
|
||||
/// <param name="motion">The FlameMotion object to convert to XML</param>
|
||||
string ToString(const FlameMotion<T> &motion)
|
||||
{
|
||||
ostringstream os;
|
||||
os << "<flame_motion motion_frequency=\"" << motion.m_MotionFreq << "\" ";
|
||||
|
||||
if (motion.m_MotionOffset > 0)
|
||||
os << "motion_offset=\"" << motion.m_MotionOffset << "\" ";
|
||||
|
||||
os << "motion_func=";
|
||||
switch(motion.m_MotionFunc)
|
||||
{
|
||||
case MOTION_SIN:
|
||||
os << "\"sin\"";
|
||||
break;
|
||||
case MOTION_HILL:
|
||||
os << "\"hill\"";
|
||||
break;
|
||||
case MOTION_TRIANGLE:
|
||||
os << "\"triangle\"";
|
||||
break;
|
||||
case MOTION_SAW:
|
||||
os << "\"saw\"";
|
||||
break;
|
||||
}
|
||||
|
||||
T r = 0.0;
|
||||
T g = 0.0;
|
||||
T b = 0.0;
|
||||
T cx = 0.0;
|
||||
T cy = 0.0;
|
||||
|
||||
for(int i = 0; i < motion.m_MotionParams.size(); ++i)
|
||||
{
|
||||
switch(motion.m_MotionParams[i].first)
|
||||
{
|
||||
case FLAME_MOTION_ZOOM:
|
||||
os << " zoom=\"" << motion.m_MotionParams[i].second << "\"";
|
||||
break;
|
||||
case FLAME_MOTION_ZPOS:
|
||||
os << " cam_zpos=\"" << motion.m_MotionParams[i].second << "\"";
|
||||
break;
|
||||
case FLAME_MOTION_PERSPECTIVE:
|
||||
os << " cam_persp=\"" << motion.m_MotionParams[i].second << "\"";
|
||||
break;
|
||||
case FLAME_MOTION_YAW:
|
||||
os << " cam_yaw=\"" << motion.m_MotionParams[i].second << "\"";
|
||||
break;
|
||||
case FLAME_MOTION_PITCH:
|
||||
os << " cam_pitch=\"" << motion.m_MotionParams[i].second << "\"";
|
||||
break;
|
||||
case FLAME_MOTION_DEPTH_BLUR:
|
||||
os << " cam_dof=\"" << motion.m_MotionParams[i].second << "\"";
|
||||
break;
|
||||
case FLAME_MOTION_CENTER_X:
|
||||
cx = motion.m_MotionParams[i].second;
|
||||
break;
|
||||
case FLAME_MOTION_CENTER_Y:
|
||||
cy = motion.m_MotionParams[i].second;
|
||||
break;
|
||||
case FLAME_MOTION_ROTATE:
|
||||
os << " rotate=\"" << motion.m_MotionParams[i].second << "\"";
|
||||
break;
|
||||
case FLAME_MOTION_HUE:
|
||||
os << " hue=\"" << motion.m_MotionParams[i].second << "\"";
|
||||
break;
|
||||
case FLAME_MOTION_BRIGHTNESS:
|
||||
os << " brightness=\"" << motion.m_MotionParams[i].second << "\"";
|
||||
break;
|
||||
case FLAME_MOTION_GAMMA:
|
||||
os << " gamma=\"" << motion.m_MotionParams[i].second << "\"";
|
||||
break;
|
||||
case FLAME_MOTION_GAMMA_THRESH:
|
||||
os << " gamma_threshold=\"" << motion.m_MotionParams[i].second << "\"";
|
||||
break;
|
||||
case FLAME_MOTION_HIGHLIGHT_POWER:
|
||||
os << " highlight_power=\"" << motion.m_MotionParams[i].second << "\"";
|
||||
break;
|
||||
case FLAME_MOTION_BACKGROUND_R:
|
||||
r = motion.m_MotionParams[i].second;
|
||||
break;
|
||||
case FLAME_MOTION_BACKGROUND_G:
|
||||
g = motion.m_MotionParams[i].second;
|
||||
break;
|
||||
case FLAME_MOTION_BACKGROUND_B:
|
||||
b = motion.m_MotionParams[i].second;
|
||||
break;
|
||||
case FLAME_MOTION_VIBRANCY:
|
||||
os << " vibrancy=\"" << motion.m_MotionParams[i].second << "\"";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( r != 0.0 || g != 0.0 || b != 0.0 )
|
||||
os << " background=\"" << r << " " << g << " " << b << "\"";
|
||||
|
||||
if ( cx != 0.0 || cy != 0.0 )
|
||||
os << " center=\"" << cx << " " << cy << "\"";
|
||||
|
||||
os << "/>\n";
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
void AddFilenameWithoutAmpersand(xmlNodePtr node, string& filename)
|
||||
{
|
||||
if (filename.find_first_of('&') != std::string::npos)
|
||||
|
66
Source/Ember/FlameMotion.h
Normal file
66
Source/Ember/FlameMotion.h
Normal file
@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include "EmberDefines.h"
|
||||
|
||||
namespace EmberNs
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// FlameMotion elements allow for motion of the flame parameters such as zoom, yaw, pitch and friends
|
||||
/// The values in these elements can be used to modify flame parameters during rotation in much the same
|
||||
/// way as motion elements on xforms do.
|
||||
/// Template argument expected to be float or double.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
class EMBER_API FlameMotion
|
||||
{
|
||||
public:
|
||||
|
||||
FlameMotion()
|
||||
{
|
||||
m_MotionFreq = 0;
|
||||
m_MotionFunc = MOTION_SIN;
|
||||
m_MotionOffset = 0;
|
||||
}
|
||||
|
||||
FlameMotion(const FlameMotion<T> &other)
|
||||
{
|
||||
operator=<T>(other);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
FlameMotion(const FlameMotion<U> &other)
|
||||
{
|
||||
operator=<U>(other);
|
||||
}
|
||||
|
||||
FlameMotion<T>& operator = (const FlameMotion<T>& other)
|
||||
{
|
||||
if (this != &other)
|
||||
FlameMotion<T>::operator=<T>(other);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
FlameMotion &operator = (const FlameMotion<U> &other)
|
||||
{
|
||||
m_MotionParams.clear();
|
||||
|
||||
for (int i = 0; i < other.m_MotionParams.size(); ++i)
|
||||
m_MotionParams.push_back(pair<eFlameMotionParam, T>(other.m_MotionParams[i].first, T(other.m_MotionParams[i].second)));
|
||||
|
||||
m_MotionFunc = other.m_MotionFunc;
|
||||
m_MotionFreq = T(other.m_MotionFreq);
|
||||
m_MotionOffset = T(other.m_MotionOffset);
|
||||
return *this;
|
||||
}
|
||||
|
||||
T m_MotionFreq;
|
||||
T m_MotionOffset;
|
||||
eMotion m_MotionFunc;
|
||||
vector<pair<eFlameMotionParam, T>> m_MotionParams;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -883,10 +883,14 @@ public:
|
||||
|
||||
return fr;
|
||||
}
|
||||
else//MOTION_HILL
|
||||
else if (funcNum == MOTION_HILL)
|
||||
{
|
||||
return ((1 - cos(T(2.0) * T(M_PI) * timeVal)) * T(0.5));
|
||||
}
|
||||
else //MOTION_SAW
|
||||
{
|
||||
return (T(2.0) * fmod(timeVal - T(0.5), T(1.0)) - T(1.0));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1010,11 +1010,13 @@ public:
|
||||
|
||||
if (!xform1->m_Motion.empty())
|
||||
xform2->ApplyMotion(*xform1, blend);
|
||||
|
||||
xform2->DeleteMotionElements();
|
||||
}
|
||||
|
||||
rotated.ApplyFlameMotion(blend);
|
||||
|
||||
rotated.RotateAffines(-blend * 360);//Rotate the affines.
|
||||
|
||||
rotated.DeleteMotionElements(); // delete all motion elements from the looped flame
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -165,6 +165,7 @@ public:
|
||||
m_Wind[1] = T(xform.m_Wind[1]);
|
||||
m_MotionFreq = xform.m_MotionFreq;
|
||||
m_MotionFunc = xform.m_MotionFunc;
|
||||
m_MotionOffset = xform.m_MotionOffset;
|
||||
|
||||
ClearAndDeleteVariations();
|
||||
|
||||
@ -234,6 +235,7 @@ public:
|
||||
m_Wind[0] = 0;
|
||||
m_Wind[1] = 0;
|
||||
m_MotionFreq = 0;
|
||||
m_MotionOffset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -262,6 +264,7 @@ public:
|
||||
m_Wind[0] = EMPTYFIELD;
|
||||
m_Wind[1] = EMPTYFIELD;
|
||||
m_MotionFreq = EMPTYFIELD;
|
||||
m_MotionOffset = EMPTYFIELD;
|
||||
}
|
||||
|
||||
m_MotionFunc = MOTION_SIN;
|
||||
@ -716,7 +719,7 @@ public:
|
||||
do \
|
||||
{ \
|
||||
if (currentMot.x != EMPTYFIELD) \
|
||||
x += currentMot.x * Interpolater<T>::MotionFuncs(func, freq * blend); \
|
||||
x += currentMot.x * Interpolater<T>::MotionFuncs(func, freq * (blend + offset)); \
|
||||
} while (0)
|
||||
|
||||
/// <summary>
|
||||
@ -731,8 +734,9 @@ public:
|
||||
{
|
||||
//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];
|
||||
intmax_t freq = currentMot.m_MotionFreq;
|
||||
T freq = currentMot.m_MotionFreq;
|
||||
eMotion func = currentMot.m_MotionFunc;
|
||||
T offset = currentMot.m_MotionOffset;
|
||||
|
||||
//Clamp these to the appropriate range after all are applied.
|
||||
APPMOT(m_Weight);
|
||||
@ -753,13 +757,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);
|
||||
newVar->m_Weight = motVar->m_Weight * Interpolater<T>::MotionFuncs(func, freq * (blend + offset));
|
||||
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);
|
||||
var->m_Weight += motVar->m_Weight * Interpolater<T>::MotionFuncs(func, freq * (blend + offset));
|
||||
}
|
||||
|
||||
//At this point, we've added if needed, or just applied the motion func to the weight.
|
||||
@ -773,7 +777,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);
|
||||
*(params[k].Param()) += motParams[k].ParamVal() * Interpolater<T>::MotionFuncs(func, freq * (blend + offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1157,6 +1161,7 @@ public:
|
||||
ss << "Wind: " << m_Wind[0] << ", " << m_Wind[1] << endl;
|
||||
ss << "Motion Frequency: " << m_MotionFreq << endl;
|
||||
ss << "Motion Func: " << m_MotionFunc << endl;
|
||||
ss << "Motion Offset: " << m_MotionOffset << endl;
|
||||
|
||||
const_cast<Xform<T>*>(this)->AllVarsFunc([&] (vector<Variation<T>*>& variations, bool& keepGoing)
|
||||
{
|
||||
@ -1232,7 +1237,8 @@ public:
|
||||
T m_Animate;//Whether or not this xform rotates during animation. 0 means stationary, > 0 means rotate. Use T instead of bool so it can be interpolated.
|
||||
T m_Wind[2];
|
||||
eMotion m_MotionFunc;
|
||||
intmax_t m_MotionFreq;
|
||||
T m_MotionFreq;
|
||||
T m_MotionOffset;
|
||||
vector<Xform<T>> m_Motion;
|
||||
string m_Name;
|
||||
|
||||
|
@ -978,7 +978,7 @@ private:
|
||||
if (theXform)
|
||||
{
|
||||
//Check for non-zero motion params.
|
||||
if (theXform->m_MotionFreq != 0)//Original checked for motion func being non-zero, but it was set to MOTION_SIN (1) in Xform::Init(), so don't check for 0 here.
|
||||
if (abs(theXform->m_MotionFreq) > 0.0)//Original checked for motion func being non-zero, but it was set to MOTION_SIN (1) in Xform::Init(), so don't check for 0 here.
|
||||
{
|
||||
m_ErrorReport.push_back(string(loc) + " : Motion parameters should not be specified in regular, non-motion xforms");
|
||||
}
|
||||
@ -1005,6 +1005,113 @@ private:
|
||||
editNode = xmlCopyNode(childNode, 1);
|
||||
xmlDocSetRootElement(currentEmber.m_Edits, editNode);
|
||||
}
|
||||
else if (!Compare(childNode->name, "flame_motion"))
|
||||
{
|
||||
FlameMotion<T> motion;
|
||||
|
||||
att = childNode->properties;
|
||||
|
||||
if (att == nullptr)
|
||||
{
|
||||
m_ErrorReport.push_back(string(loc) + " : <flame_motion> element has no attributes");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (curAtt = att; curAtt; curAtt = curAtt->next)
|
||||
{
|
||||
attStr = reinterpret_cast<char*>(xmlGetProp(childNode, curAtt->name));
|
||||
|
||||
if (ParseAndAssignFloat(curAtt->name, attStr, "motion_frequency", motion.m_MotionFreq, ret)) { }
|
||||
else if (ParseAndAssignFloat(curAtt->name, attStr, "motion_offset", motion.m_MotionOffset, ret)) { }
|
||||
else if (!Compare(curAtt->name, "motion_function"))
|
||||
{
|
||||
string func(attStr);
|
||||
if ( func == "sin" )
|
||||
motion.m_MotionFunc = MOTION_SIN;
|
||||
else if ( func == "triangle" )
|
||||
motion.m_MotionFunc = MOTION_TRIANGLE;
|
||||
else if ( func == "hill" )
|
||||
motion.m_MotionFunc = MOTION_HILL;
|
||||
else if ( func == "saw" )
|
||||
motion.m_MotionFunc = MOTION_SAW;
|
||||
else
|
||||
{
|
||||
m_ErrorReport.push_back(string(loc) + " : invalid flame motion function " + func);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!Compare(curAtt->name, "zoom"))
|
||||
ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_ZOOM, motion);
|
||||
else if (!Compare(curAtt->name, "cam_zpos"))
|
||||
ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_ZPOS, motion);
|
||||
else if (!Compare(curAtt->name, "cam_persp"))
|
||||
ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_PERSPECTIVE, motion);
|
||||
else if (!Compare(curAtt->name, "cam_yaw"))
|
||||
ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_YAW, motion);
|
||||
else if (!Compare(curAtt->name, "cam_pitch"))
|
||||
ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_PITCH, motion);
|
||||
else if (!Compare(curAtt->name, "cam_dof"))
|
||||
ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_DEPTH_BLUR, motion);
|
||||
else if (!Compare(curAtt->name, "rotate"))
|
||||
ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_ROTATE, motion);
|
||||
else if (!Compare(curAtt->name, "hue"))
|
||||
ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_HUE, motion);
|
||||
else if (!Compare(curAtt->name, "brightness"))
|
||||
ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_BRIGHTNESS, motion);
|
||||
else if (!Compare(curAtt->name, "gamma"))
|
||||
ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_GAMMA, motion);
|
||||
else if (!Compare(curAtt->name, "gamma_threshold"))
|
||||
ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_GAMMA_THRESH, motion);
|
||||
else if (!Compare(curAtt->name, "highlight_power"))
|
||||
ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_HIGHLIGHT_POWER, motion);
|
||||
else if (!Compare(curAtt->name, "vibrancy"))
|
||||
ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_VIBRANCY, motion);
|
||||
else if (!Compare(curAtt->name, "background"))
|
||||
{
|
||||
double r, g, b;
|
||||
|
||||
if (sscanf_s(attStr, "%lf %lf %lf", &r, &g, &b) != 3)
|
||||
{
|
||||
m_ErrorReport.push_back(string(loc) + " : Invalid flame motion background attribute " + string(attStr));
|
||||
xmlFree(attStr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (r != 0)
|
||||
motion.m_MotionParams.push_back(pair<eFlameMotionParam, T>(FLAME_MOTION_BACKGROUND_R, T(r)));
|
||||
if (g != 0)
|
||||
motion.m_MotionParams.push_back(pair<eFlameMotionParam, T>(FLAME_MOTION_BACKGROUND_G, T(g)));
|
||||
if (b != 0)
|
||||
motion.m_MotionParams.push_back(pair<eFlameMotionParam, T>(FLAME_MOTION_BACKGROUND_B, T(b)));
|
||||
}
|
||||
else if (!Compare(curAtt->name, "center"))
|
||||
{
|
||||
double cx, cy;
|
||||
|
||||
if (sscanf_s(attStr, "%lf %lf", &cx, &cy) != 2)
|
||||
{
|
||||
m_ErrorReport.push_back(string(loc) + " : Invalid flame motion center attribute " + string(attStr));
|
||||
xmlFree(attStr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cx != 0)
|
||||
motion.m_MotionParams.push_back(pair<eFlameMotionParam, T>(FLAME_MOTION_CENTER_X, T(cx)));
|
||||
if (cy != 0)
|
||||
motion.m_MotionParams.push_back(pair<eFlameMotionParam, T>(FLAME_MOTION_CENTER_Y, T(cy)));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ErrorReport.push_back(string(loc) + " : Unknown flame motion attribute " + string(CCX(curAtt->name)));
|
||||
xmlFree(attStr);
|
||||
return false;
|
||||
}
|
||||
|
||||
xmlFree(attStr);
|
||||
}
|
||||
|
||||
currentEmber.m_FlameMotionElements.push_back(motion);
|
||||
}
|
||||
}
|
||||
|
||||
//if (!newLinear)
|
||||
@ -1017,6 +1124,32 @@ private:
|
||||
return m_ErrorReport.empty();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a floating point value from an xml attribute and add the value to a FlameMotion object
|
||||
/// </summary>
|
||||
/// <param name="att">The current attribute</param>
|
||||
/// <param name="attStr">The attribute value to parse</param>
|
||||
/// <param name="param">The flame motion parameter type</param>
|
||||
/// <param name="motion">The flame motion element to add the parameter to</param>
|
||||
/// <returns>True if there were no errors, else false.</returns>
|
||||
bool AttToFlameMotionFloat(xmlAttrPtr att, const char *attStr, eFlameMotionParam param, FlameMotion<T> &motion)
|
||||
{
|
||||
const char* loc = __FUNCTION__;
|
||||
|
||||
bool r = false;
|
||||
T val = 0.0;
|
||||
|
||||
if (Atof(attStr, val))
|
||||
{
|
||||
motion.m_MotionParams.push_back(pair<eFlameMotionParam, T>(param, val));
|
||||
r = true;
|
||||
} else {
|
||||
m_ErrorReport.push_back(string(loc) + " : Failed to parse float value for flame motion attribute \"" + string(CCX(att->name)) + "\" : " + string(attStr) + "");
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse an xform element.
|
||||
/// </summary>
|
||||
@ -1054,9 +1187,8 @@ private:
|
||||
else if (ParseAndAssignFloat(curAtt->name, attStr, "animate", xform.m_Animate, success)) { }
|
||||
else if (ParseAndAssignFloat(curAtt->name, attStr, "opacity", xform.m_Opacity, success)) { }
|
||||
else if (ParseAndAssignFloat(curAtt->name, attStr, "var_color", xform.m_DirectColor, success)) { }
|
||||
|
||||
//Parse simple int reads.
|
||||
else if (ParseAndAssignInt(curAtt->name, attStr, "motion_frequency", xform.m_MotionFreq, success)) { }
|
||||
else if (ParseAndAssignFloat(curAtt->name, attStr, "motion_frequency", xform.m_MotionFreq, success)) { }
|
||||
else if (ParseAndAssignFloat(curAtt->name, attStr, "motion_offset", xform.m_MotionOffset, success)) { }
|
||||
|
||||
//Parse more complicated reads that have multiple possible values.
|
||||
else if (!Compare(curAtt->name, "name"))
|
||||
@ -1080,6 +1212,8 @@ private:
|
||||
xform.m_MotionFunc = MOTION_TRIANGLE;
|
||||
else if (!_stricmp("hill", attStr))
|
||||
xform.m_MotionFunc = MOTION_HILL;
|
||||
else if (!_stricmp("saw", attStr))
|
||||
xform.m_MotionFunc = MOTION_SAW;
|
||||
else
|
||||
{
|
||||
xform.m_MotionFunc = MOTION_SIN;
|
||||
|
@ -76,7 +76,6 @@ enum eOptionIDs
|
||||
OPT_SYMMETRY,
|
||||
OPT_SHEEP_GEN,
|
||||
OPT_SHEEP_ID,
|
||||
OPT_LOOPS,
|
||||
OPT_REPEAT,
|
||||
OPT_TRIES,
|
||||
OPT_MAX_XFORMS,
|
||||
@ -93,6 +92,7 @@ enum eOptionIDs
|
||||
OPT_OFFSETX,
|
||||
OPT_OFFSETY,
|
||||
OPT_USEMEM,
|
||||
OPT_LOOPS,
|
||||
|
||||
OPT_ISAAC_SEED,//String value args.
|
||||
OPT_IN,
|
||||
@ -357,7 +357,6 @@ public:
|
||||
INITUINTOPTION(Frame, Eou(OPT_ANIM_GENOME, OPT_FRAME, _T("--frame"), 0, SO_REQ_SEP, "\t--frame=<val> Synonym for \"time\".\n"));
|
||||
INITUINTOPTION(Dtime, Eou(OPT_USE_ANIMATE, OPT_DTIME, _T("--dtime"), 1, SO_REQ_SEP, "\t--dtime=<val> Time between frames [default: 1].\n"));
|
||||
INITUINTOPTION(Frames, Eou(OPT_USE_GENOME, OPT_NFRAMES, _T("--nframes"), 20, SO_REQ_SEP, "\t--nframes=<val> Number of frames for each stage of the animation [default: 20].\n"));
|
||||
INITUINTOPTION(Loops, Eou(OPT_USE_GENOME, OPT_LOOPS, _T("--loops"), 1, SO_REQ_SEP, "\t--loops=<val> Number of times to rotate each control point in sequence [default: 1].\n"));
|
||||
INITUINTOPTION(Repeat, Eou(OPT_USE_GENOME, OPT_REPEAT, _T("--repeat"), 1, SO_REQ_SEP, "\t--repeat=<val> Number of new flames to create. Ignored if sequence, inter or rotate were specified [default: 1].\n"));
|
||||
INITUINTOPTION(Tries, Eou(OPT_USE_GENOME, OPT_TRIES, _T("--tries"), 10, SO_REQ_SEP, "\t--tries=<val> Number times to try creating a flame that meets the specified constraints. Ignored if sequence, inter or rotate were specified [default: 10].\n"));
|
||||
INITUINTOPTION(MaxXforms, Eou(OPT_USE_GENOME, OPT_MAX_XFORMS, _T("--maxxforms"), UINT_MAX, SO_REQ_SEP, "\t--maxxforms=<val> The maximum number of xforms allowed in the final output.\n"));
|
||||
@ -376,6 +375,7 @@ public:
|
||||
INITDOUBLEOPTION(OffsetX, Eod(OPT_USE_GENOME, OPT_OFFSETX, _T("--offsetx"), 0.0, SO_REQ_SEP, "\t--offsetx=<val> Amount to jitter each flame horizontally when applying genome tools [default: 0].\n"));
|
||||
INITDOUBLEOPTION(OffsetY, Eod(OPT_USE_GENOME, OPT_OFFSETY, _T("--offsety"), 0.0, SO_REQ_SEP, "\t--offsety=<val> Amount to jitter each flame vertically when applying genome tools [default: 0].\n"));
|
||||
INITDOUBLEOPTION(UseMem, Eod(OPT_USE_RENDER, OPT_USEMEM, _T("--use_mem"), 0.0, SO_REQ_SEP, "\t--use_mem=<val> Number of bytes of memory to use [default: max system memory].\n"));
|
||||
INITDOUBLEOPTION(Loops, Eod(OPT_USE_GENOME, OPT_LOOPS, _T("--loops"), 1, SO_REQ_SEP, "\t--loops=<val> Number of times to rotate each control point in sequence [default: 1].\n"));
|
||||
|
||||
//String.
|
||||
INITSTRINGOPTION(IsaacSeed, Eos(OPT_USE_ALL, OPT_ISAAC_SEED, _T("--isaac_seed"), "", SO_REQ_SEP, "\t--isaac_seed=<val> Character-based seed for the random number generator [default: random].\n"));
|
||||
@ -487,7 +487,6 @@ public:
|
||||
PARSEUINTOPTION(OPT_TIME, Time);
|
||||
PARSEUINTOPTION(OPT_DTIME, Dtime);
|
||||
PARSEUINTOPTION(OPT_NFRAMES, Frames);
|
||||
PARSEUINTOPTION(OPT_LOOPS, Loops);
|
||||
PARSEUINTOPTION(OPT_REPEAT, Repeat);
|
||||
PARSEUINTOPTION(OPT_TRIES, Tries);
|
||||
PARSEUINTOPTION(OPT_MAX_XFORMS, MaxXforms);
|
||||
@ -503,6 +502,7 @@ public:
|
||||
PARSEDOUBLEOPTION(OPT_OFFSETX, OffsetX);
|
||||
PARSEDOUBLEOPTION(OPT_OFFSETY, OffsetY);
|
||||
PARSEDOUBLEOPTION(OPT_USEMEM, UseMem);
|
||||
PARSEDOUBLEOPTION(OPT_LOOPS, Loops);
|
||||
|
||||
PARSESTRINGOPTION(OPT_ISAAC_SEED, IsaacSeed);//String args.
|
||||
PARSESTRINGOPTION(OPT_IN, Input);
|
||||
@ -703,7 +703,6 @@ public:
|
||||
EmberOptionEntry<uint> Time;
|
||||
EmberOptionEntry<uint> Dtime;
|
||||
EmberOptionEntry<uint> Frames;
|
||||
EmberOptionEntry<uint> Loops;
|
||||
EmberOptionEntry<uint> Repeat;
|
||||
EmberOptionEntry<uint> Tries;
|
||||
EmberOptionEntry<uint> MaxXforms;
|
||||
@ -719,6 +718,7 @@ public:
|
||||
EmberOptionEntry<double> OffsetX;
|
||||
EmberOptionEntry<double> OffsetY;
|
||||
EmberOptionEntry<double> UseMem;
|
||||
EmberOptionEntry<double> Loops;
|
||||
|
||||
EmberOptionEntry<string> IsaacSeed;//Value string.
|
||||
EmberOptionEntry<string> Input;
|
||||
|
@ -382,9 +382,9 @@ bool EmberGenome(EmberOptions& opt)
|
||||
|
||||
for (i = 0; i < embers.size(); i++)
|
||||
{
|
||||
if (opt.Loops())
|
||||
if (opt.Loops() > 0)
|
||||
{
|
||||
for (frame = 0; frame < opt.Frames(); frame++)
|
||||
for (frame = 0; frame < round(T(opt.Frames()) * opt.Loops()); frame++)
|
||||
{
|
||||
blend = T(frame) / T(opt.Frames());
|
||||
tools.Spin(embers[i], pTemplate, result, frameCount++, blend);//Result is cleared and reassigned each time inside of Spin().
|
||||
@ -394,12 +394,23 @@ bool EmberGenome(EmberOptions& opt)
|
||||
|
||||
if (i < embers.size() - 1)
|
||||
{
|
||||
vector<Ember<T>> interpEmbers;
|
||||
interpEmbers.push_back(embers[i]);
|
||||
interpEmbers.push_back(embers[i + 1]);
|
||||
|
||||
if (opt.Loops() > 0)
|
||||
{
|
||||
// we might have looped a non-integral number of times, so store the last result as our flame to interpolate from
|
||||
|
||||
interpEmbers[i] = result;
|
||||
}
|
||||
|
||||
for (frame = 0; frame < opt.Frames(); frame++)
|
||||
{
|
||||
seqFlag = (frame == 0 || frame == opt.Frames() - 1);
|
||||
blend = frame / T(opt.Frames());
|
||||
result.Clear();
|
||||
tools.SpinInter(&embers[i], pTemplate, result, frameCount++, seqFlag, blend);
|
||||
tools.SpinInter(&interpEmbers[i], pTemplate, result, frameCount++, seqFlag, blend);
|
||||
cout << emberToXml.ToString(result, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), false, opt.HexPalette());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user