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

This example shows how to detect the intersecting faces using collision detection.

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:47
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

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
41// \cond
42
43TutorialCollisionDetection::TutorialCollisionDetection(const std::string &title)
44 : Viewer(title)
45 , model0_color_(0.8f, 1.0f, 0.8f)
46 , model1_color_(0.8f, 0.8f, 1.0f)
47{
48 auto m0 = add_model(resource::directory() + "/data/bunny.ply");
49 auto m1 = add_model(resource::directory() + "/data/mannequin.ply");
50 auto mesh0 = dynamic_cast<SurfaceMesh*>(m0);
51 auto mesh1 = dynamic_cast<SurfaceMesh*>(m1);
52 if (mesh0 && mesh1) {
53 // use the manipulator to transform the first model (visualization only and geometry is not changed)
54 mesh0->set_manipulator(std::make_shared<Manipulator>(mesh0));
55
56 // the first mesh is colored by a "face_color" property
57 mesh0->add_face_property<vec3>("face_color", model0_color_);
58 mesh0->renderer()->get_triangles_drawable("faces")->set_coloring(easy3d::State::COLOR_PROPERTY, easy3d::State::FACE, "face_color");
59
60 // the second mesh is also colored by a "face_color" property
61 mesh1->add_face_property<vec3>("face_color", model1_color_);
62 mesh1->renderer()->get_triangles_drawable("faces")->set_coloring(easy3d::State::COLOR_PROPERTY, easy3d::State::FACE, "face_color");
63
64 collider_ = new Collider(mesh0, mesh1);
65 // detect and show the result when the viewer is visible
66 detect();
67
68 timer_.set_interval(50, [this]()->void {
69 static std::mutex mutex; // ensures the previous changes are completed
70 std::lock_guard<std::mutex> guard(mutex);
71 static float angle = 0.0f;
72 angle += 0.0001f;
73 auto T = mat4::rotation(vec3(0, 0, 1), angle) * models_[0]->manipulator()->frame()->matrix();
74 models_[0]->manipulator()->frame()->setFromMatrix(T);
75 detect();
76 });
77 }
78 else
79 LOG(WARNING) << "not all the two meshes have been loaded";
80
81 manual_ =
82 "--------------------- Collision Viewer usage ----------------------\n"
83 "On start, you will see an animation with highlighted intersecting \n"
84 "faces. Press 'space' to pause/resume the animation. \n"
85 "When the animation is paused, you can manipulate the bunny model \n"
86 "(using your mouse) to perform real-time collection detection: \n"
87 " - Alt + left button: rotate bunny model \n"
88 " - Alt + right button: translate bunny model \n"
89 "------------------------------------------------------------------ \n";
90
91 hint_ = "Press 'space' to pause/resume animation\n"
92 "When paused:\n"
93 " - Alt + left button: rotate bunny model\n"
94 " - Alt + right button: translate bunny model";
95}
96
97
98TutorialCollisionDetection::~TutorialCollisionDetection() {
99 timer_.stop();
100 delete collider_;
101}
102
103
104bool TutorialCollisionDetection::mouse_drag_event(int x, int y, int dx, int dy, int button, int modifiers) {
105 if (collider_ && models().size() == 2 && modifiers == MODIF_ALT && timer_.is_paused()) {
106 auto manipulator = models_[0]->manipulator();
107 if (button == BUTTON_LEFT)
108 manipulator->frame()->action_rotate(x, y, dx, dy, camera(), ManipulatedFrame::NONE);
109 else if (button == BUTTON_RIGHT)
110 manipulator->frame()->action_translate(x, y, dx, dy, camera(), ManipulatedFrame::NONE);
111 else
112 return false;
113
114 detect();
115 return true;
116 }
117 else
118 return Viewer::mouse_drag_event(x, y, dx, dy, button, modifiers);
119}
120
121
122bool TutorialCollisionDetection::key_press_event(int key, int modifiers) {
123 if (key == KEY_SPACE) {
124 if (timer_.is_paused())
125 timer_.resume();
126 else
127 timer_.pause();
128 return true;
129 }
130 else
131 return Viewer::key_press_event(key, modifiers);
132}
133
134
135void TutorialCollisionDetection::detect() {
136 const auto pairs = collider_->detect(models_[0]->manipulator()->matrix(), mat4::identity());
137 //std::cout << pairs.size() << " pairs of intersecting faces" << std::endl;
138
139 // mark the intersecting faces red
140 // Note: The following code is for visualizing the intersecting faces and is not optimized.
141 // Ideas for better performance:
142 // (1) update only the color buffer;
143 // (2) use a shader storage buffer to transfer the *status* of the faces to the fragment shader.
144 auto mesh0 = dynamic_cast<SurfaceMesh *>(models_[0].get());
145 auto mesh1 = dynamic_cast<SurfaceMesh *>(models_[1].get());
146 auto mesh0_colors = mesh0->get_face_property<vec3>("face_color");
147 auto mesh1_colors = mesh1->get_face_property<vec3>("face_color");
148 mesh0_colors.vector().assign(mesh0->n_faces(), model0_color_);
149 mesh1_colors.vector().assign(mesh1->n_faces(), model1_color_);
150 for (const auto &pair : pairs) {
151 mesh0_colors[pair.first] = vec3(1.0f, 0.0f, 0.0f);
152 mesh1_colors[pair.second] = vec3(1.0f, 0.0f, 0.0f);
153 }
154 models_[0]->renderer()->update();
155 models_[1]->renderer()->update();
156
157 update();
158}
159
160// \endcond
@ NONE
No constraint.
Definition manipulated_frame.h:165
static Mat4< float > rotation(const Vec< 3, float > &axis, float angle)
static Mat< N, M, T > identity()
Returns an identity matrix.
Definition mat.h:697
@ COLOR_PROPERTY
Using a color property.
Definition state.h:59
@ FACE
Property defined on faces.
Definition state.h:70
A halfedge data structure for polygonal meshes of 2-manifold.
Definition surface_mesh.h:51
FaceProperty< T > get_face_property(const std::string &name) const
Get the face property with name name of type T.
Definition surface_mesh.h:1811
std::string directory()
Returns the resource directory (containing color maps, shaders, textures, fonts, etc....
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
40
41using namespace easy3d;
42
43
44int main(int argc, char **argv) {
45 // initialize Easy3D.
46 initialize();
47
48 TutorialCollisionDetection viewer(EXAMPLE_TITLE);
49
50 // run the viewer
51 return viewer.run();
52}
53
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