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