Easy3D 2.5.3
Tutorial_406_CollisionDetection

The source file containing the main() function:

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 "viewer.h"
28#include <easy3d/util/initializer.h>
29
30
31using namespace easy3d;
32
33// This example shows how to detect the intersecting faces using collision detection.
34int main(int argc, char **argv) {
35 // initialize Easy3D.
36 initialize();
37
38 TutorialCollisionDetection viewer(EXAMPLE_TITLE);
39
40 // run the viewer
41 return viewer.run();
42}
43
Definition: collider.cpp:182
void initialize(bool use_log_file, bool use_setting_file, const std::string &resource_dir)
Initialization of Easy3D.
Definition: initializer.cpp:35

The header file of the viewer class:

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#ifndef EASY3D_TUTORIAL_COLLISION_DETECTION_H
28#define EASY3D_TUTORIAL_COLLISION_DETECTION_H
29
30#include <easy3d/viewer/viewer.h>
31#include <easy3d/util/timer.h>
32
33// This class demonstrates how to detect intersecting faces of two meshes.
34
35namespace easy3d {
36 class Model;
37 class Collider;
38}
39
40class TutorialCollisionDetection : public easy3d::Viewer {
41public:
42 explicit TutorialCollisionDetection(const std::string &title);
43 ~TutorialCollisionDetection() override;
44
45private:
46 bool mouse_drag_event(int x, int y, int dx, int dy, int button, int modifiers) override;
47 bool key_press_event(int key, int modifiers) override;
48
49 void detect();
50
51private:
52 easy3d::Collider* collider_;
53
54 easy3d::vec3 model0_color_;
55 easy3d::vec3 model1_color_;
56
57 easy3d::Timer<> timer_;
58};
59
60
61#endif // EASY3D_TUTORIAL_COLLISION_DETECTION_H
Efficient collision detection.
Definition: collider.h:51
A light-weight implementation of the timer mechanism.
Definition: timer.h:49
The built-in Easy3D viewer.
Definition: viewer.h:61

The source file of the viewer class:

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 "viewer.h"
28
29#include <mutex>
30
31#include <easy3d/renderer/drawable_triangles.h>
32#include <easy3d/renderer/manipulator.h>
33#include <easy3d/renderer/manipulated_frame.h>
34#include <easy3d/renderer/renderer.h>
35#include <easy3d/util/resource.h>
36#include <easy3d/algo/collider.h>
37
38
39using namespace easy3d;
40
41TutorialCollisionDetection::TutorialCollisionDetection(const std::string &title)
42 : Viewer(title)
43 , model0_color_(0.8f, 1.0f, 0.8f)
44 , model1_color_(0.8f, 0.8f, 1.0f)
45{
46 auto m0 = add_model(resource::directory() + "/data/bunny.ply");
47 auto m1 = add_model(resource::directory() + "/data/mannequin.ply");
48 auto mesh0 = dynamic_cast<SurfaceMesh*>(m0);
49 auto mesh1 = dynamic_cast<SurfaceMesh*>(m1);
50 if (mesh0 && mesh1) {
51 // use the manipulator to transform the first model (visualization only and geometry is not changed)
52 mesh0->set_manipulator(new Manipulator(mesh0));
53
54 // the first mesh is colored by a "face_color" property
55 mesh0->add_face_property<vec3>("face_color", model0_color_);
56 mesh0->renderer()->get_triangles_drawable("faces")->set_coloring(easy3d::State::COLOR_PROPERTY, easy3d::State::FACE, "face_color");
57
58 // the second mesh is also colored by a "face_color" property
59 mesh1->add_face_property<vec3>("face_color", model1_color_);
60 mesh1->renderer()->get_triangles_drawable("faces")->set_coloring(easy3d::State::COLOR_PROPERTY, easy3d::State::FACE, "face_color");
61
62 collider_ = new Collider(mesh0, mesh1);
63 // detect and show the result when the viewer is visible
64 detect();
65
66 timer_.set_interval(50, [this]()->void {
67 static std::mutex mutex; // ensures the previous changes are completed
68 std::lock_guard<std::mutex> guard(mutex);
69 static float angle = 0.0f;
70 angle += 0.0001f;
71 auto T = mat4::rotation(vec3(0, 0, 1), angle) * models_[0]->manipulator()->frame()->matrix();
72 models_[0]->manipulator()->frame()->setFromMatrix(T);
73 detect();
74 });
75 }
76 else
77 LOG(WARNING) << "not all the two meshes have been loaded";
78
79 usage_string_ =
80 "--------------------- Collision Viewer usage ----------------------\n"
81 "On start, you will see an animation with highlighted intersecting \n"
82 "faces. Press 'space' to pause/resume the animation. \n"
83 "When the animation is paused, you can manipulate the bunny model \n"
84 "(using your mouse) to perform real-time collection detection: \n"
85 " - ALT + left button: rotate bunny model \n"
86 " - ALT + right button: translate bunny model \n"
87 "------------------------------------------------------------------ \n";
88}
89
90
91TutorialCollisionDetection::~TutorialCollisionDetection() {
92 timer_.stop();
93 delete collider_;
94}
95
96
97bool TutorialCollisionDetection::mouse_drag_event(int x, int y, int dx, int dy, int button, int modifiers) {
98 if (collider_ && models().size() == 2 && modifiers == MODIF_ALT && timer_.is_paused()) {
99 auto manipulator = models_[0]->manipulator();
100 if (button == BUTTON_LEFT)
101 manipulator->frame()->action_rotate(x, y, dx, dy, camera_, ManipulatedFrame::NONE);
102 else if (button == BUTTON_RIGHT)
103 manipulator->frame()->action_translate(x, y, dx, dy, camera_, ManipulatedFrame::NONE);
104 else
105 return false;
106
107 detect();
108 return true;
109 }
110 else
111 return Viewer::mouse_drag_event(x, y, dx, dy, button, modifiers);
112}
113
114
115bool TutorialCollisionDetection::key_press_event(int key, int modifiers) {
116 if (key == KEY_SPACE) {
117 if (timer_.is_paused())
118 timer_.resume();
119 else
120 timer_.pause();
121 return true;
122 }
123 else
124 return Viewer::key_press_event(key, modifiers);
125}
126
127
128void TutorialCollisionDetection::detect() {
129 const auto pairs = collider_->detect(models_[0]->manipulator()->matrix(), mat4::identity());
130 //std::cout << pairs.size() << " pairs of intersecting faces" << std::endl;
131
132 // mark the intersecting faces red
133 // Note: The following code is for visualizing the intersecting faces and is not optimized.
134 // Ideas for better performance:
135 // (1) update only the color buffer;
136 // (2) use a shader storage buffer to transfer the *status* of the faces to the fragment shader.
137 auto mesh0_colors = dynamic_cast<SurfaceMesh *>(models_[0])->get_face_property<vec3>("face_color");
138 auto mesh1_colors = dynamic_cast<SurfaceMesh *>(models_[1])->get_face_property<vec3>("face_color");
139 mesh0_colors.vector().assign(dynamic_cast<SurfaceMesh *>(models_[0])->n_faces(), model0_color_);
140 mesh1_colors.vector().assign(dynamic_cast<SurfaceMesh *>(models_[1])->n_faces(), model1_color_);
141 for (const auto &pair : pairs) {
142 mesh0_colors[pair.first] = vec3(1.0f, 0.0f, 0.0f);
143 mesh1_colors[pair.second] = vec3(1.0f, 0.0f, 0.0f);
144 }
145 models_[0]->renderer()->update();
146 models_[1]->renderer()->update();
147
148 update();
149}
A manipulator is for manipulation of an object.
Definition: manipulator.h:62
void set_manipulator(Manipulator *manip)
Attaches a manipulator to this model.
Definition: model.h:102
A halfedge data structure for polygonal meshes of 2-manifold.
Definition: surface_mesh.h:52
unsigned int n_faces() const
returns number of faces in the mesh
Definition: surface_mesh.h:1076
SurfaceMesh & assign(const SurfaceMesh &rhs)
assign rhs to *this. does not copy custom properties.
Definition: surface_mesh.cpp:149
virtual Model * add_model(const std::string &file_name, bool create_default_drawables=true)
Add a model from a file to the viewer to be visualized. On success, the viewer will be in charge of t...
Definition: viewer.cpp:1204
double angle(const Vec &a, const Vec &b)
Computes angle between two (un-normalized) vectors.
Definition: types.h:261