Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/modules/godot_physics_3d/godot_area_pair_3d.cpp
10277 views
1
/**************************************************************************/
2
/* godot_area_pair_3d.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#include "godot_area_pair_3d.h"
32
33
#include "godot_collision_solver_3d.h"
34
35
bool GodotAreaPair3D::setup(real_t p_step) {
36
bool result = false;
37
if (area->collides_with(body) && GodotCollisionSolver3D::solve_static(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), nullptr, this)) {
38
result = true;
39
}
40
41
process_collision = false;
42
has_space_override = false;
43
if (result != colliding) {
44
if ((int)area->get_param(PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE) != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
45
has_space_override = true;
46
} else if ((int)area->get_param(PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE) != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
47
has_space_override = true;
48
} else if ((int)area->get_param(PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE) != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
49
has_space_override = true;
50
}
51
process_collision = has_space_override;
52
53
if (area->has_monitor_callback()) {
54
process_collision = true;
55
}
56
57
colliding = result;
58
}
59
60
return process_collision;
61
}
62
63
bool GodotAreaPair3D::pre_solve(real_t p_step) {
64
if (!process_collision) {
65
return false;
66
}
67
68
if (colliding) {
69
if (has_space_override) {
70
body_has_attached_area = true;
71
body->add_area(area);
72
}
73
74
if (area->has_monitor_callback()) {
75
area->add_body_to_query(body, body_shape, area_shape);
76
}
77
} else {
78
if (has_space_override) {
79
body_has_attached_area = false;
80
body->remove_area(area);
81
}
82
83
if (area->has_monitor_callback()) {
84
area->remove_body_from_query(body, body_shape, area_shape);
85
}
86
}
87
88
return false; // Never do any post solving.
89
}
90
91
void GodotAreaPair3D::solve(real_t p_step) {
92
// Nothing to do.
93
}
94
95
GodotAreaPair3D::GodotAreaPair3D(GodotBody3D *p_body, int p_body_shape, GodotArea3D *p_area, int p_area_shape) {
96
body = p_body;
97
area = p_area;
98
body_shape = p_body_shape;
99
area_shape = p_area_shape;
100
body->add_constraint(this, 0);
101
area->add_constraint(this);
102
if (p_body->get_mode() == PhysicsServer3D::BODY_MODE_KINEMATIC) {
103
p_body->set_active(true);
104
}
105
}
106
107
GodotAreaPair3D::~GodotAreaPair3D() {
108
if (colliding) {
109
if (body_has_attached_area) {
110
body_has_attached_area = false;
111
body->remove_area(area);
112
}
113
if (area->has_monitor_callback()) {
114
area->remove_body_from_query(body, body_shape, area_shape);
115
}
116
}
117
body->remove_constraint(this);
118
area->remove_constraint(this);
119
}
120
121
////////////////////////////////////////////////////
122
123
bool GodotArea2Pair3D::setup(real_t p_step) {
124
bool result_a = area_a->collides_with(area_b);
125
bool result_b = area_b->collides_with(area_a);
126
if ((result_a || result_b) && !GodotCollisionSolver3D::solve_static(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), nullptr, this)) {
127
result_a = false;
128
result_b = false;
129
}
130
131
bool process_collision = false;
132
133
process_collision_a = false;
134
if (result_a != colliding_a) {
135
if (area_a->has_area_monitor_callback() && area_b_monitorable) {
136
process_collision_a = true;
137
process_collision = true;
138
}
139
colliding_a = result_a;
140
}
141
142
process_collision_b = false;
143
if (result_b != colliding_b) {
144
if (area_b->has_area_monitor_callback() && area_a_monitorable) {
145
process_collision_b = true;
146
process_collision = true;
147
}
148
colliding_b = result_b;
149
}
150
151
return process_collision;
152
}
153
154
bool GodotArea2Pair3D::pre_solve(real_t p_step) {
155
if (process_collision_a) {
156
if (colliding_a) {
157
area_a->add_area_to_query(area_b, shape_b, shape_a);
158
} else {
159
area_a->remove_area_from_query(area_b, shape_b, shape_a);
160
}
161
}
162
163
if (process_collision_b) {
164
if (colliding_b) {
165
area_b->add_area_to_query(area_a, shape_a, shape_b);
166
} else {
167
area_b->remove_area_from_query(area_a, shape_a, shape_b);
168
}
169
}
170
171
return false; // Never do any post solving.
172
}
173
174
void GodotArea2Pair3D::solve(real_t p_step) {
175
// Nothing to do.
176
}
177
178
GodotArea2Pair3D::GodotArea2Pair3D(GodotArea3D *p_area_a, int p_shape_a, GodotArea3D *p_area_b, int p_shape_b) {
179
area_a = p_area_a;
180
area_b = p_area_b;
181
shape_a = p_shape_a;
182
shape_b = p_shape_b;
183
area_a_monitorable = area_a->is_monitorable();
184
area_b_monitorable = area_b->is_monitorable();
185
area_a->add_constraint(this);
186
area_b->add_constraint(this);
187
}
188
189
GodotArea2Pair3D::~GodotArea2Pair3D() {
190
if (colliding_a) {
191
if (area_a->has_area_monitor_callback() && area_b_monitorable) {
192
area_a->remove_area_from_query(area_b, shape_b, shape_a);
193
}
194
}
195
196
if (colliding_b) {
197
if (area_b->has_area_monitor_callback() && area_a_monitorable) {
198
area_b->remove_area_from_query(area_a, shape_a, shape_b);
199
}
200
}
201
202
area_a->remove_constraint(this);
203
area_b->remove_constraint(this);
204
}
205
206
////////////////////////////////////////////////////
207
208
bool GodotAreaSoftBodyPair3D::setup(real_t p_step) {
209
bool result = false;
210
if (
211
area->collides_with(soft_body) &&
212
GodotCollisionSolver3D::solve_static(
213
soft_body->get_shape(soft_body_shape),
214
soft_body->get_transform() * soft_body->get_shape_transform(soft_body_shape),
215
area->get_shape(area_shape),
216
area->get_transform() * area->get_shape_transform(area_shape),
217
nullptr,
218
this)) {
219
result = true;
220
}
221
222
process_collision = false;
223
has_space_override = false;
224
if (result != colliding) {
225
if ((int)area->get_param(PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE) != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
226
has_space_override = true;
227
} else if (area->get_wind_force_magnitude() > CMP_EPSILON) {
228
has_space_override = true;
229
}
230
231
if (area->has_monitor_callback()) {
232
process_collision = true;
233
}
234
235
colliding = result;
236
}
237
238
return process_collision;
239
}
240
241
bool GodotAreaSoftBodyPair3D::pre_solve(real_t p_step) {
242
if (!process_collision) {
243
return false;
244
}
245
246
if (colliding) {
247
if (has_space_override) {
248
body_has_attached_area = true;
249
soft_body->add_area(area);
250
}
251
252
if (area->has_monitor_callback()) {
253
area->add_soft_body_to_query(soft_body, soft_body_shape, area_shape);
254
}
255
} else {
256
if (has_space_override) {
257
body_has_attached_area = false;
258
soft_body->remove_area(area);
259
}
260
261
if (area->has_monitor_callback()) {
262
area->remove_soft_body_from_query(soft_body, soft_body_shape, area_shape);
263
}
264
}
265
266
return false; // Never do any post solving.
267
}
268
269
void GodotAreaSoftBodyPair3D::solve(real_t p_step) {
270
// Nothing to do.
271
}
272
273
GodotAreaSoftBodyPair3D::GodotAreaSoftBodyPair3D(GodotSoftBody3D *p_soft_body, int p_soft_body_shape, GodotArea3D *p_area, int p_area_shape) {
274
soft_body = p_soft_body;
275
area = p_area;
276
soft_body_shape = p_soft_body_shape;
277
area_shape = p_area_shape;
278
soft_body->add_constraint(this);
279
area->add_constraint(this);
280
}
281
282
GodotAreaSoftBodyPair3D::~GodotAreaSoftBodyPair3D() {
283
if (colliding) {
284
if (body_has_attached_area) {
285
body_has_attached_area = false;
286
soft_body->remove_area(area);
287
}
288
if (area->has_monitor_callback()) {
289
area->remove_soft_body_from_query(soft_body, soft_body_shape, area_shape);
290
}
291
}
292
soft_body->remove_constraint(this);
293
area->remove_constraint(this);
294
}
295
296