From fb262c2469ef13d1dc3fe243e48d0bb9baf8df62 Mon Sep 17 00:00:00 2001 From: mfeemster Date: Mon, 6 Jul 2015 21:36:46 -0700 Subject: [PATCH] --User changes -Add motion support from Simon Detheridge at the ember level instead of just individual xforms: Add the ability to manipulate camera pitch, yaw and other goodies during flame rotation using a new element specified at the top-level of the flame. Create a new 'saw' motion function, so that these values can effectively be looped (e.g. yaw -1 to +1) over the course of a rotation. Add an offset to existing motion elements, to start them partway through their cycle. This would (for example) enable creating circular motion of xform affines, by combining two offset sine waves, one with an offset of 0.25 or 0.75. Fix loops in EmberGenome (they only had an on/off effect - this was broken in flame-genome as well) and make the loop count floating-point as well. For sequence animations, it's not necessary for clips to loop precisely if they're not designed specifically for the ES project. Similarly, there's no need for motion_frequency to be an integer value either so this was changed to allow motion that doesn't necessarily start or end at the loop boundary. I've attempted to keep each bit of functionality in its own commit. There's an argument as to whether to call the new flame motion elements (to differentiate programmatically) or just (for consistency within the file) -- I opted for the former because it was easier to modify the xml parser that way. --Code changes -Change FlameMotion.h to EmberMotion.h to keep the naming convention consistent. -Made elements of EmberMotion.m_MotionParams into their own type, MotionParam, which allows for CopyVec() to work. -Change m_FlameMotionElements to m_EmberMotionElements in Ember. -Use CopyVec() for EmberMotion instead of manual copy in copy constructors. -Add exports in Ember.cpp for EmberMotion. -Format eEmberMotionParam enum with one entry per line since it has many entries. -Use fabs() in XmlToEmber instead of glm::abs. -Minor formatting. --- Builds/MSVC/VS2013/Ember.vcxproj | 1 + Builds/MSVC/VS2013/Ember.vcxproj.filters | 3 ++ Builds/QtCreator/Ember/Ember.pro | 2 +- Source/Ember/Ember.cpp | 3 ++ Source/Ember/Ember.h | 18 +++---- Source/Ember/EmberDefines.h | 26 +++++++-- Source/Ember/EmberToXml.h | 15 +++--- Source/Ember/FlameMotion.h | 66 ----------------------- Source/Ember/Point.h | 4 ++ Source/Ember/SheepTools.h | 4 +- Source/Ember/XmlToEmber.h | 67 +++++++++++++----------- Source/EmberCommon/EmberOptions.h | 2 +- Source/EmberGenome/EmberGenome.cpp | 6 +-- 13 files changed, 90 insertions(+), 127 deletions(-) delete mode 100644 Source/Ember/FlameMotion.h diff --git a/Builds/MSVC/VS2013/Ember.vcxproj b/Builds/MSVC/VS2013/Ember.vcxproj index 4016a78..25d86c3 100644 --- a/Builds/MSVC/VS2013/Ember.vcxproj +++ b/Builds/MSVC/VS2013/Ember.vcxproj @@ -271,6 +271,7 @@ + diff --git a/Builds/MSVC/VS2013/Ember.vcxproj.filters b/Builds/MSVC/VS2013/Ember.vcxproj.filters index 59e3bf5..ab751a1 100644 --- a/Builds/MSVC/VS2013/Ember.vcxproj.filters +++ b/Builds/MSVC/VS2013/Ember.vcxproj.filters @@ -113,6 +113,9 @@ Header Files + + Header Files + diff --git a/Builds/QtCreator/Ember/Ember.pro b/Builds/QtCreator/Ember/Ember.pro index b0e57e1..f4da780 100644 --- a/Builds/QtCreator/Ember/Ember.pro +++ b/Builds/QtCreator/Ember/Ember.pro @@ -53,5 +53,5 @@ HEADERS += \ ../../../Source/Ember/VariationsDC.h \ ../../../Source/Ember/Xform.h \ ../../../Source/Ember/XmlToEmber.h \ - ../../../Source/Ember/FlameMotion.h + ../../../Source/Ember/EmberMotion.h diff --git a/Source/Ember/Ember.cpp b/Source/Ember/Ember.cpp index 9684061..89009c6 100644 --- a/Source/Ember/Ember.cpp +++ b/Source/Ember/Ember.cpp @@ -24,6 +24,7 @@ template<> unique_ptr> QTIsaac; \ template EMBER_API class XaosIterator; \ template EMBER_API class Xform; \ + template EMBER_API class MotionParam; \ + template EMBER_API class EmberMotion; \ template EMBER_API class IteratorHelper; \ template EMBER_API class Variation; \ template EMBER_API class ParamWithName; \ diff --git a/Source/Ember/Ember.h b/Source/Ember/Ember.h index b02cd76..af394ae 100644 --- a/Source/Ember/Ember.h +++ b/Source/Ember/Ember.h @@ -5,7 +5,7 @@ #include "PaletteList.h" #include "SpatialFilter.h" #include "TemporalFilter.h" -#include "FlameMotion.h" +#include "EmberMotion.h" /// /// Ember class. @@ -184,10 +184,7 @@ 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]); + CopyVec(m_EmberMotionElements, ember.m_EmberMotionElements); return *this; } @@ -479,7 +476,7 @@ public: for (size_t i = 0; i < TotalXformCount(); i++) GetTotalXform(i)->DeleteMotionElements(); - m_FlameMotionElements.clear(); + m_EmberMotionElements.clear(); } /// @@ -1294,19 +1291,20 @@ public: } #define APP_FMP(x) x += param.second * Interpolater::MotionFuncs(motion.m_MotionFunc, motion.m_MotionFreq * (blend + motion.m_MotionOffset)) + /// /// Update ember parameters based on stored motion elements /// /// 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 void ApplyFlameMotion(T blend) { - for (size_t i = 0; i < m_FlameMotionElements.size(); ++i) + for (size_t i = 0; i < m_EmberMotionElements.size(); ++i) { - const FlameMotion &motion = m_FlameMotionElements[i]; + auto& motion = m_EmberMotionElements[i]; for (size_t j = 0; j < motion.m_MotionParams.size(); ++j) { - const pair ¶m = motion.m_MotionParams[j]; + auto& param = motion.m_MotionParams[j]; switch (param.first) { @@ -1768,7 +1766,7 @@ public: size_t m_Index; //The list of motion elements for the top-level flame params - vector> m_FlameMotionElements; + vector> m_EmberMotionElements; private: /// diff --git a/Source/Ember/EmberDefines.h b/Source/Ember/EmberDefines.h index 92e69ae..43107eb 100644 --- a/Source/Ember/EmberDefines.h +++ b/Source/Ember/EmberDefines.h @@ -120,10 +120,26 @@ enum eProcessState : uint { NONE = 0, ITER_STARTED = 1, ITER_DONE = 2, FILTER_DO 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 +enum eEmberMotionParam : 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 }; } diff --git a/Source/Ember/EmberToXml.h b/Source/Ember/EmberToXml.h index f79ba8a..4080b74 100644 --- a/Source/Ember/EmberToXml.h +++ b/Source/Ember/EmberToXml.h @@ -221,8 +221,8 @@ public: os << "\">\n"; - for (i = 0; i < ember.m_FlameMotionElements.size(); ++i) - os << " " << ToString(ember.m_FlameMotionElements[i]); + for (i = 0; i < ember.m_EmberMotionElements.size(); ++i) + os << " " << ToString(ember.m_EmberMotionElements[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) @@ -729,7 +729,7 @@ private: /// Convert a FlameMotion element to an xml string /// /// The FlameMotion object to convert to XML - string ToString(const FlameMotion &motion) + string ToString(const EmberMotion& motion) { ostringstream os; os << "\n"; diff --git a/Source/Ember/FlameMotion.h b/Source/Ember/FlameMotion.h deleted file mode 100644 index 7f47d90..0000000 --- a/Source/Ember/FlameMotion.h +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once - -#include "EmberDefines.h" - -namespace EmberNs -{ - -/// -/// 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. -/// -template -class EMBER_API FlameMotion -{ -public: - - FlameMotion() - { - m_MotionFreq = 0; - m_MotionFunc = MOTION_SIN; - m_MotionOffset = 0; - } - - FlameMotion(const FlameMotion &other) - { - operator=(other); - } - - template - FlameMotion(const FlameMotion &other) - { - operator=(other); - } - - FlameMotion& operator = (const FlameMotion& other) - { - if (this != &other) - FlameMotion::operator=(other); - - return *this; - } - - template - FlameMotion &operator = (const FlameMotion &other) - { - m_MotionParams.clear(); - - for (int i = 0; i < other.m_MotionParams.size(); ++i) - m_MotionParams.push_back(pair(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> m_MotionParams; - -}; - -} diff --git a/Source/Ember/Point.h b/Source/Ember/Point.h index b157b6d..a60cd62 100644 --- a/Source/Ember/Point.h +++ b/Source/Ember/Point.h @@ -196,6 +196,10 @@ public: /// /// Member-wise constructor. /// + /// The red value, either 0-1 or 0-255. + /// The green value, either 0-1 or 0-255. + /// The blue value, either 0-1 or 0-255. + /// The alpha value, either 0-1 or 0-255. Color(T rr, T gg, T bb, T aa) : v4T(rr, gg, bb, aa) { diff --git a/Source/Ember/SheepTools.h b/Source/Ember/SheepTools.h index b01ac14..07c3d2f 100644 --- a/Source/Ember/SheepTools.h +++ b/Source/Ember/SheepTools.h @@ -1013,10 +1013,8 @@ public: } rotated.ApplyFlameMotion(blend); - rotated.RotateAffines(-blend * 360);//Rotate the affines. - - rotated.DeleteMotionElements(); // delete all motion elements from the looped flame + rotated.DeleteMotionElements();//Delete all motion elements from the looped ember, at the xform level and at the parent ember level. } /// diff --git a/Source/Ember/XmlToEmber.h b/Source/Ember/XmlToEmber.h index 6c7fb44..9612876 100644 --- a/Source/Ember/XmlToEmber.h +++ b/Source/Ember/XmlToEmber.h @@ -978,7 +978,7 @@ private: if (theXform) { //Check for non-zero motion params. - 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. + if (fabs(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"); } @@ -1007,7 +1007,7 @@ private: } else if (!Compare(childNode->name, "flame_motion")) { - FlameMotion motion; + EmberMotion motion; att = childNode->properties; @@ -1026,13 +1026,14 @@ private: else if (!Compare(curAtt->name, "motion_function")) { string func(attStr); - if ( func == "sin" ) + + if (func == "sin") motion.m_MotionFunc = MOTION_SIN; - else if ( func == "triangle" ) + else if (func == "triangle") motion.m_MotionFunc = MOTION_TRIANGLE; - else if ( func == "hill" ) + else if (func == "hill") motion.m_MotionFunc = MOTION_HILL; - else if ( func == "saw" ) + else if (func == "saw") motion.m_MotionFunc = MOTION_SAW; else { @@ -1041,31 +1042,31 @@ private: } } else if (!Compare(curAtt->name, "zoom")) - ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_ZOOM, motion); + ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_ZOOM, motion); else if (!Compare(curAtt->name, "cam_zpos")) - ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_ZPOS, motion); + ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_ZPOS, motion); else if (!Compare(curAtt->name, "cam_persp")) - ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_PERSPECTIVE, motion); + ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_PERSPECTIVE, motion); else if (!Compare(curAtt->name, "cam_yaw")) - ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_YAW, motion); + ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_YAW, motion); else if (!Compare(curAtt->name, "cam_pitch")) - ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_PITCH, motion); + ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_PITCH, motion); else if (!Compare(curAtt->name, "cam_dof")) - ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_DEPTH_BLUR, motion); + ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_DEPTH_BLUR, motion); else if (!Compare(curAtt->name, "rotate")) - ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_ROTATE, motion); + ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_ROTATE, motion); else if (!Compare(curAtt->name, "hue")) - ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_HUE, motion); + ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_HUE, motion); else if (!Compare(curAtt->name, "brightness")) - ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_BRIGHTNESS, motion); + ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_BRIGHTNESS, motion); else if (!Compare(curAtt->name, "gamma")) - ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_GAMMA, motion); + ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_GAMMA, motion); else if (!Compare(curAtt->name, "gamma_threshold")) - ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_GAMMA_THRESH, motion); + ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_GAMMA_THRESH, motion); else if (!Compare(curAtt->name, "highlight_power")) - ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_HIGHLIGHT_POWER, motion); + ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_HIGHLIGHT_POWER, motion); else if (!Compare(curAtt->name, "vibrancy")) - ret = ret && AttToFlameMotionFloat(att, attStr, FLAME_MOTION_VIBRANCY, motion); + ret = ret && AttToEmberMotionFloat(att, attStr, FLAME_MOTION_VIBRANCY, motion); else if (!Compare(curAtt->name, "background")) { double r, g, b; @@ -1078,11 +1079,13 @@ private: } if (r != 0) - motion.m_MotionParams.push_back(pair(FLAME_MOTION_BACKGROUND_R, T(r))); + motion.m_MotionParams.push_back(MotionParam(FLAME_MOTION_BACKGROUND_R, T(r))); + if (g != 0) - motion.m_MotionParams.push_back(pair(FLAME_MOTION_BACKGROUND_G, T(g))); + motion.m_MotionParams.push_back(MotionParam(FLAME_MOTION_BACKGROUND_G, T(g))); + if (b != 0) - motion.m_MotionParams.push_back(pair(FLAME_MOTION_BACKGROUND_B, T(b))); + motion.m_MotionParams.push_back(MotionParam(FLAME_MOTION_BACKGROUND_B, T(b))); } else if (!Compare(curAtt->name, "center")) { @@ -1096,9 +1099,10 @@ private: } if (cx != 0) - motion.m_MotionParams.push_back(pair(FLAME_MOTION_CENTER_X, T(cx))); + motion.m_MotionParams.push_back(MotionParam(FLAME_MOTION_CENTER_X, T(cx))); + if (cy != 0) - motion.m_MotionParams.push_back(pair(FLAME_MOTION_CENTER_Y, T(cy))); + motion.m_MotionParams.push_back(MotionParam(FLAME_MOTION_CENTER_Y, T(cy))); } else { @@ -1110,7 +1114,7 @@ private: xmlFree(attStr); } - currentEmber.m_FlameMotionElements.push_back(motion); + currentEmber.m_EmberMotionElements.push_back(motion); } } @@ -1125,26 +1129,27 @@ private: } /// - /// Parse a floating point value from an xml attribute and add the value to a FlameMotion object + /// Parse a floating point value from an xml attribute and add the value to a EmberMotion object /// /// The current attribute /// The attribute value to parse /// The flame motion parameter type /// The flame motion element to add the parameter to /// True if there were no errors, else false. - bool AttToFlameMotionFloat(xmlAttrPtr att, const char *attStr, eFlameMotionParam param, FlameMotion &motion) + bool AttToEmberMotionFloat(xmlAttrPtr att, const char* attStr, eEmberMotionParam param, EmberMotion& motion) { const char* loc = __FUNCTION__; - bool r = false; T val = 0.0; if (Atof(attStr, val)) { - motion.m_MotionParams.push_back(pair(param, val)); + motion.m_MotionParams.push_back(MotionParam(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) + ""); + } + else + { + m_ErrorReport.push_back(string(loc) + " : Failed to parse float value for flame motion attribute \"" + string(CCX(att->name)) + "\" : " + string(attStr)); } return r; diff --git a/Source/EmberCommon/EmberOptions.h b/Source/EmberCommon/EmberOptions.h index fc7e453..87e2790 100644 --- a/Source/EmberCommon/EmberOptions.h +++ b/Source/EmberCommon/EmberOptions.h @@ -375,7 +375,7 @@ public: INITDOUBLEOPTION(OffsetX, Eod(OPT_USE_GENOME, OPT_OFFSETX, _T("--offsetx"), 0.0, SO_REQ_SEP, "\t--offsetx= 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= 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= 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= Number of times to rotate each control point in sequence [default: 1].\n")); + INITDOUBLEOPTION(Loops, Eod(OPT_USE_GENOME, OPT_LOOPS, _T("--loops"), 1.0, SO_REQ_SEP, "\t--loops= 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= Character-based seed for the random number generator [default: random].\n")); diff --git a/Source/EmberGenome/EmberGenome.cpp b/Source/EmberGenome/EmberGenome.cpp index e8c3569..d62bc17 100644 --- a/Source/EmberGenome/EmberGenome.cpp +++ b/Source/EmberGenome/EmberGenome.cpp @@ -395,14 +395,14 @@ bool EmberGenome(EmberOptions& opt) if (i < embers.size() - 1) { vector> 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; + //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++)