This example shows how to triangulate a general polygonal meshes (e.g., meshes with concave faces, selfâintersecting faces, and faces with holes) using the tessellator of Easy3D.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include <easy3d/viewer/viewer.h>
28#include <easy3d/renderer/camera.h>
29#include <easy3d/core/surface_mesh.h>
30#include <easy3d/renderer/drawable_points.h>
31#include <easy3d/renderer/drawable_lines.h>
32#include <easy3d/renderer/renderer.h>
33#include <easy3d/algo/tessellator.h>
34#include <easy3d/util/initializer.h>
35
45
47
48
49typedef std::vector<vec3> Hole;
50
51
53 if (!mesh)
54 return;
55
56 mesh->update_face_normals();
57 auto normals = mesh->face_property<
vec3>(
"f:normal");
58 auto holes = mesh->get_face_property<Hole>("f:holes");
59
61 for (auto f : mesh->faces()) {
62 tessellator.begin_polygon(normals[f]);
63
64 tessellator.set_winding_rule(Tessellator::WINDING_NONZERO);
65 tessellator.begin_contour();
66 for (auto h : mesh->halfedges(f)) {
68 tessellator.add_vertex(mesh->position(v), v.
idx());
69 }
70 tessellator.end_contour();
71
72 if (holes && holes[f].size() >= 3) {
73 tessellator.set_winding_rule(Tessellator::WINDING_ODD);
74 tessellator.begin_contour();
75 for (const auto& p : holes[f])
76 tessellator.add_vertex(p);
77 tessellator.end_contour();
78 }
79
80 tessellator.end_polygon();
81 }
82
83
84
85
86 mesh->clear();
87
88 const auto& triangles = tessellator.elements();
89 if (triangles.empty())
90 return;
91
92 const auto &vts = tessellator.vertices();
93 for (auto v: vts)
94 mesh->add_vertex(
vec3(v->data()));
95
96 for (const auto &t: triangles) {
97 mesh->add_triangle(
101 );
102 }
103}
104
105
106int main(int argc, char **argv) {
107
109
110
111
112 Viewer viewer(EXAMPLE_TITLE);
113 viewer.camera()->setUpVector(
vec3(0, 1, 0));
114 viewer.camera()->setViewDirection(
vec3(0, 0, -1));
115
116
117
119
120 {
121 auto v0 = mesh->add_vertex(
vec3(0, 0, 0));
122 auto v1 = mesh->add_vertex(
vec3(800, 0, 0));
123 auto v2 = mesh->add_vertex(
vec3(800, 800, 0));
124 auto v3 = mesh->add_vertex(
vec3(600, 300, 0));
125 mesh->add_quad(v0, v1, v2, v3);
126 }
127
128 {
129 auto vertices = {
130 mesh->add_vertex(
vec3(1500, 0, 0)),
131 mesh->add_vertex(
vec3(1300, 800, 0)),
132 mesh->add_vertex(
vec3(1100, 0, 0)),
133 mesh->add_vertex(
vec3(1700, 500, 0)),
134 mesh->add_vertex(
vec3(900, 500, 0))
135 };
136 mesh->add_face(vertices);
137 }
138
139 {
140 auto vertices = {
141 mesh->add_vertex(
vec3(1800, 0, 0)),
142 mesh->add_vertex(
vec3(2200, 0, 0)),
143 mesh->add_vertex(
vec3(2200, 700, 0)),
144 mesh->add_vertex(
vec3(1800, 700, 0))
145 };
146 auto f = mesh->add_face(vertices);
147
148
149 auto holes = mesh->add_face_property<Hole>("f:holes");
150 holes[f] = {
155 };
156 }
157
158
159
160 triangulate(mesh);
161
162
163
164
165 viewer.add_model(std::shared_ptr<SurfaceMesh>(mesh), true);
166
167
168 mesh->renderer()->get_points_drawable("vertices")->set_visible(true);
170 mesh->renderer()->get_points_drawable("vertices")->set_point_size(12);
171
172 mesh->renderer()->get_lines_drawable("edges")->set_visible(true);
173
174 mesh->renderer()->get_lines_drawable("borders")->set_visible(true);
175
176
177 return viewer.run();
178}
179
@ SPHERE
The points will be drawn as spheres.
Definition drawable_points.h:62
int idx() const
Get the underlying index of this handle.
Definition surface_mesh.h:72
A halfedge data structure for polygonal meshes of 2-manifold.
Definition surface_mesh.h:51
Tessellator subdivides concave planar polygons, polygons with holes, or polygons with intersecting ed...
Definition tessellator.h:55
The built-in Easy3D viewer.
Definition viewer.h:63
Definition collider.cpp:182
Vec< 3, float > vec3
A 3D point/vector of float type.
Definition types.h:44
void initialize(bool info_to_stdout, bool use_log_file, bool use_setting_file, const std::string &resource_dir)
Initialization of Easy3D.
Definition initializer.cpp:39
This type represents a vertex (internally it is basically an index).
Definition surface_mesh.h:135