Shinya Kitaoka e5734a
#include <memory></memory>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzExt includes
Toshihiro Shimizu 890ddd
#include "ext/plasticskeleton.h"
Toshihiro Shimizu 890ddd
#include "ext/plasticskeletondeformation.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// STD includes
Toshihiro Shimizu 890ddd
#include <limits></limits>
Toshihiro Shimizu 890ddd
#include <map></map>
Toshihiro Shimizu 890ddd
#include <algorithm></algorithm>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Boost includes
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
Toshihiro Shimizu 890ddd
// Qt includes
Toshihiro Shimizu 890ddd
#include <qmutex></qmutex>
Toshihiro Shimizu 890ddd
#include <qmutexlocker></qmutexlocker>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "ext/plasticdeformerstorage.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
//    Storage multi-index map  definition
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef PlasticDeformerDataGroup DataGroup;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef std::pair<const *,="" int="" skd=""> DeformedSkeleton;</const>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct Key {
Shinya Kitaoka 120a6e
  const TMeshImage *m_mi;
Shinya Kitaoka 120a6e
  DeformedSkeleton m_ds;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::shared_ptr<datagroup> m_dataGroup;</datagroup>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  Key(const TMeshImage *mi, const SkD *sd, int skelId)
Shinya Kitaoka 120a6e
      : m_mi(mi), m_ds(sd, skelId), m_dataGroup() {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool operator<(const Key &other) const {
Shinya Kitaoka 120a6e
    return (m_mi < other.m_mi) ||
Shinya Kitaoka 120a6e
           ((!(other.m_mi < m_mi)) && (m_ds < other.m_ds));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace boost::multi_index;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
typedef boost::multi_index_container<
Shinya Kitaoka 120a6e
    Key, indexed_by<
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
             ordered_unique<identity<key>>,</identity<key>
Shinya Kitaoka 120a6e
             ordered_non_unique<tag<tmeshimage>,</tag<tmeshimage>
Shinya Kitaoka 120a6e
                                member<key, &key::m_mi="" *,="" const="" tmeshimage="">>,</key,>
Shinya Kitaoka 120a6e
             ordered_non_unique<tag<deformedskeleton>,</tag<deformedskeleton>
Shinya Kitaoka 120a6e
                                member<key, &key::m_ds="" deformedskeleton,="">></key,>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
             >>
Shinya Kitaoka 120a6e
    DeformersSet;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef DeformersSet::nth_index<0>::type DeformersByKey;
Toshihiro Shimizu 890ddd
typedef DeformersSet::index<tmeshimage>::type DeformersByMeshImage;</tmeshimage>
Toshihiro Shimizu 890ddd
typedef DeformersSet::index<deformedskeleton>::type DeformersByDeformedSkeleton;</deformedskeleton>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
//    Initialization stage  functions
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void initializeSO(PlasticDeformerData &data, const TTextureMeshP &mesh) {
Shinya Kitaoka 120a6e
  data.m_so.reset(new double[mesh->facesCount()]);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void initializeDeformerData(PlasticDeformerData &data,
Shinya Kitaoka 120a6e
                            const TTextureMeshP &mesh) {
Shinya Kitaoka 120a6e
  initializeSO(data, mesh);  // Allocates SO data
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Also, allocate suitable input-output arrays for the deformation
Shinya Kitaoka 120a6e
  data.m_output.reset(new double[2 * mesh->verticesCount()]);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void initializeDeformersData(DataGroup *group, const TMeshImage *meshImage) {
Shinya Kitaoka 120a6e
  group->m_datas.reset(new PlasticDeformerData[meshImage->meshes().size()]);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Push a PlasticDeformer for each mesh in the image
Shinya Kitaoka 120a6e
  const std::vector<ttexturemeshp> &meshes = meshImage->meshes();</ttexturemeshp>
Shinya Kitaoka 120a6e
  int fTotal                               = 0;  // Also count total # of faces
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int m, mCount = meshes.size();
Shinya Kitaoka 120a6e
  for (m = 0; m != mCount; ++m) {
Shinya Kitaoka 120a6e
    fTotal += meshes[m]->facesCount();
Shinya Kitaoka 120a6e
    initializeDeformerData(group->m_datas[m], meshes[m]);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Initialize the vector of sorted faces
Shinya Kitaoka 120a6e
  std::vector<std::pair<int, int="">> &sortedFaces = group->m_sortedFaces;</std::pair<int,>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  sortedFaces.reserve(fTotal);
Shinya Kitaoka 120a6e
  for (m = 0; m != mCount; ++m) {
Shinya Kitaoka 120a6e
    const TTextureMesh &mesh = *meshes[m];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    int f, fCount = mesh.facesCount();
Shinya Kitaoka 120a6e
    for (f = 0; f != fCount; ++f) sortedFaces.push_back(std::make_pair(f, m));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
//    Handle processing  functions
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void transformHandles(std::vector<plastichandle> &handles, const TAffine &aff) {</plastichandle>
Shinya Kitaoka 120a6e
  // Transforms handles through deformAff AND applies mi's dpi scale inverse
Shinya Kitaoka 120a6e
  std::vector<plastichandle>::size_type h, hCount = handles.size();</plastichandle>
Shinya Kitaoka 120a6e
  for (h = 0; h != hCount; ++h) handles[h].m_pos = aff * handles[h].m_pos;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void transformHandles(std::vector<tpointd> &handles, const TAffine &aff) {</tpointd>
Shinya Kitaoka 120a6e
  // Transforms handles through deformAff AND applies mi's dpi scale inverse
Shinya Kitaoka 120a6e
  std::vector<plastichandle>::size_type h, hCount = handles.size();</plastichandle>
Shinya Kitaoka 120a6e
  for (h = 0; h != hCount; ++h) handles[h] = aff * handles[h];
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void processHandles(DataGroup *group, double frame, const TMeshImage *meshImage,
Shinya Kitaoka 120a6e
                    const SkD *sd, int skelId,
Shinya Kitaoka 120a6e
                    const TAffine &deformationAffine) {
Shinya Kitaoka 120a6e
  assert(sd);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const PlasticSkeletonP &skeleton = sd->skeleton(skelId);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!skeleton || skeleton->verticesCount() == 0) {
Shinya Kitaoka 120a6e
    group->m_handles.clear();
Shinya Kitaoka 120a6e
    group->m_dstHandles.clear();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    group->m_compiled |= PlasticDeformerStorage::HANDLES;
Shinya Kitaoka 120a6e
    group->m_upToDate |= PlasticDeformerStorage::HANDLES;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int mCount = meshImage->meshes().size();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!(group->m_upToDate & PlasticDeformerStorage::HANDLES)) {
Shinya Kitaoka 120a6e
    // Compile handles if necessary
Shinya Kitaoka 120a6e
    if (!(group->m_compiled & PlasticDeformerStorage::HANDLES)) {
Shinya Kitaoka 120a6e
      // Build and transform handles
Shinya Kitaoka 120a6e
      group->m_handles = skeleton->verticesToHandles();
Shinya Kitaoka 120a6e
      ::transformHandles(group->m_handles, deformationAffine);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      // Prepare a vector for handles' face hints
Shinya Kitaoka 120a6e
      for (int m = 0; m != mCount; ++m)
Shinya Kitaoka 120a6e
        group->m_datas[m].m_faceHints.resize(group->m_handles.size(), -1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      group->m_compiled |= PlasticDeformerStorage::HANDLES;
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Then, build destination handles
Shinya Kitaoka 120a6e
    PlasticSkeleton
Shinya Kitaoka 120a6e
        deformedSkeleton;  // NOTE: Could this be moved to the group as well?
Shinya Kitaoka 120a6e
    sd->storeDeformedSkeleton(skelId, frame, deformedSkeleton);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Copy deformed skeleton data into input deformation parameters
Shinya Kitaoka 120a6e
    group->m_dstHandles = std::vector<tpointd>(</tpointd>
Shinya Kitaoka 120a6e
        deformedSkeleton.vertices().begin(), deformedSkeleton.vertices().end());
Shinya Kitaoka 120a6e
    ::transformHandles(group->m_dstHandles, deformationAffine);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    group->m_upToDate |= PlasticDeformerStorage::HANDLES;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
//    Stacking Order processing  functions
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool updateHandlesSO(DataGroup *group, const SkD *sd, int skelId,
Shinya Kitaoka 120a6e
                     double frame) {
Shinya Kitaoka 120a6e
  assert(sd);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const PlasticSkeletonP &skeleton = sd->skeleton(skelId);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!skeleton || skeleton->verticesCount() == 0) {
Shinya Kitaoka 120a6e
    group->m_soMin = group->m_soMax = 0.0;
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Copy SO values to data's handles
Shinya Kitaoka 120a6e
  // Return whether values changed with respect to previous ones
Shinya Kitaoka 120a6e
  bool changed = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(group->m_handles.size() == skeleton->verticesCount());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int h, hCount = group->m_handles.size();
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    tcg::list<plasticskeletonvertex>::iterator vt =</plasticskeletonvertex>
Shinya Kitaoka 120a6e
        skeleton->vertices().begin();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    for (h = 0; h != hCount; ++h, ++vt) {
Shinya Kitaoka 120a6e
      const SkVD *vd = sd->vertexDeformation(vt->name());
Shinya Kitaoka 120a6e
      if (!vd) continue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      double so = vd->m_params[SkVD::SO]->getValue(frame);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      PlasticHandle &handle = group->m_handles[h];
Shinya Kitaoka 120a6e
      if (handle.m_so != so) {
Shinya Kitaoka 120a6e
        group->m_handles[h].m_so = so;
Shinya Kitaoka 120a6e
        changed                  = true;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (changed) {
Shinya Kitaoka 120a6e
    // Rebuild SO minmax
Shinya Kitaoka 120a6e
    group->m_soMax = -(group->m_soMin = (std::numeric_limits<double>::max)());</double>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    for (h = 0; h != hCount; ++h) {
Shinya Kitaoka 120a6e
      const double &so = group->m_handles[h].m_so;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      group->m_soMin = std::min(group->m_soMin, so);
Shinya Kitaoka 120a6e
      group->m_soMax = std::max(group->m_soMax, so);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return changed;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void interpolateSO(DataGroup *group, const TMeshImage *meshImage) {
Shinya Kitaoka 120a6e
  int m, mCount = meshImage->meshes().size();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (group->m_handles.size() == 0) {
Shinya Kitaoka 120a6e
    // No handles case, fill in with 0s
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    for (m = 0; m != mCount; ++m) {
Shinya Kitaoka 120a6e
      const TTextureMesh &mesh  = *meshImage->meshes()[m];
Shinya Kitaoka 120a6e
      PlasticDeformerData &data = group->m_datas[m];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      std::fill(data.m_so.get(), data.m_so.get() + mesh.facesCount(), 0.0);
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Apply handles' SO values to each mesh
Shinya Kitaoka 120a6e
  for (m = 0; m != mCount; ++m) {
Shinya Kitaoka 120a6e
    const TTextureMesh &mesh  = *meshImage->meshes()[m];
Shinya Kitaoka 120a6e
    PlasticDeformerData &data = group->m_datas[m];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Interpolate so values
Shinya Kitaoka 120a6e
    std::unique_ptr<double[]> verticesSO(new double[mesh.verticesCount()]);</double[]>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    ::buildSO(verticesSO.get(), mesh, group->m_handles,
Shinya Kitaoka 120a6e
              &data.m_faceHints.front());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Make the mean of each face's vertex values and store that
Shinya Kitaoka 120a6e
    int f, fCount = mesh.facesCount();
Shinya Kitaoka 120a6e
    for (f = 0; f != fCount; ++f) {
Shinya Kitaoka 120a6e
      int v0, v1, v2;
Shinya Kitaoka 120a6e
      mesh.faceVertices(f, v0, v1, v2);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      data.m_so[f] = (verticesSO[v0] + verticesSO[v1] + verticesSO[v2]) / 3.0;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct FaceLess {
Shinya Kitaoka 120a6e
  const PlasticDeformerDataGroup *m_group;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  FaceLess(const PlasticDeformerDataGroup *group) : m_group(group) {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool operator()(const std::pair<int, int=""> &a, const std::pair<int, int=""> &b) {</int,></int,>
Shinya Kitaoka 120a6e
    return (m_group->m_datas[a.second].m_so[a.first] <
Shinya Kitaoka 120a6e
            m_group->m_datas[b.second].m_so[b.first]);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Must be invoked after updateSO
Shinya Kitaoka 120a6e
void updateSortedFaces(PlasticDeformerDataGroup *group) {
Shinya Kitaoka 120a6e
  FaceLess comp(group);
Shinya Kitaoka 120a6e
  std::sort(group->m_sortedFaces.begin(), group->m_sortedFaces.end(), comp);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void processSO(DataGroup *group, double frame, const TMeshImage *meshImage,
Shinya Kitaoka 120a6e
               const SkD *sd, int skelId, const TAffine &deformationAffine) {
Shinya Kitaoka 120a6e
  // SO re-interpolate values along the mesh if either:
Shinya Kitaoka 120a6e
  //  1. Recompilation was requested (ie some vertex may have been
Shinya Kitaoka 120a6e
  //  added/removed)
Shinya Kitaoka 120a6e
  //  2. OR the value of one of the handle has changed
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool interpolate = !(group->m_compiled & PlasticDeformerStorage::SO);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!(group->m_upToDate &
Shinya Kitaoka 120a6e
        PlasticDeformerStorage::SO))  // implied by (interpolate == true)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    interpolate = updateHandlesSO(group, sd, skelId, frame) ||
Shinya Kitaoka 120a6e
                  interpolate;  // Order is IMPORTANT
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (interpolate) {
Shinya Kitaoka 120a6e
      interpolateSO(group, meshImage);
Shinya Kitaoka 120a6e
      updateSortedFaces(group);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    group->m_compiled |= PlasticDeformerStorage::SO;
Shinya Kitaoka 120a6e
    group->m_upToDate |= PlasticDeformerStorage::SO;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
//    Mesh Deform processing  functions
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void processMesh(DataGroup *group, double frame, const TMeshImage *meshImage,
Shinya Kitaoka 120a6e
                 const SkD *sd, int skelId, const TAffine &deformationAffine) {
Shinya Kitaoka 120a6e
  if (!(group->m_upToDate & PlasticDeformerStorage::MESH)) {
Shinya Kitaoka 120a6e
    int m, mCount = meshImage->meshes().size();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (!(group->m_compiled & PlasticDeformerStorage::MESH)) {
Shinya Kitaoka 120a6e
      for (m = 0; m != mCount; ++m) {
Shinya Kitaoka 120a6e
        const TTextureMeshP &mesh = meshImage->meshes()[m];
Shinya Kitaoka 120a6e
        PlasticDeformerData &data = group->m_datas[m];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        data.m_deformer.initialize(mesh);
Shinya Kitaoka 120a6e
        data.m_deformer.compile(
Shinya Kitaoka 120a6e
            group->m_handles,
Shinya Kitaoka 120a6e
            data.m_faceHints.empty() ? 0 : &data.m_faceHints.front());
Shinya Kitaoka 120a6e
        data.m_deformer.releaseInitializedData();
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      group->m_compiled |= PlasticDeformerStorage::MESH;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    const TPointD *dstHandlePos =
Shinya Kitaoka 120a6e
        group->m_dstHandles.empty() ? 0 : &group->m_dstHandles.front();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (m = 0; m != mCount; ++m) {
Shinya Kitaoka 120a6e
      PlasticDeformerData &data = group->m_datas[m];
Shinya Kitaoka 120a6e
      data.m_deformer.deform(dstHandlePos, data.m_output.get());
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    group->m_upToDate |= PlasticDeformerStorage::MESH;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
//    PlasticDeformerData  implementation
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticDeformerData::PlasticDeformerData() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticDeformerData::~PlasticDeformerData() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
//    PlasticDeformerDataGroup  implementation
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PlasticDeformerDataGroup::PlasticDeformerDataGroup()
Shinya Kitaoka 120a6e
    : m_datas()
Shinya Kitaoka 120a6e
    , m_compiled(PlasticDeformerStorage::NONE)
Shinya Kitaoka 120a6e
    , m_upToDate(PlasticDeformerStorage::NONE)
Shinya Kitaoka 120a6e
    , m_outputFrame((std::numeric_limits<double>::max)())</double>
Shinya Kitaoka 120a6e
    , m_soMin()
Shinya Kitaoka 120a6e
    , m_soMax() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticDeformerDataGroup::~PlasticDeformerDataGroup() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
//    PlasticDeformerStorage::Imp  definition
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class PlasticDeformerStorage::Imp {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  QMutex m_mutex;            //!< Access mutex - needed for thread-safety
Shinya Kitaoka 120a6e
  DeformersSet m_deformers;  //!< Set of deformers, ordered by mesh image,
Shinya Kitaoka 38fd86
                             //! deformation, and affine.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  Imp() : m_mutex(QMutex::Recursive) {}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
//    PlasticDeformerStorage  implementation
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticDeformerStorage::PlasticDeformerStorage() : m_imp(new Imp) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticDeformerStorage::~PlasticDeformerStorage() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticDeformerStorage *PlasticDeformerStorage::instance() {
Shinya Kitaoka 120a6e
  static PlasticDeformerStorage theInstance;
Shinya Kitaoka 120a6e
  return &theInstance;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PlasticDeformerDataGroup *PlasticDeformerStorage::deformerData(
Shinya Kitaoka 120a6e
    const TMeshImage *meshImage, const PlasticSkeletonDeformation *deformation,
Shinya Kitaoka 120a6e
    int skelId) {
Shinya Kitaoka 120a6e
  QMutexLocker locker(&m_imp->m_mutex);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Search for the corresponding deformation in the storage
Shinya Kitaoka 120a6e
  Key key(meshImage, deformation, skelId);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  DeformersByKey::iterator dt = m_imp->m_deformers.find(key);
Shinya Kitaoka 120a6e
  if (dt == m_imp->m_deformers.end()) {
Shinya Kitaoka 120a6e
    // No deformer was found. Allocate it.
Shinya Kitaoka 120a6e
    key.m_dataGroup = std::make_shared<plasticdeformerdatagroup>();</plasticdeformerdatagroup>
Shinya Kitaoka 120a6e
    initializeDeformersData(key.m_dataGroup.get(), meshImage);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    dt = m_imp->m_deformers.insert(key).first;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return dt->m_dataGroup.get();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const PlasticDeformerDataGroup *PlasticDeformerStorage::process(
Shinya Kitaoka 120a6e
    double frame, const TMeshImage *meshImage,
Shinya Kitaoka 120a6e
    const PlasticSkeletonDeformation *deformation, int skelId,
Shinya Kitaoka 120a6e
    const TAffine &skeletonAffine, DataType dataType) {
Shinya Kitaoka 120a6e
  QMutexLocker locker(&m_imp->m_mutex);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  PlasticDeformerDataGroup *group =
Shinya Kitaoka 120a6e
      deformerData(meshImage, deformation, skelId);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // On-the-fly checks for data invalidation
Shinya Kitaoka 120a6e
  if (group->m_skeletonAffine != skeletonAffine) {
Shinya Kitaoka 120a6e
    group->m_upToDate       = NONE;
Shinya Kitaoka 120a6e
    group->m_compiled       = NONE;
Shinya Kitaoka 120a6e
    group->m_skeletonAffine = skeletonAffine;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (group->m_outputFrame != frame) {
Shinya Kitaoka 120a6e
    group->m_upToDate    = NONE;
Shinya Kitaoka 120a6e
    group->m_outputFrame = frame;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool doMesh    = (dataType & MESH);
Shinya Kitaoka 120a6e
  bool doSO      = (dataType & SO) || doMesh;
Shinya Kitaoka 120a6e
  bool doHandles = (bool)dataType;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Process data
Shinya Kitaoka 120a6e
  if (doHandles)
Shinya Kitaoka 120a6e
    processHandles(group, frame, meshImage, deformation, skelId,
Shinya Kitaoka 120a6e
                   skeletonAffine);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (doSO)
Shinya Kitaoka 120a6e
    processSO(group, frame, meshImage, deformation, skelId, skeletonAffine);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (doMesh)
Shinya Kitaoka 120a6e
    processMesh(group, frame, meshImage, deformation, skelId, skeletonAffine);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return group;
Shinya Kitaoka 120a6e
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
const PlasticDeformerDataGroup *PlasticDeformerStorage::processOnce(
Shinya Kitaoka 120a6e
    double frame, const TMeshImage *meshImage,
Shinya Kitaoka 120a6e
    const PlasticSkeletonDeformation *deformation, int skelId,
Shinya Kitaoka 120a6e
    const TAffine &skeletonAffine, DataType dataType) {
Shinya Kitaoka 120a6e
  PlasticDeformerDataGroup *group = new PlasticDeformerDataGroup;
Shinya Kitaoka 120a6e
  initializeDeformersData(group, meshImage);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool doMesh    = (dataType & MESH);
Shinya Kitaoka 120a6e
  bool doSO      = (dataType & SO) || doMesh;
Shinya Kitaoka 120a6e
  bool doHandles = (bool)dataType;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Process data
Shinya Kitaoka 120a6e
  if (doHandles)
Shinya Kitaoka 120a6e
    processHandles(group, frame, meshImage, deformation, skelId,
Shinya Kitaoka 120a6e
                   skeletonAffine);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (doSO)
Shinya Kitaoka 120a6e
    processSO(group, frame, meshImage, deformation, skelId, skeletonAffine);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (doMesh)
Shinya Kitaoka 120a6e
    processMesh(group, frame, meshImage, deformation, skelId, skeletonAffine);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return group;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticDeformerStorage::invalidateMeshImage(const TMeshImage *meshImage,
Shinya Kitaoka 120a6e
                                                 int recompiledData) {
Shinya Kitaoka 120a6e
  QMutexLocker locker(&m_imp->m_mutex);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  DeformersByMeshImage &deformers = m_imp->m_deformers.get<tmeshimage>();</tmeshimage>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  DeformersByMeshImage::iterator dBegin(deformers.lower_bound(meshImage));
Shinya Kitaoka 120a6e
  if (dBegin == deformers.end()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  DeformersByMeshImage::iterator dt, dEnd(deformers.upper_bound(meshImage));
Shinya Kitaoka 120a6e
  for (dt = dBegin; dt != dEnd; ++dt) {
Shinya Kitaoka 120a6e
    dt->m_dataGroup->m_outputFrame =
Shinya Kitaoka 120a6e
        (std::numeric_limits<double>::max)();  // Schedule for redeformation</double>
Shinya Kitaoka 120a6e
    if (recompiledData)
Shinya Kitaoka 120a6e
      dt->m_dataGroup->m_compiled &=
Shinya Kitaoka 120a6e
          ~recompiledData;  // Schedule for recompilation, too
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PlasticDeformerStorage::invalidateSkeleton(
Shinya Kitaoka 120a6e
    const PlasticSkeletonDeformation *deformation, int skelId,
Shinya Kitaoka 120a6e
    int recompiledData) {
Shinya Kitaoka 120a6e
  QMutexLocker locker(&m_imp->m_mutex);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  DeformedSkeleton ds(deformation, skelId);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  DeformersByDeformedSkeleton &deformers =
Shinya Kitaoka 120a6e
      m_imp->m_deformers.get<deformedskeleton>();</deformedskeleton>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  DeformersByDeformedSkeleton::iterator dBegin(deformers.lower_bound(ds));
Shinya Kitaoka 120a6e
  if (dBegin == deformers.end()) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  DeformersByDeformedSkeleton::iterator dt, dEnd(deformers.upper_bound(ds));
Shinya Kitaoka 120a6e
  for (dt = dBegin; dt != dEnd; ++dt) {
Shinya Kitaoka 120a6e
    dt->m_dataGroup->m_outputFrame =
Shinya Kitaoka 120a6e
        (std::numeric_limits<double>::max)();  // Schedule for redeformation</double>
Shinya Kitaoka 120a6e
    if (recompiledData)
Shinya Kitaoka 120a6e
      dt->m_dataGroup->m_compiled &=
Shinya Kitaoka 120a6e
          ~recompiledData;  // Schedule for recompilation, too
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PlasticDeformerStorage::invalidateDeformation(
Shinya Kitaoka 120a6e
    const PlasticSkeletonDeformation *deformation, int recompiledData) {
Shinya Kitaoka 120a6e
  QMutexLocker locker(&m_imp->m_mutex);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  DeformersByDeformedSkeleton &deformers =
Shinya Kitaoka 120a6e
      m_imp->m_deformers.get<deformedskeleton>();</deformedskeleton>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  DeformedSkeleton dsBegin(deformation, -(std::numeric_limits<int>::max)()),</int>
Shinya Kitaoka 120a6e
      dsEnd(deformation, (std::numeric_limits<int>::max)());</int>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  DeformersByDeformedSkeleton::iterator dBegin(deformers.lower_bound(dsBegin));
Shinya Kitaoka 120a6e
  DeformersByDeformedSkeleton::iterator dEnd(deformers.upper_bound(dsEnd));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (dBegin == dEnd) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (DeformersByDeformedSkeleton::iterator dt = dBegin; dt != dEnd; ++dt) {
Shinya Kitaoka 120a6e
    dt->m_dataGroup->m_outputFrame =
Shinya Kitaoka 120a6e
        (std::numeric_limits<double>::max)();  // Schedule for redeformation</double>
Shinya Kitaoka 120a6e
    if (recompiledData)
Shinya Kitaoka 120a6e
      dt->m_dataGroup->m_compiled &=
Shinya Kitaoka 120a6e
          ~recompiledData;  // Schedule for recompilation, too
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticDeformerStorage::releaseMeshData(const TMeshImage *meshImage) {
Shinya Kitaoka 120a6e
  QMutexLocker locker(&m_imp->m_mutex);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  DeformersByMeshImage &deformers = m_imp->m_deformers.get<tmeshimage>();</tmeshimage>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  DeformersByMeshImage::iterator dBegin(deformers.lower_bound(meshImage));
Shinya Kitaoka 120a6e
  if (dBegin == deformers.end()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  deformers.erase(dBegin, deformers.upper_bound(meshImage));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticDeformerStorage::releaseSkeletonData(const SkD *deformation,
Shinya Kitaoka 120a6e
                                                 int skelId) {
Shinya Kitaoka 120a6e
  QMutexLocker locker(&m_imp->m_mutex);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  DeformedSkeleton ds(deformation, skelId);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  DeformersByDeformedSkeleton &deformers =
Shinya Kitaoka 120a6e
      m_imp->m_deformers.get<deformedskeleton>();</deformedskeleton>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  DeformersByDeformedSkeleton::iterator dBegin(deformers.lower_bound(ds));
Shinya Kitaoka 120a6e
  if (dBegin == deformers.end()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  deformers.erase(dBegin, deformers.upper_bound(ds));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticDeformerStorage::releaseDeformationData(const SkD *deformation) {
Shinya Kitaoka 120a6e
  QMutexLocker locker(&m_imp->m_mutex);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  DeformersByDeformedSkeleton &deformers =
Shinya Kitaoka 120a6e
      m_imp->m_deformers.get<deformedskeleton>();</deformedskeleton>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  DeformedSkeleton dsBegin(deformation, -(std::numeric_limits<int>::max)()),</int>
Shinya Kitaoka 120a6e
      dsEnd(deformation, (std::numeric_limits<int>::max)());</int>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  DeformersByDeformedSkeleton::iterator dBegin(deformers.lower_bound(dsBegin));
Shinya Kitaoka 120a6e
  DeformersByDeformedSkeleton::iterator dEnd(deformers.upper_bound(dsEnd));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (dBegin == dEnd) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  deformers.erase(dBegin, dEnd);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticDeformerStorage::clear() {
Shinya Kitaoka 120a6e
  QMutexLocker locker(&m_imp->m_mutex);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp->m_deformers.clear();
Toshihiro Shimizu 890ddd
}