Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tmeshimage.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// tcg includes
Toshihiro Shimizu 890ddd
#include "tcg/tcg_misc.h"
Toshihiro Shimizu 890ddd
#include "tcg/tcg_mesh_bgl.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace tcg::bgl;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Boost includes
Toshihiro Shimizu 890ddd
#include <boost graph="" properties.hpp=""></boost>
Toshihiro Shimizu 890ddd
#include <boost breadth_first_search.hpp="" graph=""></boost>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// STD includes
Toshihiro Shimizu 890ddd
#include <queue></queue>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "ext/plastichandle.h"
Toshihiro Shimizu 890ddd
Campbell Barton 107701
#include <cstring></cstring>
Campbell Barton 107701
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
//    Distance building
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef tcg::Mesh<ttexturevertex, tcg::edge,="" tcg::facen<3="">> Graph;</ttexturevertex,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct DistanceGreater {
Shinya Kitaoka 120a6e
  float *m_distances;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  DistanceGreater(float *distances) : m_distances(distances) {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool operator()(int a, int b) { return m_distances[a] > m_distances[b]; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==================================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace local {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct BFS_DistanceBuilder {
Shinya Kitaoka 120a6e
  typedef boost::graph_traits<graph>::edge_descriptor edge_descr;</graph>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  float *m_distances;  //!< (NOT owned) Distances from selected vertex
Shinya Kitaoka 120a6e
  UCHAR *m_colormap;   //!< (NOT owned) Graph BFS colormap
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  BFS_DistanceBuilder(float *distances, UCHAR *colormap)
Shinya Kitaoka 120a6e
      : m_distances(distances), m_colormap(colormap) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void tree_edge(const edge_descr &e, const Graph &g) {
Shinya Kitaoka 120a6e
    int v, v0 = -1, v1 = tcg::bgl::target(e, g);
Shinya Kitaoka 120a6e
    double d, dMin = (std::numeric_limits<double>::max)();</double>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    assert(m_colormap[v1] == boost::white_color);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Search for the distance-nearest found vertex
Shinya Kitaoka 120a6e
    const Graph::vertex_type &vx1 = g.vertex(v1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    Graph::vertex_type::edges_const_iterator et, eEnd(vx1.edgesEnd());
Shinya Kitaoka 120a6e
    for (et = vx1.edgesBegin(); et != eEnd; ++et) {
Shinya Kitaoka 120a6e
      v = g.edge(*et).otherVertex(v1);
Shinya Kitaoka 120a6e
      if (m_colormap[v] != boost::white_color) {
Shinya Kitaoka 120a6e
        d                = tcg::point_ops::dist(g.vertex(v).P(), vx1.P());
Shinya Kitaoka 120a6e
        if (d < dMin) v0 = v, dMin = d;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    assert(v0 >= 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Just add to the distance from that vertex
Shinya Kitaoka 120a6e
    m_distances[v1] = m_distances[v0] + dMin;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Unused bfs methods
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void initialize_vertex(int v, const Graph &g) {}
Shinya Kitaoka 120a6e
  void discover_vertex(int v, const Graph &g) {}
Shinya Kitaoka 120a6e
  void examine_vertex(int v, const Graph &g) {}
Shinya Kitaoka 120a6e
  void finish_vertex(int v, const Graph &g) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void examine_edge(const edge_descr &e, const Graph &g) {}
Shinya Kitaoka 120a6e
  void non_tree_edge(const edge_descr &e, const Graph &g) {}
Shinya Kitaoka 120a6e
  void gray_target(const edge_descr &e, const Graph &g) {}
Shinya Kitaoka 120a6e
  void black_target(const edge_descr &e, const Graph &g) {}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace local
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==================================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool buildDistances(float *distances, const TTextureMesh &mesh,
Shinya Kitaoka 120a6e
                    const TPointD &pos, int *faceHint) {
Shinya Kitaoka 120a6e
  using namespace local;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // First off, find the face containing the specified vertex
Shinya Kitaoka 120a6e
  int localF = -1, &f = faceHint ? *faceHint : localF;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (f < 0 || f >= mesh.facesCount() || !mesh.faceContains(f, pos))
Shinya Kitaoka 120a6e
    f = mesh.faceContaining(pos);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (f < 0) return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int vCount = mesh.verticesCount();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Prepare the interpolation builder
Shinya Kitaoka 120a6e
  UCHAR *colorMap = (UCHAR *)calloc(vCount, sizeof(UCHAR));
Shinya Kitaoka 120a6e
  BFS_DistanceBuilder visitor(distances, colorMap);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  DistanceGreater gr(distances);
Shinya Kitaoka 120a6e
  std::priority_queue<int, std::vector<int="">, DistanceGreater> verticesQueue(gr);</int,>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int v0, v1, v2;
Shinya Kitaoka 120a6e
  mesh.faceVertices(f, v0, v1, v2);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Prepare BFS data
Shinya Kitaoka 120a6e
  distances[v0] = distances[v1] = distances[v2] = 0.0f;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  verticesQueue.push(v0), colorMap[v0] = boost::gray_color;
Shinya Kitaoka 120a6e
  verticesQueue.push(v1), colorMap[v1] = boost::gray_color;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Launch BFS algorithm
Shinya Kitaoka 120a6e
  boost::breadth_first_visit((const Graph &)mesh, v2, verticesQueue, visitor,
Shinya Kitaoka 120a6e
                             colorMap);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  free(colorMap);
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void buildSO(double *so, const TTextureMesh &mesh,
Shinya Kitaoka 120a6e
             const std::vector<plastichandle> &handles, int *faceHints) {</plastichandle>
Shinya Kitaoka 120a6e
  int v, vCount = mesh.verticesCount();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Build the interpolant function data
Shinya Kitaoka 120a6e
  const TRectD &bbox = mesh.getBBox();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const double len = std::max(bbox.getLx(), bbox.getLy()), val = 1e-8;
Shinya Kitaoka 120a6e
  const double k = -log(val) / len;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Allocate / initialize arrays
Shinya Kitaoka 120a6e
  float *distances = (float *)malloc(vCount * sizeof(float));
Shinya Kitaoka 120a6e
  double *wSums    = (double *)calloc(vCount, sizeof(double));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  memset(so, 0, vCount * sizeof(double));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Iterate handles - for each, add the corresponding interpolant
Shinya Kitaoka 120a6e
  int h, hCount = handles.size();
Shinya Kitaoka 120a6e
  for (h = 0; h != hCount; ++h) {
Shinya Kitaoka 120a6e
    const PlasticHandle &handle = handles[h];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (!buildDistances(distances, mesh, handle.m_pos,
Shinya Kitaoka 120a6e
                        faceHints ? &faceHints[h] : 0))
Shinya Kitaoka 120a6e
      continue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    for (v = 0; v != vCount; ++v) {
Shinya Kitaoka 120a6e
      double w = fabs(distances[v]);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      wSums[v] += w = exp(-k * w) / (1e-3 + w);
Shinya Kitaoka 120a6e
      so[v] += w * handle.m_so;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Normalize so values by the wSums
Shinya Kitaoka 120a6e
  for (v = 0; v != vCount; ++v)
Shinya Kitaoka 120a6e
    if (wSums[v] != 0.0) so[v] /= wSums[v];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Cleanup
Shinya Kitaoka 120a6e
  free(wSums);
Shinya Kitaoka 120a6e
  free(distances);
Toshihiro Shimizu 890ddd
}