1
// ---------------------------------------------------------
6
// Identifies "singular vertices", defined as having more than one connected triangle neighbourhoods, and
7
// splits the mesh surface at these vertices.
9
// ---------------------------------------------------------
11
#include <meshpincher.h>
13
#include <broadphase.h>
14
#include <surftrack.h>
17
// ---------------------------------------------------------
18
// Member function definitions
19
// ---------------------------------------------------------
21
// --------------------------------------------------------
23
/// Partition the triangles incident to a vertex into connected components
25
// --------------------------------------------------------
27
void MeshPincher::partition_vertex_neighbourhood( size_t vertex_index, std::vector< TriangleSet >& connected_components )
29
// triangles incident to vertex
30
TriangleSet triangles_incident_to_vertex = m_surf.m_mesh.m_vertex_to_triangle_map[vertex_index];
32
// unvisited triangles which are adjacent to some visited ones and incident to vt
33
TriangleSet unvisited_triangles, visited_triangles;
35
while ( triangles_incident_to_vertex.size() > 0 )
37
unvisited_triangles.clear();
38
visited_triangles.clear();
39
unvisited_triangles.push_back( triangles_incident_to_vertex.back() );
41
while ( unvisited_triangles.size() > 0 )
43
// get an unvisited triangle
44
size_t curr_tri = unvisited_triangles.back();
45
unvisited_triangles.pop_back();
47
// delete it from triangles_incident_to_vertex
48
triangles_incident_to_vertex.erase( find(triangles_incident_to_vertex.begin(), triangles_incident_to_vertex.end(), curr_tri) );
51
visited_triangles.push_back(curr_tri);
53
// get find a triangle which is incident to vertex and adjacent to curr_tri
54
for ( size_t i = 0; i < triangles_incident_to_vertex.size(); ++i )
56
size_t incident_triangle_index = triangles_incident_to_vertex[i];
58
if ( curr_tri == incident_triangle_index )
63
if ( m_surf.m_mesh.triangles_are_adjacent( curr_tri, incident_triangle_index ) )
65
// if not in visited_triangles or unvisited_triangles, put them on unvisited_triangles
66
if ( ( find(unvisited_triangles.begin(), unvisited_triangles.end(), incident_triangle_index) == unvisited_triangles.end() ) &&
67
( find(visited_triangles.begin(), visited_triangles.end(), incident_triangle_index) == visited_triangles.end() ) )
69
unvisited_triangles.push_back( incident_triangle_index );
75
// one connected component = visited triangles
76
connected_components.push_back(visited_triangles);
80
// --------------------------------------------------------
82
/// Duplicate a vertex and move the two copies away from each other slightly
84
// --------------------------------------------------------
86
bool MeshPincher::pull_apart_vertex( size_t vertex_index, const std::vector< TriangleSet >& connected_components )
88
double dx = 10.0 * m_surf.m_proximity_epsilon;
90
TriangleSet triangles_to_delete;
91
std::vector< Vec3st > triangles_to_add;
92
std::vector< size_t > vertices_added;
94
// for each connected component except the last one, create a duplicate vertex
95
for ( int i = 0; i < (int)connected_components.size() - 1; ++i )
97
// duplicate the vertex
98
size_t duplicate_vertex_index = m_surf.add_vertex( m_surf.get_position(vertex_index), m_surf.m_masses[vertex_index] );
100
vertices_added.push_back( duplicate_vertex_index );
102
Vec3d centroid( 0.0, 0.0, 0.0 );
104
// map component triangles to the duplicate vertex
105
for ( size_t t = 0; t < connected_components[i].size(); ++t )
107
// create a new triangle with 2 vertices the same, and one vertex set to the new duplicate vertex
108
Vec3st new_triangle = m_surf.m_mesh.get_triangle( connected_components[i][t] );
110
for ( unsigned short v = 0; v < 3; ++v )
112
if ( new_triangle[v] == vertex_index )
114
new_triangle[v] = duplicate_vertex_index;
118
centroid += m_surf.get_position( new_triangle[v] );
122
triangles_to_add.push_back( new_triangle );
123
triangles_to_delete.push_back( connected_components[i][t] );
126
// compute the centroid
127
centroid /= ( connected_components[i].size() * 2 );
129
// move the duplicate vertex towards the centroid
131
Vec3d added_vertex_position = (1.0 - dx) * m_surf.get_position(duplicate_vertex_index) + dx * centroid;
133
m_surf.set_position( duplicate_vertex_index, added_vertex_position );
134
m_surf.set_newposition( duplicate_vertex_index, added_vertex_position );
138
// check new triangles for collision safety
140
bool collision_occurs = false;
142
if ( m_surf.m_collision_safety )
145
for ( size_t i = 0; i < triangles_to_add.size(); ++i )
147
const Vec3st& current_triangle = triangles_to_add[i];
150
minmax( m_surf.get_position(current_triangle[0]), m_surf.get_position(current_triangle[1]), m_surf.get_position(current_triangle[2]), low, high );
152
std::vector<size_t> overlapping_triangles;
153
m_surf.m_broad_phase->get_potential_triangle_collisions( low, high, true, true, overlapping_triangles );
155
for ( size_t j=0; j < overlapping_triangles.size(); ++j )
157
const Vec3st& tri_j = m_surf.m_mesh.get_triangle(overlapping_triangles[j]);
159
assert( tri_j[0] != tri_j[1] );
161
if ( check_triangle_triangle_intersection( current_triangle, tri_j, m_surf.get_positions() ) )
163
// collision occurs - abort separation
164
collision_occurs = true;
170
// check new triangles vs each other as well
171
for ( size_t i = 0; i < triangles_to_add.size(); ++i )
173
for ( size_t j = i+1; j < triangles_to_add.size(); ++j )
175
if ( check_triangle_triangle_intersection( triangles_to_add[i], triangles_to_add[j], m_surf.get_positions() ) )
177
// collision occurs - abort separation
178
collision_occurs = true;
185
// abort separation, remove added vertices and return
187
if ( collision_occurs )
189
for ( size_t i = 0; i < vertices_added.size(); ++i )
191
m_surf.remove_vertex( vertices_added[i] );
196
// all new triangles check out okay for collision safety. Add them to the data structure.
198
for ( size_t i = 0; i < triangles_to_add.size(); ++i )
200
m_surf.add_triangle( triangles_to_add[i] );
203
for ( size_t i = 0; i < triangles_to_delete.size(); ++i )
205
m_surf.remove_triangle( triangles_to_delete[i] );
209
if ( m_surf.m_collision_safety )
211
m_surf.assert_mesh_is_intersection_free(false);
214
if ( m_surf.m_verbose ) { std::cout << "pulled apart a vertex" << std::endl; }
220
// --------------------------------------------------------
222
/// Find vertices with disconnected neighbourhoods, and pull them apart
224
// --------------------------------------------------------
226
void MeshPincher::separate_singular_vertices()
229
for ( size_t i = 0; i < m_surf.get_num_vertices(); ++i )
231
// Partition the set of triangles adjacent to this vertex into connected components
232
std::vector< TriangleSet > connected_components;
233
partition_vertex_neighbourhood( i, connected_components );
235
if ( connected_components.size() > 1 )
237
bool pinched = pull_apart_vertex( i, connected_components );
240
// TODO: Shouldn't need this.
241
m_surf.rebuild_continuous_broad_phase();