Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tstream.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzBase includes
Toshihiro Shimizu 890ddd
#include "tdoublekeyframe.h"
Toshihiro Shimizu 890ddd
#include "tparamchange.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzExt includes
Toshihiro Shimizu 890ddd
#include "ext/plasticskeleton.h"
Toshihiro Shimizu 890ddd
#include "ext/plasticdeformerstorage.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// tcg includes
Toshihiro Shimizu 890ddd
#include "tcg/tcg_misc.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// STL includes
Toshihiro Shimizu 890ddd
#include <memory></memory>
Toshihiro Shimizu 890ddd
#include <set></set>
Toshihiro Shimizu 890ddd
#include <map></map>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Boost includes
Toshihiro Shimizu 890ddd
#include <boost bimap.hpp=""></boost>
Toshihiro Shimizu 890ddd
#include <boost multi_index_container.hpp=""></boost>
Toshihiro Shimizu 890ddd
#include <boost multi_index="" ordered_index.hpp=""></boost>
Toshihiro Shimizu 890ddd
#include <boost member.hpp="" multi_index=""></boost>
Toshihiro Shimizu 890ddd
#include <boost iterator="" transform_iterator.hpp=""></boost>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "ext/plasticskeletondeformation.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PERSIST_IDENTIFIER(PlasticSkeletonVertexDeformation,
Shinya Kitaoka 120a6e
                   "PlasticSkeletonVertexDeformation")
Toshihiro Shimizu 890ddd
PERSIST_IDENTIFIER(PlasticSkeletonDeformation, "PlasticSkeletonDeformation")
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DEFINE_CLASS_CODE(PlasticSkeletonDeformation, 121)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**************************************************************************************
Toshihiro Shimizu 890ddd
//    Boost-related  stuff
Toshihiro Shimizu 890ddd
//**************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace boost::multi_index;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef boost::bimap<int, plasticskeletonp=""> SkeletonSet;</int,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//======================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct VDKey {
Shinya Kitaoka 120a6e
  QString m_name;
Shinya Kitaoka 120a6e
  int m_hookNumber;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  mutable std::map<int, int=""></int,>
Shinya Kitaoka 120a6e
      m_vIndices;  //!< Skeleton index to Vertex index map
Shinya Kitaoka 120a6e
  mutable SkVD m_vd;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
typedef boost::multi_index_container<
Shinya Kitaoka 120a6e
    VDKey,
Shinya Kitaoka 120a6e
    indexed_by<
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        ordered_unique<tag<qstring>, member<vdkey, &vdkey::m_name="" qstring,="">>,</vdkey,></tag<qstring>
Shinya Kitaoka 120a6e
        ordered_unique<tag<int>, member<vdkey, &vdkey::m_hooknumber="" int,="">></vdkey,></tag<int>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        >>
Shinya Kitaoka 120a6e
    SkVDSet;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef SkVDSet::index<int>::type SkVDByHookNumber;</int>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**************************************************************************************
Toshihiro Shimizu 890ddd
//    Local  namespace
Toshihiro Shimizu 890ddd
//**************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static const char *parNames[SkVD::PARAMS_COUNT] = {"Angle", "Distance", "SO"};
Toshihiro Shimizu 890ddd
static const char *parMeasures[SkVD::PARAMS_COUNT] = {"angle", "fxLength", ""};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Extract the angle between edges vParent->v and vGrandParent->vParent
Shinya Kitaoka 120a6e
double buildAngle(const PlasticSkeleton &skeleton, int v) {
Shinya Kitaoka 120a6e
  const PlasticSkeletonVertex &vx = skeleton.vertex(v);
Shinya Kitaoka 120a6e
  int vParent                     = vx.parent();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(vx.parent() >= 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const PlasticSkeletonVertex &vxParent = skeleton.vertex(vParent);
Shinya Kitaoka 120a6e
  int vGrandParent                      = vxParent.parent();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Build reference orientation
Shinya Kitaoka 120a6e
  TPointD dir(1.0, 0.0);  // Standard horizontal axis if no grandParent
Shinya Kitaoka 120a6e
  if (vGrandParent >= 0) {
Shinya Kitaoka 120a6e
    // Relative orientation
Shinya Kitaoka 120a6e
    const PlasticSkeletonVertex &vxGrandParent = skeleton.vertex(vGrandParent);
Shinya Kitaoka 120a6e
    dir = vxParent.P() - vxGrandParent.P();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return tcg::point_ops::angle(dir, vx.P() - vxParent.P()) * M_180_PI;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**************************************************************************************
Toshihiro Shimizu 890ddd
//    PlasticSkeletonVertex  implementation
Toshihiro Shimizu 890ddd
//**************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
SkVD::Keyframe SkVD::getKeyframe(double frame) const {
Shinya Kitaoka 120a6e
  Keyframe kf;
Shinya Kitaoka 120a6e
  for (int p          = 0; p < PARAMS_COUNT; ++p)
Shinya Kitaoka 120a6e
    kf.m_keyframes[p] = m_params[p]->getKeyframeAt(frame);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return kf;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void SkVD::setKeyframe(double frame) {
Shinya Kitaoka 120a6e
  for (int p = 0; p < PARAMS_COUNT; ++p)
Shinya Kitaoka 120a6e
    m_params[p]->setKeyframe(m_params[p]->getKeyframeAt(frame));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool SkVD::setKeyframe(const SkVD::Keyframe &values) {
Shinya Kitaoka 120a6e
  bool keyWasSet = false;
Shinya Kitaoka 120a6e
  for (int p = 0; p < PARAMS_COUNT; ++p)
Shinya Kitaoka 120a6e
    if (values.m_keyframes[p].m_isKeyframe) {
Shinya Kitaoka 120a6e
      m_params[p]->setKeyframe(values.m_keyframes[p]);
Shinya Kitaoka 120a6e
      keyWasSet = true;
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return keyWasSet;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool SkVD::setKeyframe(const SkVD::Keyframe &values, double frame,
Shinya Kitaoka 120a6e
                       double easeIn, double easeOut) {
Shinya Kitaoka 120a6e
  bool keyWasSet = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (int p = 0; p < PARAMS_COUNT; ++p)
Shinya Kitaoka 120a6e
    if (values.m_keyframes[p].m_isKeyframe) {
Shinya Kitaoka 120a6e
      TDoubleKeyframe kf(values.m_keyframes[p]);
Shinya Kitaoka 120a6e
      kf.m_frame = frame;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      if (easeIn >= 0.0) kf.m_speedIn   = TPointD(-easeIn, kf.m_speedIn.y);
Shinya Kitaoka 120a6e
      if (easeOut >= 0.0) kf.m_speedOut = TPointD(easeOut, kf.m_speedOut.y);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      m_params[p]->setKeyframe(kf);
Shinya Kitaoka 120a6e
      keyWasSet = true;
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return keyWasSet;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool SkVD::isKeyframe(double frame) const {
Shinya Kitaoka 120a6e
  for (int p = 0; p < PARAMS_COUNT; ++p)
Shinya Kitaoka 120a6e
    if (m_params[p]->isKeyframe(frame)) return true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool SkVD::isFullKeyframe(double frame) const {
Shinya Kitaoka 120a6e
  for (int p = 0; p < PARAMS_COUNT; ++p)
Shinya Kitaoka 120a6e
    if (!m_params[p]->isKeyframe(frame)) return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void SkVD::deleteKeyframe(double frame) {
Shinya Kitaoka 120a6e
  for (int p = 0; p < PARAMS_COUNT; ++p) m_params[p]->deleteKeyframe(frame);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void SkVD::saveData(TOStream &os) {
Shinya Kitaoka 120a6e
  for (int p = 0; p < PARAMS_COUNT; ++p)
Shinya Kitaoka 120a6e
    if (!m_params[p]->isDefault()) os.child(::parNames[p]) << *m_params[p];
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void SkVD::loadData(TIStream &is) {
Shinya Kitaoka 120a6e
  std::string tagName;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  while (is.matchTag(tagName)) {
Shinya Kitaoka 120a6e
    int p;
Shinya Kitaoka 120a6e
    for (p = 0; p < PARAMS_COUNT; ++p) {
Shinya Kitaoka 120a6e
      if (tagName == parNames[p]) {
Shinya Kitaoka 120a6e
        is >> *m_params[p], is.matchEndTag();
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (p >= PARAMS_COUNT) is.skipCurrentTag();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**************************************************************************************
Toshihiro Shimizu 890ddd
//    PlasticSkeletonDeformation::Imp  definition
Toshihiro Shimizu 890ddd
//**************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class PlasticSkeletonDeformation::Imp final : public TParamObserver {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  PlasticSkeletonDeformation *m_back;  //!< Back-pointer to the interface class
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SkeletonSet m_skeletons;  //!< Skeletons owned by the deformation
Shinya Kitaoka 120a6e
  SkVDSet m_vds;            //!< Container of vertex deformations
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TDoubleParamP m_skelIdsParam;  //!< Curve of skeleton ids by xsheet frame
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::set<tparamobserver *=""></tparamobserver>
Shinya Kitaoka 120a6e
      m_observers;  //!< Set of the deformation's observers
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TSyntax::Grammar
Shinya Kitaoka 120a6e
      *m_grammar;  //!< The params' grammar. Weird though - it's a VERY
Shinya Kitaoka 120a6e
                   //!< occult requirement to TDoubleParams...
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // NOTE: There \a is a deformation even for a skeleton's root node. This is
Shinya Kitaoka 120a6e
  // now required due to the
Shinya Kitaoka 120a6e
  // onwership of \a multiple skeletons at once. However, its angle and distance
Shinya Kitaoka 120a6e
  // params will be unused.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  Imp(PlasticSkeletonDeformation *back);
Shinya Kitaoka 120a6e
  ~Imp();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  Imp(PlasticSkeletonDeformation *back, const Imp &other);
Shinya Kitaoka 120a6e
  Imp &operator=(const Imp &other);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  PlasticSkeleton &skeleton(int skelId) const;
Shinya Kitaoka 120a6e
  SkVD &vertexDeformation(const QString &name) const;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void attach(int skeletonId, PlasticSkeleton *skeleton);
Shinya Kitaoka 120a6e
  void detach(int skeletonId);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void attachVertex(const QString &name, int skelId, int v);
Shinya Kitaoka 120a6e
  void detachVertex(const QString &name, int skelId, int v);
Shinya Kitaoka 120a6e
  void rebindVertex(const QString &name, int skelId, const QString &newName);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void touchParams(SkVD &vd);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //! Applies stored vertex deformations to the skeleton branch starting at v
Shinya Kitaoka 120a6e
  void updateBranchPositions(const PlasticSkeleton &originalSkeleton,
Shinya Kitaoka 120a6e
                             PlasticSkeleton &deformedSkeleton, double frame,
Shinya Kitaoka 120a6e
                             int v);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 38fd86
  void onChange(
Shinya Kitaoka 38fd86
      const TParamChange &change) override;  // Passes param notifications to
Shinya Kitaoka 38fd86
                                             // external observers
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  // Not directly copy-constructible
Shinya Kitaoka 120a6e
  Imp(const Imp &other);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PlasticSkeletonDeformation::Imp::Imp(PlasticSkeletonDeformation *back)
Shinya Kitaoka 120a6e
    : m_back(back), m_skelIdsParam(1.0), m_grammar() {
Shinya Kitaoka 120a6e
  m_skelIdsParam->setName("Skeleton Id");
Shinya Kitaoka 120a6e
  m_skelIdsParam->addObserver(this);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticSkeletonDeformation::Imp::~Imp() {
Shinya Kitaoka 120a6e
  m_skelIdsParam->removeObserver(this);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SkVDSet::iterator dt, dEnd(m_vds.end());
Shinya Kitaoka 120a6e
  for (dt = m_vds.begin(); dt != dEnd; ++dt)
Shinya Kitaoka 120a6e
    for (int p = 0; p < SkVD::PARAMS_COUNT; ++p)
Shinya Kitaoka 120a6e
      dt->m_vd.m_params[p]->removeObserver(this);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticSkeletonDeformation::Imp::Imp(PlasticSkeletonDeformation *back,
Shinya Kitaoka 120a6e
                                     const Imp &other)
Shinya Kitaoka 120a6e
    : m_back(back), m_skelIdsParam(other.m_skelIdsParam->clone()), m_grammar() {
Shinya Kitaoka 120a6e
  m_skelIdsParam->setGrammar(m_grammar);
Shinya Kitaoka 120a6e
  m_skelIdsParam->addObserver(this);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Clone the skeletons
Shinya Kitaoka 120a6e
  SkeletonSet::const_iterator st, sEnd(other.m_skeletons.end());
Shinya Kitaoka 120a6e
  for (st = other.m_skeletons.begin(); st != sEnd; ++st)
Shinya Kitaoka 120a6e
    m_skeletons.insert(SkeletonSet::value_type(
Shinya Kitaoka 120a6e
        st->get_left(), new PlasticSkeleton(*st->get_right())));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Clone each parameters curve
Shinya Kitaoka 120a6e
  SkVD vd;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SkVDSet::const_iterator dt, dEnd(other.m_vds.end());
Shinya Kitaoka 120a6e
  for (dt = other.m_vds.begin(); dt != dEnd; ++dt) {
Shinya Kitaoka 120a6e
    VDKey vdKey = {dt->m_name, dt->m_hookNumber, dt->m_vIndices};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    for (int p = 0; p < SkVD::PARAMS_COUNT; ++p) {
Shinya Kitaoka 120a6e
      TDoubleParamP ¶m = vdKey.m_vd.m_params[p];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      param = TDoubleParamP(dt->m_vd.m_params[p]->clone());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      param->setGrammar(m_grammar);
Shinya Kitaoka 120a6e
      param->addObserver(this);
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_vds.insert(vdKey);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticSkeletonDeformation::Imp &PlasticSkeletonDeformation::Imp::operator=(
Shinya Kitaoka 120a6e
    const Imp &other) {
Shinya Kitaoka 120a6e
  *m_skelIdsParam = *other.m_skelIdsParam;
Shinya Kitaoka 120a6e
  m_skelIdsParam->setGrammar(m_grammar);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Take in all curves whose name matches one of the stored ones
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Traverse known curves
Shinya Kitaoka 120a6e
  SkVDSet::iterator dt, dEnd(m_vds.end());
Shinya Kitaoka 120a6e
  SkVDSet::const_iterator st, sEnd(other.m_vds.end());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (dt = m_vds.begin(); dt != dEnd; ++dt) {
Shinya Kitaoka 120a6e
    // Search a corresponding curve in the input ones
Shinya Kitaoka 120a6e
    st = other.m_vds.find(dt->m_name);
Shinya Kitaoka 120a6e
    if (st != sEnd)
Shinya Kitaoka 120a6e
      for (int p = 0; p < SkVD::PARAMS_COUNT; ++p) {
Shinya Kitaoka 120a6e
        TDoubleParam ¶m = *dt->m_vd.m_params[p];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        param = *st->m_vd.m_params[p];
Shinya Kitaoka 120a6e
        param.setGrammar(m_grammar);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return *this;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticSkeleton &PlasticSkeletonDeformation::Imp::skeleton(int skelId) const {
Shinya Kitaoka 120a6e
  SkeletonSet::left_map::const_iterator st(m_skeletons.left.find(skelId));
Shinya Kitaoka 120a6e
  assert(st != m_skeletons.left.end());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return *st->second;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
SkVD &PlasticSkeletonDeformation::Imp::vertexDeformation(
Shinya Kitaoka 120a6e
    const QString &name) const {
Shinya Kitaoka 120a6e
  SkVDSet::const_iterator vdt(m_vds.find(name));
Shinya Kitaoka 120a6e
  assert(vdt != m_vds.end());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return vdt->m_vd;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::Imp::attach(int skeletonId,
Shinya Kitaoka 120a6e
                                             PlasticSkeleton *skeleton) {
Shinya Kitaoka 120a6e
  assert(skeleton);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Store the skeleton - acquires shared ownership
Shinya Kitaoka 120a6e
  assert(m_skeletons.left.find(skeletonId) == m_skeletons.left.end());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_skeletons.insert(SkeletonSet::value_type(skeletonId, skeleton));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Deal with vertex deformations and parameter defaults
Shinya Kitaoka 120a6e
  tcg::list<plasticskeleton::vertex_type> &vertices = skeleton->vertices();</plasticskeleton::vertex_type>
Shinya Kitaoka 120a6e
  if (!vertices.empty()) {
Shinya Kitaoka 120a6e
    tcg::list<plasticskeletonvertex>::iterator vt, vEnd(vertices.end());</plasticskeletonvertex>
Shinya Kitaoka 120a6e
    for (vt = vertices.begin(); vt != vEnd; ++vt)
Shinya Kitaoka 120a6e
      attachVertex(vt->name(), skeletonId, vt.index());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::Imp::detach(int skeletonId) {
Shinya Kitaoka 120a6e
  // First, detach all vertices
Shinya Kitaoka 120a6e
  tcg::list<plasticskeleton::vertex_type> &vertices =</plasticskeleton::vertex_type>
Shinya Kitaoka 120a6e
      skeleton(skeletonId).vertices();
Shinya Kitaoka 120a6e
  if (!vertices.empty()) {
Shinya Kitaoka 120a6e
    tcg::list<plasticskeletonvertex>::iterator vt, vEnd(vertices.end());</plasticskeletonvertex>
Shinya Kitaoka 120a6e
    for (vt = vertices.begin(); vt != vEnd; ++vt)
Shinya Kitaoka 120a6e
      detachVertex(vt->name(), skeletonId, vt.index());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Then, release the skeleton itself
Shinya Kitaoka 120a6e
  m_skeletons.left.erase(skeletonId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::Imp::attachVertex(const QString &name,
Shinya Kitaoka 120a6e
                                                   int skelId, int v) {
Shinya Kitaoka 120a6e
  struct locals {
Shinya Kitaoka 120a6e
    static int newHookNumber(Imp *imp) {
Shinya Kitaoka 120a6e
      int h = 1;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      SkVDByHookNumber::iterator vdt, vdEnd(imp->m_vds.get<int>().end());</int>
Shinya Kitaoka 120a6e
      for (vdt = imp->m_vds.get<int>().begin();</int>
Shinya Kitaoka 120a6e
           vdt != vdEnd && vdt->m_hookNumber == h; ++vdt, ++h)
Shinya Kitaoka 120a6e
        ;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      return h;
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  };  // locals
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Insert a new VD if necessary
Shinya Kitaoka 120a6e
  SkVDSet::iterator vdt(m_vds.find(name));
Shinya Kitaoka 120a6e
  if (vdt == m_vds.end()) {
Shinya Kitaoka 120a6e
    VDKey vdKey = {name, locals::newHookNumber(this)};
Shinya Kitaoka 120a6e
    touchParams(vdKey.m_vd);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    vdt = m_vds.insert(vdKey).first;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Register (skelId, v) on the vd
Shinya Kitaoka 120a6e
  vdt->m_vIndices.insert(std::make_pair(skelId, v));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::Imp::detachVertex(const QString &name,
Shinya Kitaoka 120a6e
                                                   int skelId, int v) {
Shinya Kitaoka 120a6e
  SkVDSet::iterator vdt = m_vds.find(name);
Shinya Kitaoka 120a6e
  assert(vdt != m_vds.end());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Unregister skelId
Shinya Kitaoka 120a6e
  int count = vdt->m_vIndices.erase(skelId);
Shinya Kitaoka 120a6e
  assert(count > 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (vdt->m_vIndices.empty()) {
Shinya Kitaoka 120a6e
    // De-register as vdt's observer, and release it from stored vds
Shinya Kitaoka 120a6e
    SkVD &vd = vdt->m_vd;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    for (int p = 0; p < SkVD::PARAMS_COUNT; ++p)
Shinya Kitaoka 120a6e
      vd.m_params[p]->removeObserver(this);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_vds.erase(vdt);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::Imp::rebindVertex(const QString &name,
Shinya Kitaoka 120a6e
                                                   int skelId,
Shinya Kitaoka 120a6e
                                                   const QString &newName) {
Shinya Kitaoka 120a6e
  if (name == newName) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SkVDSet::iterator oldVdt = m_vds.find(name);
Shinya Kitaoka 120a6e
  if (oldVdt == m_vds.end()) return;  // We get here when creating a new vertex
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::map<int, int="">::iterator vit = oldVdt->m_vIndices.find(skelId);</int,>
Shinya Kitaoka 120a6e
  assert(vit != oldVdt->m_vIndices.end());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int v = vit->second;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SkVDSet::iterator newVdt = m_vds.find(newName);
Shinya Kitaoka 120a6e
  if (newVdt != m_vds.end()) {
Shinya Kitaoka 120a6e
    detachVertex(name, skelId, v);
Shinya Kitaoka 120a6e
    attachVertex(newName, skelId, v);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    // Creating a new vd entry
Shinya Kitaoka 120a6e
    if (oldVdt->m_vIndices.size() == 1) {
Shinya Kitaoka 120a6e
      // The old entry should be removed - it is actually *purely* renamed
Shinya Kitaoka 120a6e
      VDKey vdKey(*oldVdt);
Shinya Kitaoka 120a6e
      vdKey.m_name = newName;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      m_vds.erase(name);
Shinya Kitaoka 120a6e
      m_vds.insert(vdKey);
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      // The old entry remains - and data must be copied from there
Shinya Kitaoka 120a6e
      detachVertex(name, skelId, v);
Shinya Kitaoka 120a6e
      attachVertex(newName, skelId, v);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      newVdt = m_vds.find(newName);  // Fetch the newly created vd
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      // Copy the existing vd into the new one
Shinya Kitaoka 120a6e
      SkVD &oldVd = oldVdt->m_vd, &newVd = newVdt->m_vd;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      int p, pCount = SkVD::PARAMS_COUNT;
Shinya Kitaoka 120a6e
      for (p = 0; p != pCount; ++p) *newVd.m_params[p] = *oldVd.m_params[p];
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::Imp::touchParams(SkVD &vd) {
Shinya Kitaoka 120a6e
  for (int p = 0; p < SkVD::PARAMS_COUNT; ++p) {
Shinya Kitaoka 120a6e
    if (vd.m_params[p]) continue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TDoubleParam *param = new TDoubleParam;
Shinya Kitaoka 120a6e
    param->setName(parNames[p]);
Shinya Kitaoka 120a6e
    param->setMeasureName(parMeasures[p]);
Shinya Kitaoka 120a6e
    param->setGrammar(m_grammar);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    vd.m_params[p] = param;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    param->addObserver(this);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::Imp::onChange(const TParamChange &change) {
Shinya Kitaoka 120a6e
  // Since the deformation was changed, any associated deformer
Shinya Kitaoka 120a6e
  // must be invalidated (at the animation-deform level only)
Shinya Kitaoka 120a6e
  PlasticDeformerStorage::instance()->invalidateDeformation(
Shinya Kitaoka 120a6e
      m_back, PlasticDeformerStorage::NONE);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Propagate notification to this object's observers
Shinya Kitaoka 120a6e
  std::set<tparamobserver *="">::iterator ot, oEnd(m_observers.end());</tparamobserver>
Shinya Kitaoka 120a6e
  for (ot = m_observers.begin(); ot != oEnd; ++ot) (*ot)->onChange(change);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PlasticSkeletonDeformation::Imp::updateBranchPositions(
Shinya Kitaoka 120a6e
    const PlasticSkeleton &originalSkeleton, PlasticSkeleton &deformedSkeleton,
Shinya Kitaoka 120a6e
    double frame, int v) {
Shinya Kitaoka 120a6e
  struct locals {
Shinya Kitaoka 120a6e
    static void buildParentDirection(const PlasticSkeleton &skel, int v,
Shinya Kitaoka 120a6e
                                     TPointD &dir) {
Shinya Kitaoka 120a6e
      assert(v >= 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      const PlasticSkeletonVertex &vx = skel.vertex(v);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      int vParent = vx.parent();
Shinya Kitaoka 120a6e
      if (vParent < 0) return;  // dir remains as passed
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      const TPointD &dir_ =
Shinya Kitaoka 120a6e
          tcg::point_ops::direction(skel.vertex(vParent).P(), vx.P(), 1e-4);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      if (dir_ != tcg::point_ops::NaP<tpointd>())</tpointd>
Shinya Kitaoka 120a6e
        dir = dir_;
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        buildParentDirection(skel, vParent, dir);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  };  // locals
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  PlasticSkeletonVertex &dvx = deformedSkeleton.vertex(v);
Shinya Kitaoka 120a6e
  int vParent                = dvx.parent();
Shinya Kitaoka 120a6e
  if (vParent >= 0) {
Shinya Kitaoka 120a6e
    // Rebuild vertex position
Shinya Kitaoka 120a6e
    const TPointD &ovxPos       = originalSkeleton.vertex(v).P();
Shinya Kitaoka 120a6e
    const TPointD &ovxParentPos = originalSkeleton.vertex(vParent).P();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Start by getting the polar reference
Shinya Kitaoka 120a6e
    TPointD oDir(1.0, 0.0), dDir(1.0, 0.0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    locals::buildParentDirection(originalSkeleton, vParent, oDir);
Shinya Kitaoka 120a6e
    locals::buildParentDirection(deformedSkeleton, vParent, dDir);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Now, rebuild vx's position
Shinya Kitaoka 120a6e
    const SkVD &vd = m_vds.find(dvx.name())->m_vd;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    double a = tcg::point_ops::angle(oDir, ovxPos - ovxParentPos) * M_180_PI;
Shinya Kitaoka 120a6e
    double d = tcg::point_ops::dist(ovxParentPos, ovxPos);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    double aDelta = vd.m_params[SkVD::ANGLE]->getValue(frame);
Shinya Kitaoka 120a6e
    double dDelta = vd.m_params[SkVD::DISTANCE]->getValue(frame);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    dvx.P() = deformedSkeleton.vertex(vParent).P() +
Shinya Kitaoka 120a6e
              (d + dDelta) * (TRotation(a + aDelta) * dDir);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Finally, update children positions
Shinya Kitaoka 120a6e
  PlasticSkeleton::vertex_type::edges_iterator et, eEnd(dvx.edgesEnd());
Shinya Kitaoka 120a6e
  for (et = dvx.edgesBegin(); et != eEnd; ++et) {
Shinya Kitaoka 120a6e
    int vChild = deformedSkeleton.edge(*et).vertex(1);
Shinya Kitaoka 120a6e
    if (vChild == v) continue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    updateBranchPositions(originalSkeleton, deformedSkeleton, frame, vChild);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**************************************************************************************
Toshihiro Shimizu 890ddd
//    PlasticSkeletonDeformation  implementation
Toshihiro Shimizu 890ddd
//**************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PlasticSkeletonDeformation::PlasticSkeletonDeformation()
Shinya Kitaoka 120a6e
    : m_imp(new Imp(this)) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticSkeletonDeformation::PlasticSkeletonDeformation(
Shinya Kitaoka 120a6e
    const PlasticSkeletonDeformation &other)
Shinya Kitaoka 120a6e
    : TSmartObject(m_classCode), m_imp(new Imp(this, *other.m_imp)) {
Shinya Kitaoka 120a6e
  // Register deformation
Shinya Kitaoka 120a6e
  SkeletonSet::iterator st, sEnd(m_imp->m_skeletons.end());
Shinya Kitaoka 120a6e
  for (st = m_imp->m_skeletons.begin(); st != sEnd; ++st)
Shinya Kitaoka 120a6e
    st->get_right()->addListener(this);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticSkeletonDeformation::~PlasticSkeletonDeformation() {
Shinya Kitaoka 120a6e
  // Unregister deformation
Shinya Kitaoka 120a6e
  SkeletonSet::iterator st, sEnd(m_imp->m_skeletons.end());
Shinya Kitaoka 120a6e
  for (st = m_imp->m_skeletons.begin(); st != sEnd; ++st)
Shinya Kitaoka 120a6e
    st->get_right()->removeListener(this);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticSkeletonDeformation &PlasticSkeletonDeformation::operator=(
Shinya Kitaoka 120a6e
    const PlasticSkeletonDeformation &other) {
Shinya Kitaoka 120a6e
  // The meaning of operator= is DIFFERENT from that implemented in the copy
Shinya Kitaoka 120a6e
  // constructor.
Shinya Kitaoka 120a6e
  // Skeletons are NOT cloned.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  *m_imp = *other.m_imp;
Shinya Kitaoka 120a6e
  return *this;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool PlasticSkeletonDeformation::empty() const {
Shinya Kitaoka 120a6e
  return m_imp->m_skeletons.empty();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int PlasticSkeletonDeformation::skeletonsCount() const {
Shinya Kitaoka 120a6e
  return m_imp->m_skeletons.size();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::skeletonIds(skelId_iterator &begin,
Shinya Kitaoka 120a6e
                                             skelId_iterator &end) const {
otakuto 91a93e
  auto const f = [](const SkeletonSet::left_map::value_type &val) {
otakuto 91a93e
    return val.first;
otakuto 91a93e
  };
Toshihiro Shimizu 890ddd
otakuto 91a93e
  begin = boost::make_transform_iterator(m_imp->m_skeletons.left.begin(), f);
otakuto 91a93e
  end   = boost::make_transform_iterator(m_imp->m_skeletons.left.end(), f);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TDoubleParamP PlasticSkeletonDeformation::skeletonIdsParam() const {
Shinya Kitaoka 120a6e
  return m_imp->m_skelIdsParam;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticSkeletonP PlasticSkeletonDeformation::skeleton(double frame) const {
Shinya Kitaoka 120a6e
  return skeleton(skeletonId(frame));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int PlasticSkeletonDeformation::skeletonId(double frame) const {
Shinya Kitaoka 120a6e
  return m_imp->m_skelIdsParam->getValue(frame);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::attach(int skeletonId,
Shinya Kitaoka 120a6e
                                        PlasticSkeleton *skeleton) {
Shinya Kitaoka 120a6e
  m_imp->attach(skeletonId, skeleton);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  skeleton->addListener(this);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::detach(int skeletonId) {
Shinya Kitaoka 120a6e
  SkeletonSet::left_map::iterator st(m_imp->m_skeletons.left.find(skeletonId));
Shinya Kitaoka 120a6e
  if (st != m_imp->m_skeletons.left.end()) {
Shinya Kitaoka 120a6e
    st->second->removeListener(this);
Shinya Kitaoka 120a6e
    m_imp->detach(skeletonId);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticSkeletonP PlasticSkeletonDeformation::skeleton(int skeletonId) const {
Shinya Kitaoka 120a6e
  SkeletonSet::left_map::const_iterator st =
Shinya Kitaoka 120a6e
      m_imp->m_skeletons.left.find(skeletonId);
Shinya Kitaoka 120a6e
  return (st == m_imp->m_skeletons.left.end()) ? PlasticSkeletonP()
Shinya Kitaoka 120a6e
                                               : st->second;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int PlasticSkeletonDeformation::skeletonId(PlasticSkeleton *skeleton) const {
Shinya Kitaoka 120a6e
  SkeletonSet::right_map::const_iterator st =
Shinya Kitaoka 120a6e
      m_imp->m_skeletons.right.find(skeleton);
Shinya Kitaoka 120a6e
  return (st == m_imp->m_skeletons.right.end())
Shinya Kitaoka 120a6e
             ? -(std::numeric_limits<int>::max)()</int>
Shinya Kitaoka 120a6e
             : st->second;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int PlasticSkeletonDeformation::vertexDeformationsCount() const {
Shinya Kitaoka 120a6e
  return m_imp->m_vds.size();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
SkVD *PlasticSkeletonDeformation::vertexDeformation(
Shinya Kitaoka 120a6e
    const QString &vxName) const {
Shinya Kitaoka 120a6e
  SkVDSet::const_iterator vdt = m_imp->m_vds.find(vxName);
Shinya Kitaoka 120a6e
  return (vdt == m_imp->m_vds.end()) ? (SkVD *)0 : &vdt->m_vd;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
SkVD *PlasticSkeletonDeformation::vertexDeformation(int skelId, int v) const {
Shinya Kitaoka 120a6e
  const QString &name = skeleton(skelId)->vertex(v).name();
Shinya Kitaoka 120a6e
  return vertexDeformation(name);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::vertexDeformations(vd_iterator &begin,
Shinya Kitaoka 120a6e
                                                    vd_iterator &end) const {
otakuto 91a93e
  auto const f = [](const VDKey &vdKey) {
otakuto 91a93e
    return std::make_pair(&vdKey.m_name, &vdKey.m_vd);
otakuto 91a93e
  };
Toshihiro Shimizu 890ddd
otakuto 91a93e
  begin = boost::make_transform_iterator(m_imp->m_vds.begin(), f);
otakuto 91a93e
  end   = boost::make_transform_iterator(m_imp->m_vds.end(), f);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PlasticSkeletonDeformation::vdSkeletonVertices(const QString &vertexName,
Shinya Kitaoka 120a6e
                                                    vx_iterator &begin,
Shinya Kitaoka 120a6e
                                                    vx_iterator &end) const {
otakuto 91a93e
  auto const f = [](const std::map<int, int="">::value_type &val) {</int,>
otakuto 91a93e
    return std::make_pair(val.first, val.second);
otakuto 91a93e
  };
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SkVDSet::const_iterator nt(m_imp->m_vds.find(vertexName));
Toshihiro Shimizu 890ddd
otakuto 91a93e
  if (nt == m_imp->m_vds.end()) {
otakuto 91a93e
    begin = vx_iterator();
otakuto 91a93e
    end   = vx_iterator();
otakuto 91a93e
  } else {
otakuto 91a93e
    begin = boost::make_transform_iterator(nt->m_vIndices.begin(), f);
otakuto 91a93e
    end   = boost::make_transform_iterator(nt->m_vIndices.end(), f);
otakuto 91a93e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int PlasticSkeletonDeformation::hookNumber(const QString &name) const {
Shinya Kitaoka 120a6e
  SkVDSet::const_iterator nt(m_imp->m_vds.find(name));
Shinya Kitaoka 120a6e
  return (nt == m_imp->m_vds.end()) ? -1 : nt->m_hookNumber;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int PlasticSkeletonDeformation::hookNumber(int skelId, int v) const {
Shinya Kitaoka 120a6e
  const QString &name = skeleton(skelId)->vertex(v).name();
Shinya Kitaoka 120a6e
  return hookNumber(name);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
QString PlasticSkeletonDeformation::vertexName(int hookNumber) const {
Shinya Kitaoka 120a6e
  const SkVDByHookNumber &vds = m_imp->m_vds.get<int>();</int>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SkVDByHookNumber::const_iterator ht(vds.find(hookNumber));
Shinya Kitaoka 120a6e
  return (ht == vds.end()) ? QString() : ht->m_name;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int PlasticSkeletonDeformation::vertexIndex(int hookNumber, int skelId) const {
Shinya Kitaoka 120a6e
  const SkVDByHookNumber &vds = m_imp->m_vds.get<int>();</int>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SkVDByHookNumber::const_iterator ht(vds.find(hookNumber));
Shinya Kitaoka 120a6e
  if (ht == vds.end()) return -1;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::map<int, int="">::const_iterator st(ht->m_vIndices.find(skelId));</int,>
Shinya Kitaoka 120a6e
  return (st == ht->m_vIndices.end()) ? -1 : st->second;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::getKeyframeAt(double frame,
Shinya Kitaoka 120a6e
                                               SkDKey &keyframe) const {
Shinya Kitaoka 120a6e
  keyframe.m_skelIdKeyframe = m_imp->m_skelIdsParam->getKeyframeAt(frame);
Shinya Kitaoka 120a6e
  keyframe.m_vertexKeyframes.clear();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SkVDSet::const_iterator dt, dEnd(m_imp->m_vds.end());
Shinya Kitaoka 120a6e
  for (dt = m_imp->m_vds.begin(); dt != dEnd; ++dt)
Shinya Kitaoka 120a6e
    keyframe.m_vertexKeyframes.insert(
Shinya Kitaoka 120a6e
        std::make_pair(dt->m_name, dt->m_vd.getKeyframe(frame)));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::setKeyframe(double frame) {
Shinya Kitaoka 120a6e
  m_imp->m_skelIdsParam->setKeyframe(frame);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SkVDSet::iterator dt, dEnd(m_imp->m_vds.end());
Shinya Kitaoka 120a6e
  for (dt = m_imp->m_vds.begin(); dt != dEnd; ++dt) dt->m_vd.setKeyframe(frame);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool PlasticSkeletonDeformation::setKeyframe(const SkDKey &keyframe) {
Shinya Kitaoka 120a6e
  bool keyWasSet = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (keyframe.m_skelIdKeyframe.m_isKeyframe) {
Shinya Kitaoka 120a6e
    m_imp->m_skelIdsParam->setKeyframe(keyframe.m_skelIdKeyframe);
Shinya Kitaoka 120a6e
    keyWasSet = true;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const std::map<qstring, skvd::keyframe=""> &vdKeys = keyframe.m_vertexKeyframes;</qstring,>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Iterate the keyframe's vertex deformations
Shinya Kitaoka 120a6e
  std::map<qstring, skvd::keyframe="">::const_iterator kt, kEnd(vdKeys.end());</qstring,>
Shinya Kitaoka 120a6e
  for (kt = vdKeys.begin(); kt != vdKeys.end(); ++kt) {
Shinya Kitaoka 120a6e
    // Search for a corresponding vertex deformation among stored ones
Shinya Kitaoka 120a6e
    SkVDSet::iterator vdt = m_imp->m_vds.find(kt->first);
Shinya Kitaoka 120a6e
    if (vdt != m_imp->m_vds.end()) {
Shinya Kitaoka 120a6e
      // Set the corresponding keyframe
Shinya Kitaoka 120a6e
      keyWasSet = vdt->m_vd.setKeyframe(kt->second) || keyWasSet;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return keyWasSet;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool PlasticSkeletonDeformation::setKeyframe(const SkDKey &keyframe,
Shinya Kitaoka 120a6e
                                             double frame, double easeIn,
Shinya Kitaoka 120a6e
                                             double easeOut) {
Shinya Kitaoka 120a6e
  bool keyWasSet = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (keyframe.m_skelIdKeyframe.m_isKeyframe) {
Shinya Kitaoka 120a6e
    TDoubleKeyframe kf(keyframe.m_skelIdKeyframe);
Shinya Kitaoka 120a6e
    kf.m_frame = frame;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_imp->m_skelIdsParam->setKeyframe(kf);
Shinya Kitaoka 120a6e
    keyWasSet = true;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const std::map<qstring, skvd::keyframe=""> &vdKeys = keyframe.m_vertexKeyframes;</qstring,>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Iterate the keyframe's vertex deformations
Shinya Kitaoka 120a6e
  std::map<qstring, skvd::keyframe="">::const_iterator kt, kEnd(vdKeys.end());</qstring,>
Shinya Kitaoka 120a6e
  for (kt = vdKeys.begin(); kt != vdKeys.end(); ++kt) {
Shinya Kitaoka 120a6e
    // Search for a corresponding vertex deformation among stored ones
Shinya Kitaoka 120a6e
    SkVDSet::iterator vdt = m_imp->m_vds.find(kt->first);
Shinya Kitaoka 120a6e
    if (vdt != m_imp->m_vds.end()) {
Shinya Kitaoka 120a6e
      // Set the corresponding keyframe
Shinya Kitaoka 120a6e
      keyWasSet = vdt->m_vd.setKeyframe(kt->second, frame, easeIn, easeOut) ||
Shinya Kitaoka 120a6e
                  keyWasSet;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return keyWasSet;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool PlasticSkeletonDeformation::isKeyframe(double frame) const {
Shinya Kitaoka 120a6e
  if (m_imp->m_skelIdsParam->isKeyframe(frame)) return true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SkVDSet::const_iterator dt, dEnd(m_imp->m_vds.end());
Shinya Kitaoka 120a6e
  for (dt = m_imp->m_vds.begin(); dt != dEnd; ++dt)
Shinya Kitaoka 120a6e
    if (dt->m_vd.isKeyframe(frame)) return true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool PlasticSkeletonDeformation::isFullKeyframe(double frame) const {
Shinya Kitaoka 120a6e
  if (!m_imp->m_skelIdsParam->isKeyframe(frame)) return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SkVDSet::const_iterator dt, dEnd(m_imp->m_vds.end());
Shinya Kitaoka 120a6e
  for (dt = m_imp->m_vds.begin(); dt != dEnd; ++dt)
Shinya Kitaoka 120a6e
    if (!dt->m_vd.isFullKeyframe(frame)) return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::deleteKeyframe(double frame) {
Shinya Kitaoka 120a6e
  m_imp->m_skelIdsParam->deleteKeyframe(frame);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SkVDSet::iterator dt, dEnd(m_imp->m_vds.end());
Shinya Kitaoka 120a6e
  for (dt = m_imp->m_vds.begin(); dt != dEnd; ++dt)
Shinya Kitaoka 120a6e
    dt->m_vd.deleteKeyframe(frame);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::storeDeformedSkeleton(
Shinya Kitaoka 120a6e
    int skelId, double frame, PlasticSkeleton &skeleton) const {
Shinya Kitaoka 120a6e
  // Copy the un-deformed skeleton to the output one
Shinya Kitaoka 120a6e
  const PlasticSkeletonP &origSkel = this->skeleton(skelId);
Shinya Kitaoka 120a6e
  skeleton                         = origSkel ? *origSkel : PlasticSkeleton();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Update the skeleton to the specified frame
Shinya Kitaoka 120a6e
  if (!skeleton.vertices().empty())
Shinya Kitaoka 120a6e
    m_imp->updateBranchPositions(*origSkel, skeleton, frame,
Shinya Kitaoka 120a6e
                                 skeleton.vertices().begin().m_idx);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PlasticSkeletonDeformation::updatePosition(
Shinya Kitaoka 120a6e
    const PlasticSkeleton &originalSkeleton, PlasticSkeleton &deformedSkeleton,
Shinya Kitaoka 120a6e
    double frame, int v, const TPointD &pos) {
Shinya Kitaoka 120a6e
  const PlasticSkeletonVertex &vx = deformedSkeleton.vertex(v);
Shinya Kitaoka 120a6e
  int vParent                     = vx.parent();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const TPointD &vParentPos = deformedSkeleton.vertex(vParent).P();
Shinya Kitaoka 120a6e
  const TPointD &vPos       = deformedSkeleton.vertex(v).P();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SkVD &vd = m_imp->m_vds.find(vx.name())->m_vd;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // NOTE: The following aDelta calculation should be done as a true difference
Shinya Kitaoka 120a6e
  // - this is still ok and spares
Shinya Kitaoka 120a6e
  // access to v's grandParent...
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double aDelta = tcg::point_ops::angle(vPos - vParentPos, pos - vParentPos) *
Shinya Kitaoka 120a6e
                  M_180_PI,
Shinya Kitaoka 120a6e
         dDelta = tcg::point_ops::dist(vParentPos, pos) -
Shinya Kitaoka 120a6e
                  tcg::point_ops::dist(vParentPos, vPos),
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
         a = tcrop(vd.m_params[SkVD::ANGLE]->getValue(frame) + aDelta,
Shinya Kitaoka 120a6e
                   vx.m_minAngle, vx.m_maxAngle),
Shinya Kitaoka 120a6e
         d = vd.m_params[SkVD::DISTANCE]->getValue(frame) + dDelta;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  vd.m_params[SkVD::ANGLE]->setValue(frame, a);
Shinya Kitaoka 120a6e
  vd.m_params[SkVD::DISTANCE]->setValue(frame, d);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp->updateBranchPositions(originalSkeleton, deformedSkeleton, frame, v);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PlasticSkeletonDeformation::updateAngle(
Shinya Kitaoka 120a6e
    const PlasticSkeleton &originalSkeleton, PlasticSkeleton &deformedSkeleton,
Shinya Kitaoka 120a6e
    double frame, int v, const TPointD &pos) {
Shinya Kitaoka 120a6e
  const PlasticSkeletonVertex &vx = deformedSkeleton.vertex(v);
Shinya Kitaoka 120a6e
  int vParent                     = vx.parent();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const TPointD &vParentPos = deformedSkeleton.vertex(vParent).P();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // No need to access the grandParent, we're making the diff against the old vx
Shinya Kitaoka 120a6e
  // position
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SkVD &vd = m_imp->m_vds.find(vx.name())->m_vd;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double aDelta = tcg::point_ops::angle(vx.P() - vParentPos, pos - vParentPos) *
Shinya Kitaoka 120a6e
                  M_180_PI,
Shinya Kitaoka 120a6e
         a = tcrop(vd.m_params[SkVD::ANGLE]->getValue(frame) + aDelta,
Shinya Kitaoka 120a6e
                   vx.m_minAngle, vx.m_maxAngle);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  vd.m_params[SkVD::ANGLE]->setValue(frame, a);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp->updateBranchPositions(originalSkeleton, deformedSkeleton, frame, v);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::addVertex(PlasticSkeleton *skel, int v) {
Shinya Kitaoka 120a6e
  int skelId = skeletonId(skel);
Shinya Kitaoka 120a6e
  assert(skelId >= 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp->attachVertex(skel->vertex(v).name(), skelId, v);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::insertVertex(PlasticSkeleton *skel, int v) {
Shinya Kitaoka 120a6e
  int skelId = skeletonId(skel);
Shinya Kitaoka 120a6e
  assert(skelId >= 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp->attachVertex(skel->vertex(v).name(), skelId, v);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::deleteVertex(PlasticSkeleton *skel, int v) {
Shinya Kitaoka 120a6e
  assert(v > 0);  // Root should not be deleted
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int skelId = skeletonId(skel);
Shinya Kitaoka 120a6e
  assert(skelId >= 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Remove the vertex deformation associated with v
Shinya Kitaoka 120a6e
  m_imp->detachVertex(skel->vertex(v).name(), skelId, v);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::vertexNameChange(PlasticSkeleton *skel, int v,
Shinya Kitaoka 120a6e
                                                  const QString &newName) {
Shinya Kitaoka 120a6e
  int skelId = skeletonId(skel);
Shinya Kitaoka 120a6e
  assert(skelId >= 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp->rebindVertex(skel->vertex(v).name(), skelId, newName);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::clear(PlasticSkeleton *skel) {
Shinya Kitaoka 120a6e
  int skelId = skeletonId(skel);
Shinya Kitaoka 120a6e
  assert(skelId >= 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp->detach(skelId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::addObserver(TParamObserver *observer) {
Shinya Kitaoka 120a6e
  m_imp->m_observers.insert(observer);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::removeObserver(TParamObserver *observer) {
Shinya Kitaoka 120a6e
  m_imp->m_observers.erase(observer);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::setGrammar(TSyntax::Grammar *grammar) {
Shinya Kitaoka 120a6e
  SkVDSet::iterator vdt, vdEnd(m_imp->m_vds.end());
Shinya Kitaoka 120a6e
  for (vdt = m_imp->m_vds.begin(); vdt != vdEnd; ++vdt) {
Shinya Kitaoka 120a6e
    SkVD &vd = vdt->m_vd;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    for (int c = 0; c != SkVD::PARAMS_COUNT; ++c)
Shinya Kitaoka 120a6e
      vd.m_params[c]->setGrammar(grammar);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp->m_skelIdsParam->setGrammar(grammar);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp->m_grammar = grammar;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::saveData(TOStream &os) {
Shinya Kitaoka 120a6e
  // Save skeleton vertex deformations
Shinya Kitaoka 120a6e
  os.openChild("VertexDeforms");  // These are saved *before* skeletons
Shinya Kitaoka 120a6e
  {                               // ON PURPOSE - in loadData(), we'll
Shinya Kitaoka 120a6e
    SkVDSet::iterator vdt,
Shinya Kitaoka 120a6e
        vdEnd(m_imp->m_vds.end());  // attach() skeletons to a completely
Shinya Kitaoka 120a6e
    for (vdt = m_imp->m_vds.begin(); vdt != vdEnd;
Shinya Kitaoka 120a6e
         ++vdt)  // rebuilt set of vertex deformations.
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      os.child("Name") << vdt->m_name;
Shinya Kitaoka 120a6e
      os.child("Hook") << vdt->m_hookNumber;
Shinya Kitaoka 120a6e
      os.child("VD") << vdt->m_vd;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  os.closeChild();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Save skeleton ids param
Shinya Kitaoka 120a6e
  os.child("SkelIdsParam") << *m_imp->m_skelIdsParam;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Save skeletons
Shinya Kitaoka 120a6e
  os.openChild("Skeletons");
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    SkeletonSet::iterator st, sEnd(m_imp->m_skeletons.end());
Shinya Kitaoka 120a6e
    for (st = m_imp->m_skeletons.begin(); st != sEnd; ++st) {
Shinya Kitaoka 120a6e
      os.child("SkelId") << st->get_left();
Shinya Kitaoka 120a6e
      os.child("Skeleton") << *st->get_right();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  os.closeChild();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::loadData(TIStream &is) {
Shinya Kitaoka 120a6e
  if (is.getVersion() < VersionNumber(1, 21)) {
Shinya Kitaoka 120a6e
    loadData_prerelease(is);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int skeletonId;
Shinya Kitaoka 120a6e
  PlasticSkeleton *skeleton;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::string tagName;
Shinya Kitaoka 120a6e
  while (is.openChild(tagName)) {
Shinya Kitaoka 120a6e
    if (tagName == "VertexDeforms") {
Shinya Kitaoka 120a6e
      VDKey vKey;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      while (is.openChild(tagName)) {
Shinya Kitaoka 120a6e
        if (tagName == "Name")
Shinya Kitaoka 120a6e
          is >> vKey.m_name, is.matchEndTag();
Shinya Kitaoka 120a6e
        else if (tagName == "Hook")
Shinya Kitaoka 120a6e
          is >> vKey.m_hookNumber, is.matchEndTag();
Shinya Kitaoka 120a6e
        else if (tagName == "VD") {
Shinya Kitaoka 120a6e
          m_imp->touchParams(vKey.m_vd);
Shinya Kitaoka 120a6e
          is >> vKey.m_vd, is.matchEndTag();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
          m_imp->m_vds.insert(vKey);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
          vKey = VDKey();
Shinya Kitaoka 120a6e
        } else
Shinya Kitaoka 120a6e
          is.skipCurrentTag();
Shinya Kitaoka 120a6e
      }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      is.matchEndTag();
Shinya Kitaoka 120a6e
    } else if (tagName == "SkelIdsParam")
Shinya Kitaoka 120a6e
      is >> *m_imp->m_skelIdsParam, is.matchEndTag();
Shinya Kitaoka 120a6e
    else if (tagName == "Skeletons") {
Shinya Kitaoka 120a6e
      while (is.openChild(tagName)) {
Shinya Kitaoka 120a6e
        if (tagName == "SkelId")
Shinya Kitaoka 120a6e
          is >> skeletonId, is.matchEndTag();
Shinya Kitaoka 120a6e
        else if (tagName == "Skeleton") {
Shinya Kitaoka 120a6e
          skeleton = new PlasticSkeleton;
Shinya Kitaoka 120a6e
          is >> *skeleton, is.matchEndTag();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
          attach(skeletonId, skeleton);
Shinya Kitaoka 120a6e
          skeletonId = 0, skeleton = 0;
Shinya Kitaoka 120a6e
        } else
Shinya Kitaoka 120a6e
          is.skipCurrentTag();
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      is.matchEndTag();
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      is.skipCurrentTag();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
//------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
void PlasticSkeletonDeformation::loadData_prerelease(TIStream &is) {
Shinya Kitaoka 120a6e
  struct locals {
Shinya Kitaoka 120a6e
    static void buildParentDirection(const PlasticSkeleton &skel, int v,
Shinya Kitaoka 120a6e
                                     TPointD &dir) {
Shinya Kitaoka 120a6e
      assert(v >= 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      const PlasticSkeletonVertex &vx = skel.vertex(v);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int vParent = vx.parent();
Shinya Kitaoka 120a6e
      if (vParent < 0) return;  // dir remains as passed
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      const TPointD &dir_ =
Shinya Kitaoka 120a6e
          tcg::point_ops::direction(skel.vertex(vParent).P(), vx.P(), 1e-4);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (dir_ != tcg::point_ops::NaP<tpointd>())</tpointd>
Shinya Kitaoka 120a6e
        dir = dir_;
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        buildParentDirection(skel, vParent, dir);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //------------------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    static void adjust(SkD &sd, int v) {
Shinya Kitaoka 120a6e
      PlasticSkeleton &skeleton = *sd.skeleton(1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      PlasticSkeletonVertex &vx = skeleton.vertex(v);
Shinya Kitaoka 120a6e
      int vParent               = vx.parent();
Shinya Kitaoka 120a6e
      if (vParent >= 0) {
Shinya Kitaoka 120a6e
        // Rebuild vertex position
Shinya Kitaoka 120a6e
        const TPointD &vxPos       = skeleton.vertex(v).P();
Shinya Kitaoka 120a6e
        const TPointD &vxParentPos = skeleton.vertex(vParent).P();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        // Start by getting the polar reference
Shinya Kitaoka 120a6e
        TPointD dir(1.0, 0.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        buildParentDirection(skeleton, vParent, dir);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        // Now, rebuild vx's position
Shinya Kitaoka 120a6e
        SkVD &vd = sd.m_imp->m_vds.find(vx.name())->m_vd;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        double a = tcg::point_ops::angle(dir, vxPos - vxParentPos) * M_180_PI;
Shinya Kitaoka 120a6e
        double d = tcg::point_ops::dist(vxParentPos, vxPos);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        {
Shinya Kitaoka 120a6e
          TDoubleParamP param(vd.m_params[SkVD::ANGLE]);
Shinya Kitaoka 120a6e
          param->setDefaultValue(0.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          int k, kCount = param->getKeyframeCount();
Shinya Kitaoka 120a6e
          for (k = 0; k != kCount; ++k) {
Shinya Kitaoka 120a6e
            TDoubleKeyframe kf(param->getKeyframe(k));
Shinya Kitaoka 120a6e
            kf.m_value -= a;
Shinya Kitaoka 120a6e
            param->setKeyframe(k, kf);
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        {
Shinya Kitaoka 120a6e
          TDoubleParamP param(vd.m_params[SkVD::DISTANCE]);
Shinya Kitaoka 120a6e
          param->setDefaultValue(0.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          int k, kCount = param->getKeyframeCount();
Shinya Kitaoka 120a6e
          for (k = 0; k != kCount; ++k) {
Shinya Kitaoka 120a6e
            TDoubleKeyframe kf(param->getKeyframe(k));
Shinya Kitaoka 120a6e
            kf.m_value -= d;
Shinya Kitaoka 120a6e
            param->setKeyframe(k, kf);
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Finally, update children positions
Shinya Kitaoka 120a6e
      PlasticSkeleton::vertex_type::edges_iterator et, eEnd(vx.edgesEnd());
Shinya Kitaoka 120a6e
      for (et = vx.edgesBegin(); et != eEnd; ++et) {
Shinya Kitaoka 120a6e
        int vChild = skeleton.edge(*et).vertex(1);
Shinya Kitaoka 120a6e
        if (vChild == v) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        adjust(sd, vChild);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  };  // locals
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  PlasticSkeletonP skeleton(new PlasticSkeleton);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::string tagName;
Shinya Kitaoka 120a6e
  while (is.openChild(tagName)) {
Shinya Kitaoka 120a6e
    if (tagName == "Skeleton")
Shinya Kitaoka 120a6e
      is >> *skeleton, is.matchEndTag();
Shinya Kitaoka 120a6e
    else if (tagName == "VertexDeforms") {
Shinya Kitaoka 120a6e
      while (is.openChild(tagName)) {
Shinya Kitaoka 120a6e
        if (tagName == "VD") {
Shinya Kitaoka 120a6e
          VDKey vKey;
Shinya Kitaoka 120a6e
          m_imp->touchParams(vKey.m_vd);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
          is >> vKey.m_name, is >> vKey.m_vd;
Shinya Kitaoka 120a6e
          is.closeChild();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
          // Rebuild vKey's data from skeleton
Shinya Kitaoka 120a6e
          int v, vCount = skeleton->verticesCount();
Shinya Kitaoka 120a6e
          for (v = 0; v != vCount; ++v)
Shinya Kitaoka 120a6e
            if (skeleton->vertex(v).name() == vKey.m_name) break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          assert(v < vCount);
Shinya Kitaoka 120a6e
          vKey.m_hookNumber = skeleton->vertex(v).number();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          m_imp->m_vds.insert(vKey);
Shinya Kitaoka 120a6e
        } else
Shinya Kitaoka 120a6e
          is.skipCurrentTag();
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      is.matchEndTag();
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      is.skipCurrentTag();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  attach(1, skeleton.getPointer());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // SkVD params are now intended as deltas. Adjusting...
Shinya Kitaoka 120a6e
  locals::adjust(*this, 0);
Toshihiro Shimizu 890ddd
}