|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// TnzCore includes
|
|
Toshihiro Shimizu |
890ddd |
#include "tmeshimage.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tgl.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tundo.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// TnzExt includes
|
|
Toshihiro Shimizu |
890ddd |
#include "ext/plasticdeformerstorage.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// tcg includes
|
|
Toshihiro Shimizu |
890ddd |
#include "tcg/tcg_macros.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tcg/tcg_point_ops.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tcg/tcg_iterator_ops.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tcg/tcg_function_types.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tcg/tcg_deleter_types.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tcg/tcg_unique_ptr.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// boost includes
|
|
Toshihiro Shimizu |
890ddd |
#include <boost unordered_set.hpp=""></boost>
|
|
Toshihiro Shimizu |
890ddd |
#include <boost unordered_map.hpp=""></boost>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
using namespace tcg::bgl;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include <boost breadth_first_search.hpp="" graph=""></boost>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// STD includes
|
|
Toshihiro Shimizu |
890ddd |
#include <stack></stack>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "plastictool.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
using namespace PlasticToolLocals;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//****************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Local namespace stuff
|
|
Toshihiro Shimizu |
890ddd |
//****************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
typedef PlasticTool::MeshIndex MeshIndex;
|
|
Toshihiro Shimizu |
890ddd |
typedef TTextureMesh::vertex_type vertex_type;
|
|
Toshihiro Shimizu |
890ddd |
typedef TTextureMesh::edge_type edge_type;
|
|
Toshihiro Shimizu |
890ddd |
typedef TTextureMesh::face_type face_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool borderEdge(const TTextureMesh &mesh, int e)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return (mesh.edge(e).facesCount() < 2);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool borderVertex(const TTextureMesh &mesh, int v)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
const TTextureVertex &vx = mesh.vertex(v);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tcg::vertex_traits<ttexturevertex>::edges_const_iterator et, eEnd(vx.edgesEnd());</ttexturevertex>
|
|
Toshihiro Shimizu |
890ddd |
for (et = vx.edgesBegin(); et != eEnd; ++et) {
|
|
Toshihiro Shimizu |
890ddd |
if (borderEdge(mesh, *et))
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool testSwapEdge(const TTextureMesh &mesh, int e)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return (mesh.edge(e).facesCount() == 2);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool testCollapseEdge(const TTextureMesh &mesh, int e)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
struct Locals {
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh &m_mesh;
|
|
Toshihiro Shimizu |
890ddd |
int m_e;
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh::edge_type &m_ed;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool testTrianglesCount()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
// There must be at least one remanining triangle
|
|
Toshihiro Shimizu |
890ddd |
return (m_mesh.facesCount() > m_ed.facesCount());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool testBoundary()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
// Must not join two non-adjacent boundary vertices
|
|
Toshihiro Shimizu |
890ddd |
return (!borderVertex(m_mesh, m_ed.vertex(0)) ||
|
|
Toshihiro Shimizu |
890ddd |
!borderVertex(m_mesh, m_ed.vertex(1)) ||
|
|
Toshihiro Shimizu |
890ddd |
borderEdge(m_mesh, m_e));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool testAdjacency()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
// See TriMesh<>::collapseEdge()
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Retrieve allowed adjacent vertices
|
|
Toshihiro Shimizu |
890ddd |
int f, fCount = m_ed.facesCount();
|
|
Toshihiro Shimizu |
890ddd |
int allowedV[6], *avt, *avEnd = allowedV + 3 * fCount;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (f = 0, avt = allowedV; f != fCount; ++f, avt += 3)
|
|
Toshihiro Shimizu |
890ddd |
m_mesh.faceVertices(m_ed.face(f), avt[0], avt[1], avt[2]);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Test adjacent vertices
|
|
Toshihiro Shimizu |
890ddd |
int v0 = m_ed.vertex(0), v1 = m_ed.vertex(1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const vertex_type &vx0 = m_mesh.vertex(v0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tcg::vertex_traits<vertex_type>::edges_const_iterator et, eEnd = vx0.edgesEnd();</vertex_type>
|
|
Toshihiro Shimizu |
890ddd |
for (et = vx0.edgesBegin(); et != eEnd; ++et) {
|
|
Toshihiro Shimizu |
890ddd |
int otherV = m_mesh.edge(*et).otherVertex(v0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_mesh.edgeInciding(v1, otherV) >= 0) {
|
|
Toshihiro Shimizu |
890ddd |
// Adjacent vertex - must be found in the allowed list
|
|
Toshihiro Shimizu |
890ddd |
if (std::find(allowedV, avEnd, otherV) == avEnd)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
} locals = {mesh, e, mesh.edge(e)};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return (locals.testTrianglesCount() &&
|
|
Toshihiro Shimizu |
890ddd |
locals.testBoundary() &&
|
|
Toshihiro Shimizu |
890ddd |
locals.testAdjacency());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} // namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//****************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// PlasticToolLocals stuff
|
|
Toshihiro Shimizu |
890ddd |
//****************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace PlasticToolLocals
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct Closer {
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh &m_mesh;
|
|
Toshihiro Shimizu |
890ddd |
TPointD m_pos;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double dist2(const TTextureMesh::vertex_type &a)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return tcg::point_ops::dist2<tpointd>(a.P(), m_pos);</tpointd>
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double dist2(const TTextureMesh::edge_type &a)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh::vertex_type &avx0 = m_mesh.vertex(a.vertex(0)),
|
|
Toshihiro Shimizu |
890ddd |
&avx1 = m_mesh.vertex(a.vertex(1));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return sq(tcg::point_ops::segDist<tpointd>(avx0.P(), avx1.P(), m_pos));</tpointd>
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool operator()(const TTextureMesh::vertex_type &a,
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh::vertex_type &b)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return (dist2(a) < dist2(b));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool operator()(const TTextureMesh::edge_type &a,
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh::edge_type &b)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return (dist2(a) < dist2(b));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//==============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::pair<double, int=""> closestVertex(const TTextureMesh &mesh, const TPointD &pos)</double,>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
Closer closer = {mesh, pos};
|
|
Toshihiro Shimizu |
890ddd |
int vIdx = int(std::min_element(mesh.vertices().begin(), mesh.vertices().end(), closer).index());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return std::make_pair(closer.dist2(mesh.vertex(vIdx)), vIdx);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::pair<double, int=""> closestEdge(const TTextureMesh &mesh, const TPointD &pos)</double,>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
Closer closer = {mesh, pos};
|
|
Toshihiro Shimizu |
890ddd |
int eIdx = int(std::min_element(mesh.edges().begin(), mesh.edges().end(), closer).index());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return std::make_pair(closer.dist2(mesh.edge(eIdx)), eIdx);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::pair<double, meshindex=""> closestVertex(const TMeshImage &mi, const TPointD &pos)</double,>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
std::pair<double, meshindex=""> closest((std::numeric_limits<double>::max)(), MeshIndex());</double></double,>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TMeshImage::meshes_container &meshes = mi.meshes();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TMeshImage::meshes_container::const_iterator mt, mEnd = meshes.end();
|
|
Toshihiro Shimizu |
890ddd |
for (mt = meshes.begin(); mt != mEnd; ++mt) {
|
|
Toshihiro Shimizu |
890ddd |
const std::pair<double, int=""> &candidateIdx = closestVertex(**mt, pos);</double,>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::pair<double, meshindex=""> candidate(</double,>
|
|
Toshihiro Shimizu |
890ddd |
candidateIdx.first, MeshIndex(mt - meshes.begin(), candidateIdx.second));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (candidate < closest)
|
|
Toshihiro Shimizu |
890ddd |
closest = candidate;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return closest;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::pair<double, meshindex=""> closestEdge(const TMeshImage &mi, const TPointD &pos)</double,>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
std::pair<double, meshindex=""> closest((std::numeric_limits<double>::max)(), MeshIndex());</double></double,>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TMeshImage::meshes_container &meshes = mi.meshes();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TMeshImage::meshes_container::const_iterator mt, mEnd = meshes.end();
|
|
Toshihiro Shimizu |
890ddd |
for (mt = meshes.begin(); mt != mEnd; ++mt) {
|
|
Toshihiro Shimizu |
890ddd |
const std::pair<double, int=""> &candidateIdx = closestEdge(**mt, pos);</double,>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::pair<double, meshindex=""> candidate(</double,>
|
|
Toshihiro Shimizu |
890ddd |
candidateIdx.first, MeshIndex(mt - meshes.begin(), candidateIdx.second));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (candidate < closest)
|
|
Toshihiro Shimizu |
890ddd |
closest = candidate;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return closest;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} // namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//****************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Cut Mesh operation
|
|
Toshihiro Shimizu |
890ddd |
//****************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct EdgeCut {
|
|
Toshihiro Shimizu |
890ddd |
int m_vIdx; //!< Vertex index to cut from.
|
|
Toshihiro Shimizu |
890ddd |
int m_eIdx; //!< Edge index to cut.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
EdgeCut(int vIdx, int eIdx)
|
|
Toshihiro Shimizu |
890ddd |
: m_vIdx(vIdx), m_eIdx(eIdx) {}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct VertexOccurrence {
|
|
Toshihiro Shimizu |
890ddd |
int m_count; //!< Number of times a vertex occurs.
|
|
Toshihiro Shimizu |
890ddd |
int m_adjacentEdgeIdx[2]; //!< Edge indexes of which a vertex is endpoint.
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool buildEdgeCuts(const TMeshImage &mi, const PlasticTool::MeshSelection &edgesSelection,
|
|
Toshihiro Shimizu |
890ddd |
int &meshIdx, std::vector<edgecut> &edgeCuts)</edgecut>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
typedef PlasticTool::MeshSelection::objects_container edges_container;
|
|
Toshihiro Shimizu |
890ddd |
typedef PlasticTool::MeshIndex MeshIndex;
|
|
Toshihiro Shimizu |
890ddd |
typedef boost::unordered_map<int, vertexoccurrence=""> VertexOccurrencesMap;</int,>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct locals {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
static bool differentMesh(const MeshIndex &a, const MeshIndex &b)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return (a.m_meshIdx != b.m_meshIdx);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
static int testSingleMesh(const edges_container &edges)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(!edges.empty());
|
|
Toshihiro Shimizu |
890ddd |
return (std::find_if(
|
|
Toshihiro Shimizu |
890ddd |
edges.begin(), edges.end(), tcg::bind2nd(&differentMesh, edges.front())) == edges.end())
|
|
Toshihiro Shimizu |
890ddd |
? edges.front().m_meshIdx
|
|
Toshihiro Shimizu |
890ddd |
: -1;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
static bool testNoBoundaryEdge(
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh &mesh, const edges_container &edges)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
edges_container::const_iterator et, eEnd = edges.end();
|
|
Toshihiro Shimizu |
890ddd |
for (et = edges.begin(); et != eEnd; ++et)
|
|
Toshihiro Shimizu |
890ddd |
if (::borderEdge(mesh, et->m_idx))
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
static bool buildVertexOccurrences(
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh &mesh, const edges_container &edges,
|
|
Toshihiro Shimizu |
890ddd |
VertexOccurrencesMap &vertexOccurrences)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
// Calculate vertex occurrences as edge endpoints
|
|
Toshihiro Shimizu |
890ddd |
edges_container::const_iterator et, eEnd = edges.end();
|
|
Toshihiro Shimizu |
890ddd |
for (et = edges.begin(); et != eEnd; ++et) {
|
|
Toshihiro Shimizu |
890ddd |
const edge_type &ed = mesh.edge(et->m_idx);
|
|
Toshihiro Shimizu |
890ddd |
int v0 = ed.vertex(0), v1 = ed.vertex(1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
VertexOccurrence &vo0 = vertexOccurrences[v0],
|
|
Toshihiro Shimizu |
890ddd |
&vo1 = vertexOccurrences[v1];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (vo0.m_count > 1 || vo1.m_count > 1)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
vo0.m_adjacentEdgeIdx[vo0.m_count++] =
|
|
Toshihiro Shimizu |
890ddd |
vo1.m_adjacentEdgeIdx[vo1.m_count++] = et->m_idx;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
static bool buildEdgeCuts(
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh &mesh, const edges_container &edges,
|
|
Toshihiro Shimizu |
890ddd |
std::vector<edgecut> &edgeCuts)</edgecut>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
VertexOccurrencesMap vertexOccurrences;
|
|
Toshihiro Shimizu |
890ddd |
if (!buildVertexOccurrences(mesh, edges, vertexOccurrences))
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Build endpoints (exactly 2)
|
|
Toshihiro Shimizu |
890ddd |
int endPoints[2];
|
|
Toshihiro Shimizu |
890ddd |
int epCount = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
VertexOccurrencesMap::iterator ot, oEnd = vertexOccurrences.end();
|
|
Toshihiro Shimizu |
890ddd |
for (ot = vertexOccurrences.begin(); ot != oEnd; ++ot) {
|
|
Toshihiro Shimizu |
890ddd |
if (ot->second.m_count == 1) {
|
|
Toshihiro Shimizu |
890ddd |
if (epCount > 1)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
endPoints[epCount++] = ot->first;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (epCount != 2)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Pick the first endpoint on the boundary, if any (otherwise, just pick one)
|
|
Toshihiro Shimizu |
890ddd |
int *ept, *epEnd = endPoints + 2;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ept = std::find_if(endPoints, epEnd, tcg::bind1st(&borderVertex, mesh));
|
|
Toshihiro Shimizu |
890ddd |
if (ept == epEnd) {
|
|
Toshihiro Shimizu |
890ddd |
// There is no boundary endpoint
|
|
Toshihiro Shimizu |
890ddd |
if (edges.size() < 2) // We should not cut the mesh on a
|
|
Toshihiro Shimizu |
890ddd |
return false; // single edge - no vertex to duplicate!
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ept = endPoints;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Build the edge cuts list, expanding the edges selection from
|
|
Toshihiro Shimizu |
890ddd |
// the chosen endpoint
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
edgeCuts.push_back(EdgeCut( // Build the first EdgeCut separately
|
|
Toshihiro Shimizu |
890ddd |
*ept, vertexOccurrences[*ept].m_adjacentEdgeIdx[0]));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int e, eCount = int(edges.size()); // Build the remaining ones
|
|
Toshihiro Shimizu |
890ddd |
for (e = 1; e != eCount; ++e) {
|
|
Toshihiro Shimizu |
890ddd |
const EdgeCut &lastCut = edgeCuts.back();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int vIdx = mesh.edge(lastCut.m_eIdx).otherVertex(lastCut.m_vIdx);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const int(&adjEdges)[2] = vertexOccurrences[vIdx].m_adjacentEdgeIdx;
|
|
Toshihiro Shimizu |
890ddd |
int eIdx = (adjEdges[0] == lastCut.m_eIdx) ? adjEdges[1] : adjEdges[0];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
edgeCuts.push_back(EdgeCut(vIdx, eIdx));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const edges_container &edges = edgesSelection.objects();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Trivial early bailouts
|
|
Toshihiro Shimizu |
890ddd |
if (edges.empty())
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Selected edges must lie on the same mesh
|
|
Toshihiro Shimizu |
890ddd |
meshIdx = locals::testSingleMesh(edges);
|
|
Toshihiro Shimizu |
890ddd |
if (meshIdx < 0)
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh &mesh = *mi.meshes()[meshIdx];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// No selected edge must be on the boundary
|
|
Toshihiro Shimizu |
890ddd |
return (locals::testNoBoundaryEdge(mesh, edges) &&
|
|
Toshihiro Shimizu |
890ddd |
locals::buildEdgeCuts(mesh, edges, edgeCuts));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline bool testCutMesh(const TMeshImage &mi, const PlasticTool::MeshSelection &edgesSelection)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
std::vector<edgecut> edgeCuts;</edgecut>
|
|
Toshihiro Shimizu |
890ddd |
int meshIdx;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return buildEdgeCuts(mi, edgesSelection, meshIdx, edgeCuts);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void slitMesh(TTextureMesh &mesh, int e) //! Opens a slit along the specified edge index.
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TTextureMesh::edge_type &ed = mesh.edge(e);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(ed.facesCount() == 2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Duplicate the edge and pass one face to the duplicate
|
|
Toshihiro Shimizu |
890ddd |
TTextureMesh::edge_type edDup(ed.vertex(0), ed.vertex(1));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int f = ed.face(1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
edDup.addFace(f);
|
|
Toshihiro Shimizu |
890ddd |
ed.eraseFace(ed.facesBegin() + 1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int eDup = mesh.addEdge(edDup);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Alter the face to host the duplicate
|
|
Toshihiro Shimizu |
890ddd |
TTextureMesh::face_type &fc = mesh.face(f);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
(fc.edge(0) == e) ? fc.setEdge(0, eDup) : (fc.edge(1) == e) ? fc.setEdge(1, eDup) : fc.setEdge(2, eDup);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*!
|
|
Toshihiro Shimizu |
890ddd |
\brief Duplicates a mesh edge-vertex pair (the 'cut') and separates their
|
|
Toshihiro Shimizu |
890ddd |
connections to adjacent mesh primitives.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
\remark The starting vertex is supposed to be on the mesh boundary.
|
|
Toshihiro Shimizu |
890ddd |
\remark Edges with a single neighbouring face can be duplicated, too.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
void cutEdge(TTextureMesh &mesh, const EdgeCut &edgeCut)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
struct locals {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
static void transferEdge(
|
|
Toshihiro Shimizu |
890ddd |
TTextureMesh &mesh, int e, int vFrom, int vTo)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
edge_type &ed = mesh.edge(e);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
vertex_type &vxFrom = mesh.vertex(vFrom),
|
|
Toshihiro Shimizu |
890ddd |
&vxTo = mesh.vertex(vTo);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
(ed.vertex(0) == vFrom) ? ed.setVertex(0, vTo) : ed.setVertex(1, vTo);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
vxTo.addEdge(e);
|
|
Toshihiro Shimizu |
890ddd |
vxFrom.eraseEdge(std::find(vxFrom.edges().begin(), vxFrom.edges().end(), e));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
static void transferFace(
|
|
Toshihiro Shimizu |
890ddd |
TTextureMesh &mesh, int eFrom, int eTo)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
edge_type &edFrom = mesh.edge(eFrom),
|
|
Toshihiro Shimizu |
890ddd |
&edTo = mesh.edge(eTo);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int f = mesh.edge(eFrom).face(1);
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
face_type &fc = mesh.face(f);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
(fc.edge(0) == eFrom) ? fc.setEdge(0, eTo) : (fc.edge(1) == eFrom) ? fc.setEdge(1, eTo) : fc.setEdge(2, eTo);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
edTo.addFace(f);
|
|
Toshihiro Shimizu |
890ddd |
edFrom.eraseFace(edFrom.facesBegin() + 1);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
}; // locals
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int vOrig = edgeCut.m_vIdx,
|
|
Toshihiro Shimizu |
890ddd |
eOrig = edgeCut.m_eIdx;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Create a new vertex at the same position of the original
|
|
Toshihiro Shimizu |
890ddd |
int vDup = mesh.addVertex(vertex_type(mesh.vertex(vOrig).P()));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int e = eOrig;
|
|
Toshihiro Shimizu |
890ddd |
if (mesh.edge(e).facesCount() == 2) {
|
|
Toshihiro Shimizu |
890ddd |
// Duplicate the cut edge
|
|
Toshihiro Shimizu |
890ddd |
e = mesh.addEdge(edge_type(vDup, mesh.edge(eOrig).otherVertex(vOrig)));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Transfer one face from the original to the duplicate
|
|
Toshihiro Shimizu |
890ddd |
locals::transferFace(mesh, eOrig, e);
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
// Transfer the original edge to the duplicate vertex
|
|
Toshihiro Shimizu |
890ddd |
locals::transferEdge(mesh, eOrig, vOrig, vDup);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Edges adjacent to the original vertex that are also adjacent
|
|
Toshihiro Shimizu |
890ddd |
// to the transferred face above must be transferred too
|
|
Toshihiro Shimizu |
890ddd |
int f = mesh.edge(e).face(0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
while (f >= 0) {
|
|
Toshihiro Shimizu |
890ddd |
// Retrieve the next edge to transfer
|
|
Toshihiro Shimizu |
890ddd |
int otherE = mesh.otherFaceEdge(f, mesh.edge(e).otherVertex(vDup));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// NOTE: Not "mesh.edgeInciding(vOrig, mesh.otherFaceVertex(f, e))" in the calculation
|
|
Toshihiro Shimizu |
890ddd |
// of otherE. This is required since by transferring each edge at a time,
|
|
Toshihiro Shimizu |
890ddd |
// we're 'breaking' faces up - f is adjacent to both vOrig AND vDup!
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// The chosen calculation, instead, just asks for the one edge which does
|
|
Toshihiro Shimizu |
890ddd |
// not have a specific vertex in common to the 2 other edges in the face.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
locals::transferEdge(mesh, otherE, vOrig, vDup);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Update e and f
|
|
Toshihiro Shimizu |
890ddd |
e = otherE;
|
|
Toshihiro Shimizu |
890ddd |
f = mesh.edge(otherE).otherFace(f);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
namespace locals_
|
|
Toshihiro Shimizu |
890ddd |
{ // Need to use a named namespace due to
|
|
Toshihiro Shimizu |
890ddd |
// a known gcc 4.2 bug with compiler-generated
|
|
Toshihiro Shimizu |
890ddd |
struct VertexesRecorder // copy constructors.
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
boost::unordered_set<int> &m_examinedVertexes;</int>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
typedef boost::on_examine_vertex event_filter;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
VertexesRecorder(boost::unordered_set<int> &examinedVertexes)</int>
|
|
Toshihiro Shimizu |
890ddd |
: m_examinedVertexes(examinedVertexes) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void operator()(int v, const TTextureMesh &)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_examinedVertexes.insert(v);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
namespace
|
|
Toshihiro Shimizu |
890ddd |
{ //
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void splitUnconnectedMesh(TMeshImage &mi, int meshIdx)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
struct locals {
|
|
Toshihiro Shimizu |
890ddd |
static void buildConnectedComponent(
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh &mesh, boost::unordered_set<int> &vertexes)</int>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
// Prepare BFS algorithm
|
|
Toshihiro Shimizu |
890ddd |
tcg::unique_ptr<uchar, tcg::freer=""> colorMapP(</uchar,>
|
|
Toshihiro Shimizu |
890ddd |
(UCHAR *)calloc(mesh.vertices().nodesCount(), sizeof(UCHAR)));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
locals_::VertexesRecorder vertexesRecorder(vertexes);
|
|
Toshihiro Shimizu |
890ddd |
std::stack<int> verticesQueue;</int>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Launch it
|
|
Toshihiro Shimizu |
890ddd |
boost::breadth_first_visit(mesh, int(mesh.vertices().begin().index()),
|
|
Toshihiro Shimizu |
890ddd |
verticesQueue, boost::make_bfs_visitor(vertexesRecorder), colorMapP.get());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}; // locals
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Retrieve the list of vertexes in the first connected component
|
|
Toshihiro Shimizu |
890ddd |
TTextureMesh &origMesh = *mi.meshes()[meshIdx];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
boost::unordered_set<int> firstComponent;</int>
|
|
Toshihiro Shimizu |
890ddd |
locals::buildConnectedComponent(origMesh, firstComponent);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (firstComponent.size() == origMesh.verticesCount())
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// There are (exactly) 2 connected components. Just duplicate the mesh
|
|
Toshihiro Shimizu |
890ddd |
// and keep/delete found vertexes.
|
|
Toshihiro Shimizu |
890ddd |
TTextureMeshP dupMeshPtr(new TTextureMesh(origMesh));
|
|
Toshihiro Shimizu |
890ddd |
TTextureMesh &dupMesh = *dupMeshPtr;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TTextureMesh::vertices_container &vertices = origMesh.vertices();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TTextureMesh::vertices_container::iterator vt, vEnd = vertices.end();
|
|
Toshihiro Shimizu |
890ddd |
for (vt = vertices.begin(); vt != vEnd;) {
|
|
Toshihiro Shimizu |
890ddd |
int v = int(vt.index());
|
|
Toshihiro Shimizu |
890ddd |
++vt;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (firstComponent.count(v))
|
|
Toshihiro Shimizu |
890ddd |
dupMesh.removeVertex(v);
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
origMesh.removeVertex(v);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
dupMesh.squeeze();
|
|
Toshihiro Shimizu |
890ddd |
origMesh.squeeze();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
mi.meshes().push_back(dupMeshPtr);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void splitMesh(TMeshImage &mi, int meshIdx, int lastBoundaryVertex)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
// Retrieve a cutting edge with a single adjacent face - cutting that
|
|
Toshihiro Shimizu |
890ddd |
// will just duplicate the vertex and separate the mesh in 2 connected
|
|
Toshihiro Shimizu |
890ddd |
// components
|
|
Toshihiro Shimizu |
890ddd |
TTextureMesh &mesh = *mi.meshes()[meshIdx];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int e;
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
const vertex_type &lbVx = mesh.vertex(lastBoundaryVertex);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
vertex_type::edges_const_iterator et =
|
|
Toshihiro Shimizu |
890ddd |
std::find_if(lbVx.edgesBegin(), lbVx.edgesEnd(), tcg::bind1st(&borderEdge, mesh));
|
|
Toshihiro Shimizu |
890ddd |
assert(et != lbVx.edgesEnd());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
e = *et;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
cutEdge(mesh, EdgeCut(lastBoundaryVertex, e));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// At this point, separate the 2 resulting connected components
|
|
Toshihiro Shimizu |
890ddd |
// in 2 separate meshes (if necessary)
|
|
Toshihiro Shimizu |
890ddd |
splitUnconnectedMesh(mi, meshIdx);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool cutMesh(TMeshImage &mi, const PlasticTool::MeshSelection &edgesSelection)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
struct locals {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
static int lastVertex(
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh &mesh, const std::vector<edgecut> &edgeCuts)</edgecut>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return mesh.edge(edgeCuts.back().m_eIdx)
|
|
Toshihiro Shimizu |
890ddd |
.otherVertex(edgeCuts.back().m_vIdx);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
static int lastBoundaryVertex(
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh &mesh, const std::vector<edgecut> &edgeCuts)</edgecut>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int v = lastVertex(mesh, edgeCuts);
|
|
Toshihiro Shimizu |
890ddd |
return ::borderVertex(mesh, v) ? v : -1;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
}; // locals
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::vector<edgecut> edgeCuts;</edgecut>
|
|
Toshihiro Shimizu |
890ddd |
int meshIdx;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!::buildEdgeCuts(mi, edgesSelection, meshIdx, edgeCuts))
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TTextureMesh &mesh = *mi.meshes()[meshIdx];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int lastBoundaryVertex = locals::lastBoundaryVertex(mesh, edgeCuts);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Slit the mesh on the first edge, in case the cuts do not start
|
|
Toshihiro Shimizu |
890ddd |
// on the mesh boundary
|
|
Toshihiro Shimizu |
890ddd |
std::vector<edgecut>::iterator ecBegin = edgeCuts.begin();</edgecut>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!::borderVertex(mesh, ecBegin->m_vIdx)) {
|
|
Toshihiro Shimizu |
890ddd |
::slitMesh(mesh, ecBegin->m_eIdx);
|
|
Toshihiro Shimizu |
890ddd |
++ecBegin;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Cut edges, in the order specified by edgeCuts
|
|
Toshihiro Shimizu |
890ddd |
std::for_each(ecBegin, edgeCuts.end(),
|
|
Toshihiro Shimizu |
890ddd |
tcg::bind1st(&cutEdge, mesh));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Finally, the mesh could have been split in 2 - we need to separate
|
|
Toshihiro Shimizu |
890ddd |
// the pieces if needed
|
|
Toshihiro Shimizu |
890ddd |
if (lastBoundaryVertex >= 0)
|
|
Toshihiro Shimizu |
890ddd |
splitMesh(mi, meshIdx, lastBoundaryVertex);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} // namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//****************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Undo definitions
|
|
Toshihiro Shimizu |
890ddd |
//****************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class MoveVertexUndo_Mesh : public TUndo
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int m_row, m_col; //!< Xsheet coordinates
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::vector<meshindex> m_vIdxs; //!< Moved vertices</meshindex>
|
|
Toshihiro Shimizu |
890ddd |
std::vector<tpointd> m_origVxsPos; //!< Original vertex positions</tpointd>
|
|
Toshihiro Shimizu |
890ddd |
TPointD m_posShift; //!< Vertex positions shift
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
MoveVertexUndo_Mesh(
|
|
Toshihiro Shimizu |
890ddd |
const std::vector<meshindex> &vIdxs,</meshindex>
|
|
Toshihiro Shimizu |
890ddd |
const std::vector<tpointd> &origVxsPos,</tpointd>
|
|
Toshihiro Shimizu |
890ddd |
const TPointD &posShift)
|
|
Toshihiro Shimizu |
890ddd |
: m_row(::row()), m_col(::column()), m_vIdxs(vIdxs), m_origVxsPos(origVxsPos), m_posShift(posShift)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(m_vIdxs.size() == m_origVxsPos.size());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int getSize() const { return int(sizeof(*this) + m_vIdxs.size() * (sizeof(int) + 2 * sizeof(TPointD))); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void redo() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
PlasticTool::TemporaryActivation tempActivate(m_row, m_col);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.setMeshVertexesSelection(m_vIdxs);
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.moveVertex_mesh(m_origVxsPos, m_posShift);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.invalidate();
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.notifyImageChanged(); // IMPORTANT: In particular, sets the level's
|
|
Toshihiro Shimizu |
890ddd |
} // dirty flag, so Toonz knows it has
|
|
Toshihiro Shimizu |
890ddd |
// to be saved!
|
|
Toshihiro Shimizu |
890ddd |
void undo() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
PlasticTool::TemporaryActivation tempActivate(m_row, m_col);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.setMeshVertexesSelection(m_vIdxs);
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.moveVertex_mesh(m_origVxsPos, TPointD());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.invalidate();
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.notifyImageChanged();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//==============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class SwapEdgeUndo : public TUndo
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int m_row, m_col; //!< Xsheet coordinates
|
|
Toshihiro Shimizu |
890ddd |
mutable MeshIndex m_edgeIdx; //!< Edge index
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
SwapEdgeUndo(const MeshIndex &edgeIdx)
|
|
Toshihiro Shimizu |
890ddd |
: m_row(::row()), m_col(::column()), m_edgeIdx(edgeIdx) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int getSize() const { return sizeof(*this); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void redo() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
PlasticTool::TemporaryActivation tempActivate(m_row, m_col);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TMeshImageP &mi = TMeshImageP(TTool::getImage(true));
|
|
Toshihiro Shimizu |
890ddd |
assert(mi);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Perform swap
|
|
Toshihiro Shimizu |
890ddd |
TTextureMesh &mesh = *mi->meshes()[m_edgeIdx.m_meshIdx];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_edgeIdx.m_idx = mesh.swapEdge(m_edgeIdx.m_idx);
|
|
Toshihiro Shimizu |
890ddd |
assert(m_edgeIdx.m_idx >= 0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Invalidate any deformer associated with mi
|
|
Toshihiro Shimizu |
890ddd |
PlasticDeformerStorage::instance()->releaseMeshData(mi.getPointer());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Update tool selection
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.setMeshEdgesSelection(m_edgeIdx);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.invalidate();
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.notifyImageChanged();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void undo() const { redo(); } // Operation is idempotent (indices
|
|
Toshihiro Shimizu |
890ddd |
// are perfectly restored, too)
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//==============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class TTextureMeshUndo : public TUndo
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
protected:
|
|
Toshihiro Shimizu |
890ddd |
int m_row, m_col; //!< Xsheet coordinates
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int m_meshIdx; //!< Mesh index in the image at stored xsheet coords
|
|
Toshihiro Shimizu |
890ddd |
mutable TTextureMesh m_origMesh; //!< Copy of the original mesh
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
TTextureMeshUndo(int meshIdx)
|
|
Toshihiro Shimizu |
890ddd |
: m_row(::row()), m_col(::column()), m_meshIdx(meshIdx) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Let's say 1MB each - storing the mesh is costly
|
|
Toshihiro Shimizu |
890ddd |
int getSize() const { return 1 << 20; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TMeshImageP getMeshImage() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
const TMeshImageP &mi = TMeshImageP(TTool::getImage(true));
|
|
Toshihiro Shimizu |
890ddd |
assert(mi);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return mi;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//==============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class CollapseEdgeUndo : public TTextureMeshUndo
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int m_eIdx; //!< Collapsed edge index
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
CollapseEdgeUndo(const MeshIndex &edgeIdx)
|
|
Toshihiro Shimizu |
890ddd |
: TTextureMeshUndo(edgeIdx.m_meshIdx), m_eIdx(edgeIdx.m_idx) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void redo() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
PlasticTool::TemporaryActivation tempActivate(m_row, m_col);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TMeshImageP &mi = getMeshImage();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Store the original mesh
|
|
Toshihiro Shimizu |
890ddd |
TTextureMesh &mesh = *mi->meshes()[m_meshIdx];
|
|
Toshihiro Shimizu |
890ddd |
m_origMesh = mesh;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Collapse
|
|
Toshihiro Shimizu |
890ddd |
mesh.collapseEdge(m_eIdx);
|
|
Toshihiro Shimizu |
890ddd |
mesh.squeeze();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Invalidate any cached deformer associated with the modified mesh image
|
|
Toshihiro Shimizu |
890ddd |
PlasticDeformerStorage::instance()->releaseMeshData(mi.getPointer());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Refresh the tool
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.clearMeshSelections();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.invalidate();
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.notifyImageChanged();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void undo() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
PlasticTool::TemporaryActivation tempActivate(m_row, m_col);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TMeshImageP &mi = getMeshImage();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Restore the original mesh
|
|
Toshihiro Shimizu |
890ddd |
TTextureMesh &mesh = *mi->meshes()[m_meshIdx];
|
|
Toshihiro Shimizu |
890ddd |
mesh = m_origMesh;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
PlasticDeformerStorage::instance()->releaseMeshData(mi.getPointer());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Restore selection
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.setMeshEdgesSelection(MeshIndex(m_meshIdx, m_eIdx));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.invalidate();
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.notifyImageChanged();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//==============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class SplitEdgeUndo : public TTextureMeshUndo
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int m_eIdx; //!< Split edge index
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
SplitEdgeUndo(const MeshIndex &edgeIdx)
|
|
Toshihiro Shimizu |
890ddd |
: TTextureMeshUndo(edgeIdx.m_meshIdx), m_eIdx(edgeIdx.m_idx) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void redo() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
PlasticTool::TemporaryActivation tempActivate(m_row, m_col);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TMeshImageP &mi = getMeshImage();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Store the original mesh
|
|
Toshihiro Shimizu |
890ddd |
TTextureMesh &mesh = *mi->meshes()[m_meshIdx];
|
|
Toshihiro Shimizu |
890ddd |
m_origMesh = mesh;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Split
|
|
Toshihiro Shimizu |
890ddd |
mesh.splitEdge(m_eIdx);
|
|
Toshihiro Shimizu |
890ddd |
//mesh.squeeze(); // There should be no need to squeeze
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(mesh.vertices().size() == mesh.vertices().nodesCount()); //
|
|
Toshihiro Shimizu |
890ddd |
assert(mesh.edges().size() == mesh.edges().nodesCount()); //
|
|
Toshihiro Shimizu |
890ddd |
assert(mesh.faces().size() == mesh.faces().nodesCount()); //
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
PlasticDeformerStorage::instance()->releaseMeshData(mi.getPointer());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.clearMeshSelections();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.invalidate();
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.notifyImageChanged();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void undo() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
PlasticTool::TemporaryActivation tempActivate(m_row, m_col);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TMeshImageP &mi = getMeshImage();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Restore the original mesh
|
|
Toshihiro Shimizu |
890ddd |
TTextureMesh &mesh = *mi->meshes()[m_meshIdx];
|
|
Toshihiro Shimizu |
890ddd |
mesh = m_origMesh;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
PlasticDeformerStorage::instance()->releaseMeshData(mi.getPointer());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Restore selection
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.setMeshEdgesSelection(MeshIndex(m_meshIdx, m_eIdx));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.invalidate();
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.notifyImageChanged();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//==============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class CutEdgesUndo : public TUndo
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int m_row, m_col; //!< Xsheet coordinates
|
|
Toshihiro Shimizu |
890ddd |
TMeshImageP m_origImage; //!< Clone of the original image
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
PlasticTool::MeshSelection m_edgesSelection; //!< Selection to operate on
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
CutEdgesUndo(const PlasticTool::MeshSelection &edgesSelection)
|
|
Toshihiro Shimizu |
890ddd |
: m_row(::row()), m_col(::column()), m_origImage(TTool::getImage(false)->cloneImage()), m_edgesSelection(edgesSelection) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int getSize() const { return 1 << 20; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool do_() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TMeshImageP mi = TTool::getImage(true);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (::cutMesh(*mi, m_edgesSelection)) {
|
|
Toshihiro Shimizu |
890ddd |
PlasticDeformerStorage::instance()->releaseMeshData(mi.getPointer());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.clearMeshSelections();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.invalidate();
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.notifyImageChanged();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void redo() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
PlasticTool::TemporaryActivation tempActivate(m_row, m_col);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool ret = do_();
|
|
Toshihiro Shimizu |
890ddd |
(void)ret;
|
|
Toshihiro Shimizu |
890ddd |
assert(ret);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void undo() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
PlasticTool::TemporaryActivation tempActivate(m_row, m_col);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TMeshImageP mi = TTool::getImage(true);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Restore the original image
|
|
Toshihiro Shimizu |
890ddd |
*mi = *m_origImage;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
PlasticDeformerStorage::instance()->releaseMeshData(mi.getPointer());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Restore selection
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.setMeshEdgesSelection(m_edgesSelection);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.invalidate();
|
|
Toshihiro Shimizu |
890ddd |
l_plasticTool.notifyImageChanged();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} // namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//****************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// PlasticTool functions
|
|
Toshihiro Shimizu |
890ddd |
//****************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticTool::storeMeshImage()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TMeshImageP mi = getImage(false);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (mi != m_mi) {
|
|
Toshihiro Shimizu |
890ddd |
m_mi = mi;
|
|
Toshihiro Shimizu |
890ddd |
clearMeshSelections();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticTool::setMeshSelection(MeshSelection &target, const MeshSelection &newSel)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (newSel.isEmpty()) {
|
|
Toshihiro Shimizu |
890ddd |
target.selectNone();
|
|
Toshihiro Shimizu |
890ddd |
target.makeNotCurrent();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
target.setObjects(newSel.objects());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
target.notifyView();
|
|
Toshihiro Shimizu |
890ddd |
target.makeCurrent();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticTool::toggleMeshSelection(MeshSelection &target, const MeshSelection &addition)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
typedef MeshSelection::objects_container objects_container;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const objects_container &storedIdxs = target.objects();
|
|
Toshihiro Shimizu |
890ddd |
const objects_container &addedIdxs = addition.objects();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Build new selection
|
|
Toshihiro Shimizu |
890ddd |
objects_container selectedIdxs;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (target.contains(addition)) {
|
|
Toshihiro Shimizu |
890ddd |
std::set_difference(
|
|
Toshihiro Shimizu |
890ddd |
storedIdxs.begin(), storedIdxs.end(),
|
|
Toshihiro Shimizu |
890ddd |
addedIdxs.begin(), addedIdxs.end(),
|
|
Toshihiro Shimizu |
890ddd |
std::back_inserter(selectedIdxs));
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
std::set_union(
|
|
Toshihiro Shimizu |
890ddd |
storedIdxs.begin(), storedIdxs.end(),
|
|
Toshihiro Shimizu |
890ddd |
addedIdxs.begin(), addedIdxs.end(),
|
|
Toshihiro Shimizu |
890ddd |
std::back_inserter(selectedIdxs));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
setMeshSelection(target, selectedIdxs);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticTool::clearMeshSelections()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_mvHigh = m_meHigh = MeshIndex();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_mvSel.selectNone();
|
|
Toshihiro Shimizu |
890ddd |
m_mvSel.makeNotCurrent();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_meSel.selectNone();
|
|
Toshihiro Shimizu |
890ddd |
m_meSel.makeNotCurrent();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticTool::setMeshVertexesSelection(const MeshSelection &vSel)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
setMeshSelection(m_meSel, MeshSelection()), setMeshSelection(m_mvSel, vSel);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticTool::toggleMeshVertexesSelection(const MeshSelection &vSel)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
setMeshSelection(m_meSel, MeshSelection()), toggleMeshSelection(m_mvSel, vSel);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticTool::setMeshEdgesSelection(const MeshSelection &eSel)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
setMeshSelection(m_meSel, eSel), setMeshSelection(m_mvSel, MeshSelection());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticTool::toggleMeshEdgesSelection(const MeshSelection &eSel)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
toggleMeshSelection(m_meSel, eSel), setMeshSelection(m_mvSel, MeshSelection());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticTool::mouseMove_mesh(const TPointD &pos, const TMouseEvent &me)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
// Track mouse position
|
|
Toshihiro Shimizu |
890ddd |
m_pos = pos; // Needs to be done now - ensures m_pos is valid
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_mvHigh = MeshIndex(); // Reset highlighted primitives
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_mi) {
|
|
Toshihiro Shimizu |
890ddd |
// Look for nearest primitive
|
|
Toshihiro Shimizu |
890ddd |
std::pair<double, meshindex=""> closestVertex = ::closestVertex(*m_mi, pos),</double,>
|
|
Toshihiro Shimizu |
890ddd |
closestEdge = ::closestEdge(*m_mi, pos);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Discriminate on fixed metric
|
|
Toshihiro Shimizu |
890ddd |
const double hDistSq = sq(getPixelSize() * MESH_HIGHLIGHT_DISTANCE);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_mvHigh = m_meHigh = MeshIndex();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (closestEdge.first < hDistSq)
|
|
Toshihiro Shimizu |
890ddd |
m_meHigh = closestEdge.second;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (closestVertex.first < hDistSq)
|
|
Toshihiro Shimizu |
890ddd |
m_mvHigh = closestVertex.second, m_meHigh = MeshIndex();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(!(m_mvHigh && m_meHigh)); // Vertex and edge highlights are mutually exclusive
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticTool::leftButtonDown_mesh(const TPointD &pos, const TMouseEvent &me)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
struct Locals {
|
|
Toshihiro Shimizu |
890ddd |
PlasticTool *m_this;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void updateSelection(MeshSelection &sel, const MeshIndex &idx, const TMouseEvent &me)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (idx) {
|
|
Toshihiro Shimizu |
890ddd |
MeshSelection newSel(idx);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (me.isCtrlPressed())
|
|
Toshihiro Shimizu |
890ddd |
m_this->toggleMeshSelection(sel, newSel);
|
|
Toshihiro Shimizu |
890ddd |
else if (!sel.contains(newSel))
|
|
Toshihiro Shimizu |
890ddd |
m_this->setMeshSelection(sel, newSel);
|
|
Toshihiro Shimizu |
890ddd |
} else
|
|
Toshihiro Shimizu |
890ddd |
m_this->setMeshSelection(sel, MeshSelection());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
static TPointD vertexPos(const TMeshImage &mi, const MeshIndex &meshIdx)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return mi.meshes()[meshIdx.m_meshIdx]->vertex(meshIdx.m_idx).P();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} locals = {this};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Track mouse position
|
|
Toshihiro Shimizu |
890ddd |
m_pressedPos = m_pos = pos;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Update selection
|
|
Toshihiro Shimizu |
890ddd |
locals.updateSelection(m_mvSel, m_mvHigh, me);
|
|
Toshihiro Shimizu |
890ddd |
locals.updateSelection(m_meSel, m_meHigh, me);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Store original vertex positions
|
|
Toshihiro Shimizu |
890ddd |
if (!m_mvSel.isEmpty()) {
|
|
Toshihiro Shimizu |
890ddd |
m_pressedVxsPos = std::vector<tpointd>(</tpointd>
|
|
Toshihiro Shimizu |
890ddd |
tcg::make_cast_it(m_mvSel.objects().begin(), tcg::bind1st(&Locals::vertexPos, *m_mi)),
|
|
Toshihiro Shimizu |
890ddd |
tcg::make_cast_it(m_mvSel.objects().end(), tcg::bind1st(&Locals::vertexPos, *m_mi)));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Redraw selections
|
|
Toshihiro Shimizu |
890ddd |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticTool::leftButtonDrag_mesh(const TPointD &pos, const TMouseEvent &me)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
// Track mouse position
|
|
Toshihiro Shimizu |
890ddd |
m_pos = pos;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!m_mvSel.isEmpty()) {
|
|
Toshihiro Shimizu |
890ddd |
moveVertex_mesh(m_pressedVxsPos, pos - m_pressedPos);
|
|
Toshihiro Shimizu |
890ddd |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticTool::leftButtonUp_mesh(const TPointD &pos, const TMouseEvent &me)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
// Track mouse position
|
|
Toshihiro Shimizu |
890ddd |
m_pos = pos;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_dragged && !m_mvSel.isEmpty()) {
|
|
Toshihiro Shimizu |
890ddd |
TUndoManager::manager()->add(new MoveVertexUndo_Mesh(
|
|
Toshihiro Shimizu |
890ddd |
m_mvSel.objects(), m_pressedVxsPos, pos - m_pressedPos));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
notifyImageChanged(); // Sets the level's dirty flag -.-'
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticTool::addContextMenuActions_mesh(QMenu *menu)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
bool ret = true;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!m_meSel.isEmpty()) {
|
|
Toshihiro Shimizu |
890ddd |
if (m_meSel.hasSingleObject()) {
|
|
Toshihiro Shimizu |
890ddd |
const MeshIndex &mIdx = m_meSel.objects().front();
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh &mesh = *m_mi->meshes()[mIdx.m_meshIdx];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (::testSwapEdge(mesh, mIdx.m_idx)) {
|
|
Toshihiro Shimizu |
890ddd |
QAction *swapEdge = menu->addAction(tr("Swap Edge"));
|
|
Toshihiro Shimizu |
890ddd |
ret = ret && connect(swapEdge, SIGNAL(triggered()), &l_plasticTool, SLOT(swapEdge_mesh_undo()));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (::testCollapseEdge(mesh, mIdx.m_idx)) {
|
|
Toshihiro Shimizu |
890ddd |
QAction *collapseEdge = menu->addAction(tr("Collapse Edge"));
|
|
Toshihiro Shimizu |
890ddd |
ret = ret && connect(collapseEdge, SIGNAL(triggered()), &l_plasticTool, SLOT(collapseEdge_mesh_undo()));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QAction *splitEdge = menu->addAction(tr("Split Edge"));
|
|
Toshihiro Shimizu |
890ddd |
ret = ret && connect(splitEdge, SIGNAL(triggered()), &l_plasticTool, SLOT(splitEdge_mesh_undo()));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (::testCutMesh(*m_mi, m_meSel)) {
|
|
Toshihiro Shimizu |
890ddd |
QAction *cutEdges = menu->addAction(tr("Cut Mesh"));
|
|
Toshihiro Shimizu |
890ddd |
ret = ret && connect(cutEdges, SIGNAL(triggered()), &l_plasticTool, SLOT(cutEdges_mesh_undo()));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
menu->addSeparator();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(ret);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticTool::moveVertex_mesh(
|
|
Toshihiro Shimizu |
890ddd |
const std::vector<tpointd> &origVxsPos, const TPointD &posShift)</tpointd>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_mvSel.isEmpty() || !m_mi)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(origVxsPos.size() == m_mvSel.objects().size());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Move selected vertices
|
|
Toshihiro Shimizu |
890ddd |
TMeshImageP mi = getImage(true);
|
|
Toshihiro Shimizu |
890ddd |
assert(m_mi == mi);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int v, vCount = int(m_mvSel.objects().size());
|
|
Toshihiro Shimizu |
890ddd |
for (v = 0; v != vCount; ++v) {
|
|
Toshihiro Shimizu |
890ddd |
const MeshIndex &meshIndex = m_mvSel.objects()[v];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TTextureMesh &mesh = *mi->meshes()[meshIndex.m_meshIdx];
|
|
Toshihiro Shimizu |
890ddd |
mesh.vertex(meshIndex.m_idx).P() = origVxsPos[v] + posShift;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Mesh must be recompiled
|
|
Toshihiro Shimizu |
890ddd |
PlasticDeformerStorage::instance()->invalidateMeshImage(
|
|
Toshihiro Shimizu |
890ddd |
mi.getPointer(), PlasticDeformerStorage::MESH);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticTool::swapEdge_mesh_undo()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!(m_mi && m_meSel.hasSingleObject()))
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Test current edge swapability
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
const MeshIndex &eIdx = m_meSel.objects().front();
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh &mesh = *m_mi->meshes()[eIdx.m_meshIdx];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!::testSwapEdge(mesh, eIdx.m_idx))
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Perform operation
|
|
Toshihiro Shimizu |
890ddd |
std::auto_ptr<tundo> undo(new SwapEdgeUndo(m_meSel.objects().front()));</tundo>
|
|
Toshihiro Shimizu |
890ddd |
undo->redo();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TUndoManager::manager()->add(undo.release());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticTool::collapseEdge_mesh_undo()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!(m_mi && m_meSel.hasSingleObject()))
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Test collapsibility of current edge
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
const MeshIndex &eIdx = m_meSel.objects().front();
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh &mesh = *m_mi->meshes()[eIdx.m_meshIdx];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!::testCollapseEdge(mesh, eIdx.m_idx))
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Perform operation
|
|
Toshihiro Shimizu |
890ddd |
std::auto_ptr<tundo> undo(new CollapseEdgeUndo(m_meSel.objects().front()));</tundo>
|
|
Toshihiro Shimizu |
890ddd |
undo->redo();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TUndoManager::manager()->add(undo.release());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticTool::splitEdge_mesh_undo()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!(m_mi && m_meSel.hasSingleObject()))
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::auto_ptr<tundo> undo(new SplitEdgeUndo(m_meSel.objects().front()));</tundo>
|
|
Toshihiro Shimizu |
890ddd |
undo->redo();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TUndoManager::manager()->add(undo.release());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticTool::cutEdges_mesh_undo()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!m_mi)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::auto_ptr<cutedgesundo> undo(new CutEdgesUndo(m_meSel.objects()));</cutedgesundo>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (undo->do_())
|
|
Toshihiro Shimizu |
890ddd |
TUndoManager::manager()->add(undo.release());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticTool::draw_mesh()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
struct Locals {
|
|
Toshihiro Shimizu |
890ddd |
PlasticTool *m_this;
|
|
Toshihiro Shimizu |
890ddd |
double m_pixelSize;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void drawLine(const TPointD &a, const TPointD &b)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
glVertex2d(a.x, a.y);
|
|
Toshihiro Shimizu |
890ddd |
glVertex2d(b.x, b.y);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void drawVertexSelections()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
typedef MeshSelection::objects_container objects_container;
|
|
Toshihiro Shimizu |
890ddd |
const objects_container &objects = m_this->m_mvSel.objects();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
glColor3ub(255, 0, 0); // Red
|
|
Toshihiro Shimizu |
890ddd |
glLineWidth(1.0f);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const double hSize = MESH_SELECTED_HANDLE_SIZE * m_pixelSize;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
objects_container::const_iterator vt, vEnd = objects.end();
|
|
Toshihiro Shimizu |
890ddd |
for (vt = objects.begin(); vt != vEnd; ++vt) {
|
|
Toshihiro Shimizu |
890ddd |
const TTextureVertex &vx = m_this->m_mi->meshes()[vt->m_meshIdx]
|
|
Toshihiro Shimizu |
890ddd |
->vertex(vt->m_idx);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
::drawFullSquare(vx.P(), hSize);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void drawEdgeSelections()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
typedef MeshSelection::objects_container objects_container;
|
|
Toshihiro Shimizu |
890ddd |
const objects_container &objects = m_this->m_meSel.objects();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
glColor3ub(0, 0, 255); // Blue
|
|
Toshihiro Shimizu |
890ddd |
glLineWidth(2.0f);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
glBegin(GL_LINES);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
objects_container::const_iterator et, eEnd = objects.end();
|
|
Toshihiro Shimizu |
890ddd |
for (et = objects.begin(); et != eEnd; ++et) {
|
|
Toshihiro Shimizu |
890ddd |
const TTextureVertex
|
|
Toshihiro Shimizu |
890ddd |
&vx0 = m_this->m_mi->meshes()[et->m_meshIdx]->edgeVertex(et->m_idx, 0),
|
|
Toshihiro Shimizu |
890ddd |
&vx1 = m_this->m_mi->meshes()[et->m_meshIdx]->edgeVertex(et->m_idx, 1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
drawLine(vx0.P(), vx1.P());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
glEnd();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void drawVertexHighlights()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_this->m_mvHigh) {
|
|
Toshihiro Shimizu |
890ddd |
const MeshIndex &vHigh = m_this->m_mvHigh;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh::vertex_type &vx =
|
|
Toshihiro Shimizu |
890ddd |
m_this->m_mi->meshes()[vHigh.m_meshIdx]->vertex(vHigh.m_idx);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
glColor3ub(255, 0, 0); // Red
|
|
Toshihiro Shimizu |
890ddd |
glLineWidth(1.0f);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const double hSize = MESH_HIGHLIGHTED_HANDLE_SIZE * m_pixelSize;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
::drawSquare(vx.P(), hSize);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void drawEdgeHighlights()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_this->m_meHigh) {
|
|
Toshihiro Shimizu |
890ddd |
const MeshIndex &eHigh = m_this->m_meHigh;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh::vertex_type
|
|
Toshihiro Shimizu |
890ddd |
&vx0 = m_this->m_mi->meshes()[eHigh.m_meshIdx]->edgeVertex(eHigh.m_idx, 0),
|
|
Toshihiro Shimizu |
890ddd |
&vx1 = m_this->m_mi->meshes()[eHigh.m_meshIdx]->edgeVertex(eHigh.m_idx, 1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
glPushAttrib(GL_LINE_BIT);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
glEnable(GL_LINE_STIPPLE);
|
|
Toshihiro Shimizu |
890ddd |
glLineStipple(1, 0xCCCC);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
glColor3ub(0, 0, 255); // Blue
|
|
Toshihiro Shimizu |
890ddd |
glLineWidth(1.0f);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
glBegin(GL_LINES);
|
|
Toshihiro Shimizu |
890ddd |
drawLine(vx0.P(), vx1.P());
|
|
Toshihiro Shimizu |
890ddd |
glEnd();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
glPopAttrib();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} locals = {this, getPixelSize()};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// The selected mesh image is already drawn by the stage
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Draw additional overlays
|
|
Toshihiro Shimizu |
890ddd |
if (m_mi) {
|
|
Toshihiro Shimizu |
890ddd |
locals.drawVertexSelections();
|
|
Toshihiro Shimizu |
890ddd |
locals.drawEdgeSelections();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
locals.drawVertexHighlights();
|
|
Toshihiro Shimizu |
890ddd |
locals.drawEdgeHighlights();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|