This example shows how to detect the intersecting faces using collision detection.
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#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
34
36 class Model;
37 class Collider;
38}
39
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:
53
56
58};
59
60
61#endif
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
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 "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
40
41
42
43TutorialCollisionDetection::TutorialCollisionDetection(const std::string &title)
45 , model0_color_(0.8f, 1.0f, 0.8f)
46 , model1_color_(0.8f, 0.8f, 1.0f)
47{
52 if (mesh0 && mesh1) {
53
54 mesh0->set_manipulator(std::make_shared<Manipulator>(mesh0));
55
56
57 mesh0->add_face_property<
vec3>(
"face_color", model0_color_);
59
60
61 mesh1->add_face_property<
vec3>(
"face_color", model1_color_);
63
64 collider_ =
new Collider(mesh0, mesh1);
65
66 detect();
67
68 timer_.set_interval(50, [this]()->void {
69 static std::mutex mutex;
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)
109 else if (button == BUTTON_RIGHT)
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
138
139
140
141
142
143
144 auto mesh0 =
dynamic_cast<SurfaceMesh *
>(models_[0].get());
145 auto mesh1 =
dynamic_cast<SurfaceMesh *
>(models_[1].get());
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
@ 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....