1
// ---------------------------------------------------------
6
// The SurfTrack class: a dynamic mesh with topological changes and mesh maintenance operations.
8
// ---------------------------------------------------------
10
#ifndef EL_TOPO_SURFTRACK_H
11
#define EL_TOPO_SURFTRACK_H
13
#include <dynamicsurface.h>
14
#include <edgecollapser.h>
15
#include <edgeflipper.h>
16
#include <edgesplitter.h>
17
#include <meshmerger.h>
18
#include <meshpincher.h>
19
#include <meshsmoother.h>
21
// ---------------------------------------------------------
22
// Forwards and typedefs
23
// ---------------------------------------------------------
25
class SubdivisionScheme;
26
typedef std::vector<size_t> TriangleSet;
28
// ---------------------------------------------------------
30
// ---------------------------------------------------------
32
// ---------------------------------------------------------
34
/// Structure for setting up a SurfTrack object with some initial parameters. This is passed to the SurfTrack constructor.
36
// ---------------------------------------------------------
38
struct SurfTrackInitializationParameters
41
/// Constructor. Sets default values for parameters which are not likely to be specified.
43
SurfTrackInitializationParameters();
45
/// Elements closer than this are considered "near" (or proximate)
47
double m_proximity_epsilon;
49
/// Coefficient of friction to apply during collisions
51
double m_friction_coefficient;
53
/// Smallest triangle area to allow
55
double m_min_triangle_area;
57
/// Collision epsilon to use during mesh improvment operations (i.e. if any mesh elements are closer than this, the operation is
58
/// aborted). NOTE: This should be greater than collision_epsilon, to prevent improvement operations from moving elements into
59
/// a collision configuration.
61
double m_improve_collision_epsilon;
63
/// Whether to set the min and max edge lengths as fractions of the initial average edge length
67
// If use_fraction is true, the following three values are taken to be fractions of the average edge length of the new surface.
68
// If use_fraction is false, these are absolute.
70
/// Smallest edge length allowed
72
double m_min_edge_length;
74
/// Longest edge length allowed
76
double m_max_edge_length;
78
/// Maximum change in volume allowed for one operation
80
double m_max_volume_change;
82
/// Smallest interior angle at a triangle vertex allowed
84
double m_min_triangle_angle;
86
/// Largest interior angle at a triangle vertex allowed
88
double m_max_triangle_angle;
90
/// Whether to scale by curvature when computing edge lengths, in order to refine high-curvature regions
92
bool m_use_curvature_when_splitting;
94
/// Whether to scale by curvature when computing edge lengths, in order to coarsen low-curvature regions
96
bool m_use_curvature_when_collapsing;
98
/// The minimum curvature scaling allowed
100
double m_min_curvature_multiplier;
102
/// The maximum curvature scaling allowed
104
double m_max_curvature_multiplier;
106
/// Whether to allow vertices to move during improvement
108
bool m_allow_vertex_movement;
110
/// Minimum edge length improvement in order to flip an edge
112
double m_edge_flip_min_length_change;
114
/// Elements within this distance will trigger a merge attempt
116
double m_merge_proximity_epsilon;
118
/// Type of subdivision to use when collapsing or splitting (butterfly, quadric error minimization, etc.)
120
SubdivisionScheme *m_subdivision_scheme;
122
/// Whether to enforce collision-free surfaces (including during mesh maintenance operations)
124
bool m_collision_safety;
126
/// Whether to allow changes in topology
128
bool m_allow_topology_changes;
130
/// Whether to allow non-manifold (edges incident on more than two triangles)
132
bool m_allow_non_manifold;
134
/// Whether to allow mesh improvement
136
bool m_perform_improvement;
140
// ---------------------------------------------------------
142
/// Used to build a list of edges sorted in order of increasing length.
144
// ---------------------------------------------------------
150
SortableEdge( size_t ei, double el ) :
155
/// Comparison operator for sorting
157
bool operator<( const SortableEdge& other ) const
159
return (this->m_edge_length < other.m_edge_length);
162
/// The index of the edge
166
/// The stored edge length
168
double m_edge_length;
173
// ---------------------------------------------------------
175
/// Keeps track of a vertex removal or addition. If it's an addition, it also points to the edge that was split to create it.
177
// ---------------------------------------------------------
179
struct VertexUpdateEvent
183
VertexUpdateEvent(bool is_remove = false,
184
size_t vertex_index = (size_t)~0,
185
const Vec2st& split_edge = Vec2st((size_t)~0) ) :
186
m_is_remove( is_remove ),
187
m_vertex_index( vertex_index ),
188
m_split_edge( split_edge )
191
/// Tag for identifying a vertex removal
193
static const bool VERTEX_REMOVE = true;
195
/// Tag for identifying a vertex addition
197
static const bool VERTEX_ADD = false;
199
/// Wether this event is a vertex removal
203
/// The index of the vertex being added or removed
205
size_t m_vertex_index;
207
/// If this is a vertex addition due to edge splitting, the edge that was split
214
// ---------------------------------------------------------
216
/// Keeps track of a triangle removal or addition. If addition, contains the three vertices that form the new triangle.
218
// ---------------------------------------------------------
220
struct TriangleUpdateEvent
224
TriangleUpdateEvent(bool is_remove = false,
225
size_t triangle_index = (size_t)~0,
226
const Vec3st& triangle = Vec3st((size_t)~0) ) :
227
m_is_remove( is_remove ),
228
m_triangle_index( triangle_index ),
232
/// Tag for identifying a triangle removal
234
static const bool TRIANGLE_REMOVE = true;
236
/// Tag for identifying a triangle addition
238
static const bool TRIANGLE_ADD = false;
240
/// Wether this event is a triangle removal
244
/// The index of the triangle being added or removed
246
size_t m_triangle_index;
248
/// If this is a triangle addition, the triangle added
255
// ---------------------------------------------------------
257
/// A DynamicSurface with topological and mesh maintenance operations.
259
// ---------------------------------------------------------
261
class SurfTrack : public DynamicSurface
266
/// Create a SurfTrack object from a set of vertices and triangles using the specified paramaters
268
SurfTrack(const std::vector<Vec3d>& vs,
269
const std::vector<Vec3st>& ts,
270
const std::vector<double>& masses,
271
const SurfTrackInitializationParameters& initial_parameters );
279
/// Disallow copying and assignment by declaring private
281
SurfTrack( const SurfTrack& );
283
/// Disallow copying and assignment by declaring private
285
SurfTrack& operator=( const SurfTrack& );
294
/// Add a triangle to the surface. Update the underlying TriMesh and acceleration grid.
296
size_t add_triangle(const Vec3st& t);
298
/// Remove a triangle from the surface. Update the underlying TriMesh and acceleration grid.
300
void remove_triangle(size_t t);
302
/// Add a vertex to the surface. Update the acceleration grid.
304
size_t add_vertex( const Vec3d& new_vertex_position, double new_vertex_mass );
306
/// Remove a vertex from the surface. Update the acceleration grid.
308
void remove_vertex(size_t v);
310
/// Remove deleted vertices and triangles from the mesh data structures
318
/// Run mesh maintenance operations
320
void improve_mesh( );
322
/// Run edge-edge merging
324
void topology_changes( );
330
/// Check for and delete flaps and zero-area triangles among the given triangle indices, then separate singular vertices.
332
void trim_non_manifold( std::vector<size_t>& triangle_indices );
334
/// Check for and delete flaps and zero-area triangles among *all* triangles, then separate singular vertices.
336
inline void trim_non_manifold();
338
/// Fire an assert if any degenerate triangles or tets (flaps) are found.
340
void assert_no_degenerate_triangles();
346
/// Edge collapse operation object
348
EdgeCollapser m_collapser;
350
/// Edge split operation object
352
EdgeSplitter m_splitter;
354
/// Edge flip operation object
356
EdgeFlipper m_flipper;
358
/// NULL-space surface smoothing
360
MeshSmoother m_smoother;
362
/// Surface merging object
366
/// Surface splitting operation object
368
MeshPincher m_pincher;
370
/// Collision epsilon to use during mesh improvment operations
372
double m_improve_collision_epsilon;
374
/// Minimum edge length improvement in order to flip an edge
376
double m_edge_flip_min_length_change;
378
/// Maximum volume change allowed when flipping or collapsing an edge
380
double m_max_volume_change;
382
/// Mimimum edge length. Edges shorter than this will be collapsed.
384
double m_min_edge_length;
386
/// Maximum edge length. Edges longer than this will be subdivided.
388
double m_max_edge_length;
390
/// Elements within this distance will trigger a merge attempt
392
double m_merge_proximity_epsilon;
394
/// Try to prevent triangles with area less than this
396
double m_min_triangle_area;
398
/// Don't create triangles with angles less than this. If angles less than this do exist, try to remove them.
400
double m_min_triangle_angle;
402
/// Don't create triangles with angles greater than this. If angles greater than this do exist, try to remove them.
404
double m_max_triangle_angle;
406
/// Interpolation scheme, determines edge midpoint location
408
SubdivisionScheme *m_subdivision_scheme;
410
/// If we allocate our own SubdivisionScheme object, we must delete it in this object's deconstructor.
412
bool should_delete_subdivision_scheme_object;
414
/// Triangles which are involved in connectivity changes which may introduce degeneracies
416
std::vector<size_t> m_dirty_triangles;
418
/// Whether to allow merging and separation
420
bool m_allow_topology_changes;
422
/// Whether to allow non-manifold (edges incident on more than two triangles)
424
bool m_allow_non_manifold;
426
/// Whether to perform adaptivity operations
428
bool m_perform_improvement;
430
/// When doing mesh optimization, whether to allow the vertices to move. If set to false, we allow edge flipping, edge
431
/// splitting, and edge collapsing (where the edge is collapsed down to one of its endpoints). If true, we do mesh smoothing,
432
/// as well as allowing a collapsed edge to collapse down to some point other than an endpoint.
434
bool m_allow_vertex_movement;
436
/// History of vertex removal or addition events
438
std::vector<VertexUpdateEvent> m_vertex_change_history;
440
/// History of triangle removal or addition events
442
std::vector<TriangleUpdateEvent> m_triangle_change_history;
444
/// Map of triangle indices, mapping pre-defrag triangle indices to post-defrag indices
446
std::vector<Vec2st> m_defragged_triangle_map;
448
/// Map of vertex indices, mapping pre-defrag vertex indices to post-defrag indices
450
std::vector<Vec2st> m_defragged_vertex_map;
454
// ---------------------------------------------------------
456
// ---------------------------------------------------------
458
// ---------------------------------------------------------
460
/// Search the entire mesh for non-manifold elements and remove them
461
/// NOTE: SHOULD USE THE VERSION THAT ACCEPTS A SET OF TRIANGLE INDICES INSTEAD.
463
// ---------------------------------------------------------
465
inline void SurfTrack::trim_non_manifold()
468
std::vector<size_t> triangle_indices;
469
triangle_indices.resize( m_mesh.num_triangles() );
470
for ( size_t i = 0; i < triangle_indices.size(); ++i )
472
triangle_indices[i] = i;
475
trim_non_manifold( triangle_indices );