Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/modules/godot_physics_3d/godot_collision_object_3d.cpp
10277 views
1
/**************************************************************************/
2
/* godot_collision_object_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_collision_object_3d.h"
32
33
#include "godot_physics_server_3d.h"
34
#include "godot_space_3d.h"
35
36
void GodotCollisionObject3D::add_shape(GodotShape3D *p_shape, const Transform3D &p_transform, bool p_disabled) {
37
Shape s;
38
s.shape = p_shape;
39
s.xform = p_transform;
40
s.xform_inv = s.xform.affine_inverse();
41
s.bpid = 0; //needs update
42
s.disabled = p_disabled;
43
shapes.push_back(s);
44
p_shape->add_owner(this);
45
46
if (!pending_shape_update_list.in_list()) {
47
GodotPhysicsServer3D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list);
48
}
49
}
50
51
void GodotCollisionObject3D::set_shape(int p_index, GodotShape3D *p_shape) {
52
ERR_FAIL_INDEX(p_index, shapes.size());
53
shapes[p_index].shape->remove_owner(this);
54
shapes.write[p_index].shape = p_shape;
55
56
p_shape->add_owner(this);
57
if (!pending_shape_update_list.in_list()) {
58
GodotPhysicsServer3D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list);
59
}
60
}
61
62
void GodotCollisionObject3D::set_shape_transform(int p_index, const Transform3D &p_transform) {
63
ERR_FAIL_INDEX(p_index, shapes.size());
64
65
shapes.write[p_index].xform = p_transform;
66
shapes.write[p_index].xform_inv = p_transform.affine_inverse();
67
if (!pending_shape_update_list.in_list()) {
68
GodotPhysicsServer3D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list);
69
}
70
}
71
72
void GodotCollisionObject3D::set_shape_disabled(int p_idx, bool p_disabled) {
73
ERR_FAIL_INDEX(p_idx, shapes.size());
74
75
GodotCollisionObject3D::Shape &shape = shapes.write[p_idx];
76
if (shape.disabled == p_disabled) {
77
return;
78
}
79
80
shape.disabled = p_disabled;
81
82
if (!space) {
83
return;
84
}
85
86
if (p_disabled && shape.bpid != 0) {
87
space->get_broadphase()->remove(shape.bpid);
88
shape.bpid = 0;
89
if (!pending_shape_update_list.in_list()) {
90
GodotPhysicsServer3D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list);
91
}
92
} else if (!p_disabled && shape.bpid == 0) {
93
if (!pending_shape_update_list.in_list()) {
94
GodotPhysicsServer3D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list);
95
}
96
}
97
}
98
99
void GodotCollisionObject3D::remove_shape(GodotShape3D *p_shape) {
100
//remove a shape, all the times it appears
101
for (int i = 0; i < shapes.size(); i++) {
102
if (shapes[i].shape == p_shape) {
103
remove_shape(i);
104
i--;
105
}
106
}
107
}
108
109
void GodotCollisionObject3D::remove_shape(int p_index) {
110
//remove anything from shape to be erased to end, so subindices don't change
111
ERR_FAIL_INDEX(p_index, shapes.size());
112
for (int i = p_index; i < shapes.size(); i++) {
113
if (shapes[i].bpid == 0) {
114
continue;
115
}
116
//should never get here with a null owner
117
space->get_broadphase()->remove(shapes[i].bpid);
118
shapes.write[i].bpid = 0;
119
}
120
shapes[p_index].shape->remove_owner(this);
121
shapes.remove_at(p_index);
122
123
if (!pending_shape_update_list.in_list()) {
124
GodotPhysicsServer3D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list);
125
}
126
}
127
128
void GodotCollisionObject3D::_set_static(bool p_static) {
129
if (_static == p_static) {
130
return;
131
}
132
_static = p_static;
133
134
if (!space) {
135
return;
136
}
137
for (int i = 0; i < get_shape_count(); i++) {
138
const Shape &s = shapes[i];
139
if (s.bpid > 0) {
140
space->get_broadphase()->set_static(s.bpid, _static);
141
}
142
}
143
}
144
145
void GodotCollisionObject3D::_unregister_shapes() {
146
for (int i = 0; i < shapes.size(); i++) {
147
Shape &s = shapes.write[i];
148
if (s.bpid > 0) {
149
space->get_broadphase()->remove(s.bpid);
150
s.bpid = 0;
151
}
152
}
153
}
154
155
void GodotCollisionObject3D::_update_shapes() {
156
if (!space) {
157
return;
158
}
159
160
for (int i = 0; i < shapes.size(); i++) {
161
Shape &s = shapes.write[i];
162
if (s.disabled) {
163
continue;
164
}
165
166
//not quite correct, should compute the next matrix..
167
AABB shape_aabb = s.shape->get_aabb();
168
Transform3D xform = transform * s.xform;
169
shape_aabb = xform.xform(shape_aabb);
170
shape_aabb.grow_by((s.aabb_cache.size.x + s.aabb_cache.size.y) * 0.5 * 0.05);
171
s.aabb_cache = shape_aabb;
172
173
Vector3 scale = xform.get_basis().get_scale();
174
s.area_cache = s.shape->get_volume() * scale.x * scale.y * scale.z;
175
176
if (s.bpid == 0) {
177
s.bpid = space->get_broadphase()->create(this, i, shape_aabb, _static);
178
space->get_broadphase()->set_static(s.bpid, _static);
179
}
180
181
space->get_broadphase()->move(s.bpid, shape_aabb);
182
}
183
}
184
185
void GodotCollisionObject3D::_update_shapes_with_motion(const Vector3 &p_motion) {
186
if (!space) {
187
return;
188
}
189
190
for (int i = 0; i < shapes.size(); i++) {
191
Shape &s = shapes.write[i];
192
if (s.disabled) {
193
continue;
194
}
195
196
//not quite correct, should compute the next matrix..
197
AABB shape_aabb = s.shape->get_aabb();
198
Transform3D xform = transform * s.xform;
199
shape_aabb = xform.xform(shape_aabb);
200
shape_aabb.merge_with(AABB(shape_aabb.position + p_motion, shape_aabb.size)); //use motion
201
s.aabb_cache = shape_aabb;
202
203
if (s.bpid == 0) {
204
s.bpid = space->get_broadphase()->create(this, i, shape_aabb, _static);
205
space->get_broadphase()->set_static(s.bpid, _static);
206
}
207
208
space->get_broadphase()->move(s.bpid, shape_aabb);
209
}
210
}
211
212
void GodotCollisionObject3D::_set_space(GodotSpace3D *p_space) {
213
GodotSpace3D *old_space = space;
214
space = p_space;
215
216
if (old_space) {
217
old_space->remove_object(this);
218
219
for (int i = 0; i < shapes.size(); i++) {
220
Shape &s = shapes.write[i];
221
if (s.bpid) {
222
old_space->get_broadphase()->remove(s.bpid);
223
s.bpid = 0;
224
}
225
}
226
}
227
228
if (space) {
229
space->add_object(this);
230
_update_shapes();
231
}
232
}
233
234
void GodotCollisionObject3D::_shape_changed() {
235
_update_shapes();
236
_shapes_changed();
237
}
238
239
GodotCollisionObject3D::GodotCollisionObject3D(Type p_type) :
240
pending_shape_update_list(this) {
241
type = p_type;
242
}
243
244