Easy3D 2.6.1
Loading...
Searching...
No Matches
Tutorial_601_Tessellator/main.cpp

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.

Note: For general rendering purposes, you can use the tessellator to create a TrianglesDrawable for the model without explicitly triangulating the mesh.

1/********************************************************************
2 * Copyright (C) 2015 Liangliang Nan <liangliang.nan@gmail.com>
3 * https://3d.bk.tudelft.nl/liangliang/
4 *
5 * This file is part of Easy3D. If it is useful in your research/work,
6 * I would be grateful if you show your appreciation by citing it:
7 * ------------------------------------------------------------------
8 * Liangliang Nan.
9 * Easy3D: a lightweight, easy-to-use, and efficient C++ library
10 * for processing and rendering 3D data.
11 * Journal of Open Source Software, 6(64), 3255, 2021.
12 * ------------------------------------------------------------------
13 *
14 * Easy3D is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License Version 3
16 * as published by the Free Software Foundation.
17 *
18 * Easy3D is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
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
46using namespace easy3d;
47
48
49typedef std::vector<vec3> Hole;
50
51// convert the mesh into a triangular mesh using the tessellator
52void triangulate(SurfaceMesh *mesh) {
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
60 Tessellator tessellator;
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)) {
67 SurfaceMesh::Vertex v = mesh->target(h);
68 tessellator.add_vertex(mesh->position(v), v.idx());
69 }
70 tessellator.end_contour();
71
72 if (holes && holes[f].size() >= 3) { // has a valid hole
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 // now the tessellation is done. We can clear the old mesh and
84 // fill it will the new set of triangles
85
86 mesh->clear();
87
88 const auto& triangles = tessellator.elements();
89 if (triangles.empty())
90 return; // in degenerate cases num can be zero
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(
98 SurfaceMesh::Vertex(static_cast<int>(t[0])),
99 SurfaceMesh::Vertex(static_cast<int>(t[1])),
100 SurfaceMesh::Vertex(static_cast<int>(t[2]))
101 );
102 }
103}
104
105
106int main(int argc, char **argv) {
107 // initialize Easy3D.
108 initialize();
109
110 // create the default Easy3D viewer.
111 // (a viewer must be created before creating any drawables).
112 Viewer viewer(EXAMPLE_TITLE);
113 viewer.camera()->setUpVector(vec3(0, 1, 0));
114 viewer.camera()->setViewDirection(vec3(0, 0, -1));
115
116 //-------- create a simple mesh with 3 complex faces ---------
117
118 auto mesh = new SurfaceMesh;
119
120 { // face 1: a concave quad
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 { // face 2: a self-intersecting face representing a star
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 { // face 3: a quad face with a hole
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 // let's create a hole (also a quad shape) in this face
149 auto holes = mesh->add_face_property<Hole>("f:holes");
150 holes[f] = {
151 vec3(1900, 100, 0),
152 vec3(2100, 100, 0),
153 vec3(2100, 600, 0),
154 vec3(1900, 600, 0)
155 };
156 }
157
158 //-------- triangulate the mesh using the tessellator ---------
159
160 triangulate(mesh);
161
162 // ------------------------------------------------------------
163
164 // add the model to the viewer
165 viewer.add_model(std::shared_ptr<SurfaceMesh>(mesh), true);
166
167 // show the vertices
168 mesh->renderer()->get_points_drawable("vertices")->set_visible(true);
169 mesh->renderer()->get_points_drawable("vertices")->set_impostor_type(easy3d::PointsDrawable::SPHERE);
170 mesh->renderer()->get_points_drawable("vertices")->set_point_size(12);
171 // show the edges
172 mesh->renderer()->get_lines_drawable("edges")->set_visible(true);
173 // also show the borders
174 mesh->renderer()->get_lines_drawable("borders")->set_visible(true);
175
176 // run the viewer
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