bullet3 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +194 -0
- data/data/cube.urdf +22 -0
- data/data/plane.urdf +19 -0
- data/ext/bullet3/CMakeLists.txt +224 -0
- data/ext/bullet3/bullet3.cpp +34 -0
- data/ext/bullet3/collision/rb_collision.cpp +428 -0
- data/ext/bullet3/collision/rb_collision.hpp +87 -0
- data/ext/bullet3/collision/shapes/rb_collision_shape.cpp +485 -0
- data/ext/bullet3/collision/shapes/rb_collision_shape.hpp +5 -0
- data/ext/bullet3/constraints/rb_constraints.cpp +1310 -0
- data/ext/bullet3/constraints/rb_constraints.hpp +226 -0
- data/ext/bullet3/dynamics/rb_dynamics.cpp +862 -0
- data/ext/bullet3/dynamics/rb_dynamics.hpp +180 -0
- data/ext/bullet3/extconf.rb +57 -0
- data/ext/bullet3/io/rb_io.cpp +108 -0
- data/ext/bullet3/io/rb_io.hpp +40 -0
- data/ext/bullet3/linear_math/rb_matrix3x3.cpp +93 -0
- data/ext/bullet3/linear_math/rb_matrix3x3.hpp +5 -0
- data/ext/bullet3/linear_math/rb_quaternion.cpp +134 -0
- data/ext/bullet3/linear_math/rb_quaternion.hpp +5 -0
- data/ext/bullet3/linear_math/rb_transform.cpp +157 -0
- data/ext/bullet3/linear_math/rb_transform.hpp +34 -0
- data/ext/bullet3/linear_math/rb_vector3.cpp +123 -0
- data/ext/bullet3/linear_math/rb_vector3.hpp +5 -0
- data/ext/bullet3/multi_body/rb_multi_body.cpp +1000 -0
- data/ext/bullet3/multi_body/rb_multi_body.hpp +190 -0
- data/ext/bullet3/soft_body/rb_soft_body.cpp +720 -0
- data/ext/bullet3/soft_body/rb_soft_body.hpp +122 -0
- data/ext/bullet3/util/rb_debug_draw.cpp +250 -0
- data/ext/bullet3/util/rb_debug_draw.hpp +47 -0
- data/ext/bullet3/util/ruby_cpp_compat.hpp +29 -0
- data/ext/bullet3/util/type_conversions.hpp +107 -0
- data/ext/bullet3/vehicle/rb_vehicle.cpp +467 -0
- data/ext/bullet3/vehicle/rb_vehicle.hpp +115 -0
- data/lib/bullet3/collision.rb +6 -0
- data/lib/bullet3/constraints.rb +6 -0
- data/lib/bullet3/data.rb +39 -0
- data/lib/bullet3/debug_draw.rb +73 -0
- data/lib/bullet3/dynamics.rb +4 -0
- data/lib/bullet3/io.rb +110 -0
- data/lib/bullet3/linear_math/matrix3x3.rb +69 -0
- data/lib/bullet3/linear_math/quaternion.rb +187 -0
- data/lib/bullet3/linear_math/transform.rb +48 -0
- data/lib/bullet3/linear_math/vector3.rb +199 -0
- data/lib/bullet3/linear_math.rb +6 -0
- data/lib/bullet3/multi_body.rb +6 -0
- data/lib/bullet3/simulation.rb +1170 -0
- data/lib/bullet3/soft_body.rb +6 -0
- data/lib/bullet3/vehicle.rb +4 -0
- data/lib/bullet3/version.rb +5 -0
- data/lib/bullet3.rb +49 -0
- metadata +124 -0
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
#include "rb_collision.hpp"
|
|
2
|
+
|
|
3
|
+
#include <functional>
|
|
4
|
+
#include <stdexcept>
|
|
5
|
+
#include <utility>
|
|
6
|
+
|
|
7
|
+
#include "../dynamics/rb_dynamics.hpp"
|
|
8
|
+
#include "../util/type_conversions.hpp"
|
|
9
|
+
|
|
10
|
+
namespace {
|
|
11
|
+
btCollisionShape* collision_shape_from_value(VALUE value)
|
|
12
|
+
{
|
|
13
|
+
btCollisionShape* shape = Rice::detail::From_Ruby<btCollisionShape*>().convert(value);
|
|
14
|
+
if (shape == nullptr) {
|
|
15
|
+
throw std::invalid_argument("expected Bullet3::Shapes::CollisionShape");
|
|
16
|
+
}
|
|
17
|
+
return shape;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
bullet3::CollisionObject* collision_object_from_value(VALUE value)
|
|
21
|
+
{
|
|
22
|
+
bullet3::CollisionObject* object = Rice::detail::From_Ruby<bullet3::CollisionObject*>().convert(value);
|
|
23
|
+
if (object == nullptr) {
|
|
24
|
+
throw std::invalid_argument("expected Bullet3::CollisionObject");
|
|
25
|
+
}
|
|
26
|
+
return object;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
void set_vector_hash_value(Rice::Hash& hash, const char* key, const btVector3& value)
|
|
30
|
+
{
|
|
31
|
+
hash[Rice::Symbol(key)] = Rice::Object(Rice::detail::To_Ruby<btVector3>().convert(btVector3(value)));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
Rice::Array aabb_array(const btVector3& aabb_min, const btVector3& aabb_max)
|
|
35
|
+
{
|
|
36
|
+
Rice::Array array;
|
|
37
|
+
array.push(Rice::Object(Rice::detail::To_Ruby<btVector3>().convert(btVector3(aabb_min))));
|
|
38
|
+
array.push(Rice::Object(Rice::detail::To_Ruby<btVector3>().convert(btVector3(aabb_max))));
|
|
39
|
+
return array;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
class ContactCollector : public btCollisionWorld::ContactResultCallback {
|
|
43
|
+
public:
|
|
44
|
+
explicit ContactCollector(std::function<VALUE(const btCollisionObject*)> ruby_object_for)
|
|
45
|
+
: ruby_object_for_(std::move(ruby_object_for))
|
|
46
|
+
{
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
btScalar addSingleResult(btManifoldPoint& contact_point,
|
|
50
|
+
const btCollisionObjectWrapper* object0,
|
|
51
|
+
int part_id0,
|
|
52
|
+
int index0,
|
|
53
|
+
const btCollisionObjectWrapper* object1,
|
|
54
|
+
int part_id1,
|
|
55
|
+
int index1) override
|
|
56
|
+
{
|
|
57
|
+
Rice::Hash contact;
|
|
58
|
+
contact[Rice::Symbol("body0")] = Rice::Object(ruby_object_for_(object0->getCollisionObject()));
|
|
59
|
+
contact[Rice::Symbol("body1")] = Rice::Object(ruby_object_for_(object1->getCollisionObject()));
|
|
60
|
+
set_vector_hash_value(contact, "position_world_on_a", contact_point.getPositionWorldOnA());
|
|
61
|
+
set_vector_hash_value(contact, "position_world_on_b", contact_point.getPositionWorldOnB());
|
|
62
|
+
set_vector_hash_value(contact, "normal_world_on_b", contact_point.m_normalWorldOnB);
|
|
63
|
+
contact[Rice::Symbol("distance")] = contact_point.getDistance();
|
|
64
|
+
contact[Rice::Symbol("part_id0")] = part_id0;
|
|
65
|
+
contact[Rice::Symbol("index0")] = index0;
|
|
66
|
+
contact[Rice::Symbol("part_id1")] = part_id1;
|
|
67
|
+
contact[Rice::Symbol("index1")] = index1;
|
|
68
|
+
contacts.push(contact);
|
|
69
|
+
return btScalar(0);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
Rice::Array contacts;
|
|
73
|
+
|
|
74
|
+
private:
|
|
75
|
+
std::function<VALUE(const btCollisionObject*)> ruby_object_for_;
|
|
76
|
+
};
|
|
77
|
+
} // namespace
|
|
78
|
+
|
|
79
|
+
namespace bullet3 {
|
|
80
|
+
AxisSweep3::AxisSweep3(VALUE world_aabb_min, VALUE world_aabb_max, int max_handles)
|
|
81
|
+
: broadphase_(std::make_unique<btAxisSweep3>(
|
|
82
|
+
coerce_vector(Rice::Object(world_aabb_min)),
|
|
83
|
+
coerce_vector(Rice::Object(world_aabb_max)),
|
|
84
|
+
static_cast<unsigned short>(max_handles)))
|
|
85
|
+
{
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
btAxisSweep3* AxisSweep3::get()
|
|
89
|
+
{
|
|
90
|
+
return broadphase_.get();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
CollisionObject::CollisionObject()
|
|
94
|
+
: collision_object_(std::make_unique<btCollisionObject>())
|
|
95
|
+
{
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
CollisionObject::CollisionObject(VALUE collision_shape)
|
|
99
|
+
: CollisionObject()
|
|
100
|
+
{
|
|
101
|
+
set_collision_shape(collision_shape);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
btCollisionObject* CollisionObject::get()
|
|
105
|
+
{
|
|
106
|
+
return collision_object_.get();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const btCollisionObject* CollisionObject::get() const
|
|
110
|
+
{
|
|
111
|
+
return collision_object_.get();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
Transform CollisionObject::world_transform() const
|
|
115
|
+
{
|
|
116
|
+
return Transform(collision_object_->getWorldTransform());
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
Transform CollisionObject::set_world_transform(Rice::Object transform)
|
|
120
|
+
{
|
|
121
|
+
btTransform value = coerce_transform(transform);
|
|
122
|
+
collision_object_->setWorldTransform(value);
|
|
123
|
+
return Transform(value);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
btCollisionShape* CollisionObject::collision_shape() const
|
|
127
|
+
{
|
|
128
|
+
return collision_object_->getCollisionShape();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
void CollisionObject::set_collision_shape(VALUE collision_shape)
|
|
132
|
+
{
|
|
133
|
+
collision_object_->setCollisionShape(collision_shape_from_value(collision_shape));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
btScalar CollisionObject::friction() const
|
|
137
|
+
{
|
|
138
|
+
return collision_object_->getFriction();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
btScalar CollisionObject::set_friction(btScalar friction)
|
|
142
|
+
{
|
|
143
|
+
collision_object_->setFriction(friction);
|
|
144
|
+
return friction;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
btScalar CollisionObject::restitution() const
|
|
148
|
+
{
|
|
149
|
+
return collision_object_->getRestitution();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
btScalar CollisionObject::set_restitution(btScalar restitution)
|
|
153
|
+
{
|
|
154
|
+
collision_object_->setRestitution(restitution);
|
|
155
|
+
return restitution;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
int CollisionObject::collision_flags() const
|
|
159
|
+
{
|
|
160
|
+
return collision_object_->getCollisionFlags();
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
int CollisionObject::set_collision_flags(int flags)
|
|
164
|
+
{
|
|
165
|
+
collision_object_->setCollisionFlags(flags);
|
|
166
|
+
return flags;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
bool CollisionObject::active() const
|
|
170
|
+
{
|
|
171
|
+
return collision_object_->isActive();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
void CollisionObject::activate()
|
|
175
|
+
{
|
|
176
|
+
collision_object_->activate(true);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
Rice::Array CollisionObject::aabb() const
|
|
180
|
+
{
|
|
181
|
+
btCollisionShape* shape = collision_object_->getCollisionShape();
|
|
182
|
+
if (shape == nullptr) {
|
|
183
|
+
throw std::runtime_error("collision object has no shape");
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
btVector3 aabb_min;
|
|
187
|
+
btVector3 aabb_max;
|
|
188
|
+
shape->getAabb(collision_object_->getWorldTransform(), aabb_min, aabb_max);
|
|
189
|
+
return aabb_array(aabb_min, aabb_max);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
CollisionWorld::CollisionWorld()
|
|
193
|
+
{
|
|
194
|
+
build_owned_world();
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
CollisionWorld::CollisionWorld(CollisionDispatcher& dispatcher, DbvtBroadphase& broadphase, CollisionConfiguration& configuration)
|
|
198
|
+
: world_(std::make_unique<btCollisionWorld>(dispatcher.get(), broadphase.get(), configuration.get()))
|
|
199
|
+
{
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
CollisionWorld::CollisionWorld(CollisionDispatcher& dispatcher, AxisSweep3& broadphase, CollisionConfiguration& configuration)
|
|
203
|
+
: world_(std::make_unique<btCollisionWorld>(dispatcher.get(), broadphase.get(), configuration.get()))
|
|
204
|
+
{
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
CollisionWorld::~CollisionWorld()
|
|
208
|
+
{
|
|
209
|
+
collision_objects_.clear();
|
|
210
|
+
collision_object_values_.clear();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
void CollisionWorld::build_owned_world()
|
|
214
|
+
{
|
|
215
|
+
owned_configuration_ = std::make_unique<btDefaultCollisionConfiguration>();
|
|
216
|
+
owned_dispatcher_ = std::make_unique<btCollisionDispatcher>(owned_configuration_.get());
|
|
217
|
+
owned_broadphase_ = std::make_unique<btDbvtBroadphase>();
|
|
218
|
+
world_ = std::make_unique<btCollisionWorld>(owned_dispatcher_.get(), owned_broadphase_.get(), owned_configuration_.get());
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
btCollisionWorld* CollisionWorld::get()
|
|
222
|
+
{
|
|
223
|
+
return world_.get();
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
void CollisionWorld::add_collision_object(VALUE collision_object, int group, int mask)
|
|
227
|
+
{
|
|
228
|
+
CollisionObject* object = collision_object_from_value(collision_object);
|
|
229
|
+
btCollisionObject* bullet_object = object->get();
|
|
230
|
+
if (collision_objects_.insert(bullet_object).second) {
|
|
231
|
+
world_->addCollisionObject(bullet_object, group, mask);
|
|
232
|
+
collision_object_values_[bullet_object] = collision_object;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
void CollisionWorld::remove_collision_object(VALUE collision_object)
|
|
237
|
+
{
|
|
238
|
+
CollisionObject* object = collision_object_from_value(collision_object);
|
|
239
|
+
btCollisionObject* bullet_object = object->get();
|
|
240
|
+
auto iterator = collision_objects_.find(bullet_object);
|
|
241
|
+
if (iterator != collision_objects_.end()) {
|
|
242
|
+
world_->removeCollisionObject(bullet_object);
|
|
243
|
+
collision_objects_.erase(iterator);
|
|
244
|
+
}
|
|
245
|
+
collision_object_values_.erase(bullet_object);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
int CollisionWorld::num_collision_objects() const
|
|
249
|
+
{
|
|
250
|
+
return world_->getNumCollisionObjects();
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
void CollisionWorld::update_aabbs()
|
|
254
|
+
{
|
|
255
|
+
world_->updateAabbs();
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
void CollisionWorld::compute_overlapping_pairs()
|
|
259
|
+
{
|
|
260
|
+
world_->computeOverlappingPairs();
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
VALUE CollisionWorld::ruby_object_for(const btCollisionObject* collision_object) const
|
|
264
|
+
{
|
|
265
|
+
auto iterator = collision_object_values_.find(collision_object);
|
|
266
|
+
if (iterator == collision_object_values_.end()) {
|
|
267
|
+
return Qnil;
|
|
268
|
+
}
|
|
269
|
+
return iterator->second;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
Rice::Object CollisionWorld::ray_test_closest(Rice::Object from, Rice::Object to) const
|
|
273
|
+
{
|
|
274
|
+
btVector3 ray_from = coerce_vector(from);
|
|
275
|
+
btVector3 ray_to = coerce_vector(to);
|
|
276
|
+
btCollisionWorld::ClosestRayResultCallback callback(ray_from, ray_to);
|
|
277
|
+
world_->rayTest(ray_from, ray_to, callback);
|
|
278
|
+
|
|
279
|
+
if (!callback.hasHit()) {
|
|
280
|
+
return Rice::Object(Qnil);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
Rice::Hash hit;
|
|
284
|
+
hit[Rice::Symbol("body")] = Rice::Object(ruby_object_for(callback.m_collisionObject));
|
|
285
|
+
hit[Rice::Symbol("fraction")] = callback.m_closestHitFraction;
|
|
286
|
+
set_vector_hash_value(hit, "point", callback.m_hitPointWorld);
|
|
287
|
+
set_vector_hash_value(hit, "normal", callback.m_hitNormalWorld);
|
|
288
|
+
return hit;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
Rice::Array CollisionWorld::ray_test_all(Rice::Object from, Rice::Object to) const
|
|
292
|
+
{
|
|
293
|
+
btVector3 ray_from = coerce_vector(from);
|
|
294
|
+
btVector3 ray_to = coerce_vector(to);
|
|
295
|
+
btCollisionWorld::AllHitsRayResultCallback callback(ray_from, ray_to);
|
|
296
|
+
world_->rayTest(ray_from, ray_to, callback);
|
|
297
|
+
|
|
298
|
+
Rice::Array hits;
|
|
299
|
+
for (int index = 0; index < callback.m_collisionObjects.size(); ++index) {
|
|
300
|
+
Rice::Hash hit;
|
|
301
|
+
hit[Rice::Symbol("body")] = Rice::Object(ruby_object_for(callback.m_collisionObjects[index]));
|
|
302
|
+
hit[Rice::Symbol("fraction")] = callback.m_hitFractions[index];
|
|
303
|
+
set_vector_hash_value(hit, "point", callback.m_hitPointWorld[index]);
|
|
304
|
+
set_vector_hash_value(hit, "normal", callback.m_hitNormalWorld[index]);
|
|
305
|
+
hits.push(hit);
|
|
306
|
+
}
|
|
307
|
+
return hits;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
Rice::Array CollisionWorld::contact_test(VALUE collision_object) const
|
|
311
|
+
{
|
|
312
|
+
CollisionObject* object = collision_object_from_value(collision_object);
|
|
313
|
+
ContactCollector callback([this](const btCollisionObject* bullet_object) {
|
|
314
|
+
return ruby_object_for(bullet_object);
|
|
315
|
+
});
|
|
316
|
+
world_->contactTest(object->get(), callback);
|
|
317
|
+
return callback.contacts;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
Rice::Array CollisionWorld::contact_pair_test(VALUE collision_object_a, VALUE collision_object_b) const
|
|
321
|
+
{
|
|
322
|
+
CollisionObject* object_a = collision_object_from_value(collision_object_a);
|
|
323
|
+
CollisionObject* object_b = collision_object_from_value(collision_object_b);
|
|
324
|
+
ContactCollector callback([this](const btCollisionObject* bullet_object) {
|
|
325
|
+
return ruby_object_for(bullet_object);
|
|
326
|
+
});
|
|
327
|
+
world_->contactPairTest(object_a->get(), object_b->get(), callback);
|
|
328
|
+
return callback.contacts;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
Rice::Array CollisionWorld::closest_points(VALUE collision_object_a, VALUE collision_object_b, btScalar distance_threshold) const
|
|
332
|
+
{
|
|
333
|
+
CollisionObject* object_a = collision_object_from_value(collision_object_a);
|
|
334
|
+
CollisionObject* object_b = collision_object_from_value(collision_object_b);
|
|
335
|
+
ContactCollector callback([this](const btCollisionObject* bullet_object) {
|
|
336
|
+
return ruby_object_for(bullet_object);
|
|
337
|
+
});
|
|
338
|
+
callback.m_closestDistanceThreshold = distance_threshold;
|
|
339
|
+
world_->contactPairTest(object_a->get(), object_b->get(), callback);
|
|
340
|
+
return callback.contacts;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
void CollisionWorld::mark() const
|
|
344
|
+
{
|
|
345
|
+
for (const auto& entry : collision_object_values_) {
|
|
346
|
+
rb_gc_mark(entry.second);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
} // namespace bullet3
|
|
350
|
+
|
|
351
|
+
namespace Rice {
|
|
352
|
+
template <>
|
|
353
|
+
void ruby_mark<bullet3::CollisionWorld>(bullet3::CollisionWorld* world)
|
|
354
|
+
{
|
|
355
|
+
if (world != nullptr) {
|
|
356
|
+
world->mark();
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
} // namespace Rice
|
|
360
|
+
|
|
361
|
+
void Init_Collision(Rice::Module rb_mBullet)
|
|
362
|
+
{
|
|
363
|
+
Rice::define_class_under<bullet3::AxisSweep3>(rb_mBullet, "AxisSweep3")
|
|
364
|
+
.define_constructor(Rice::Constructor<bullet3::AxisSweep3, VALUE, VALUE, int>(),
|
|
365
|
+
Rice::Arg("world_aabb_min").setValue(),
|
|
366
|
+
Rice::Arg("world_aabb_max").setValue(),
|
|
367
|
+
Rice::Arg("max_handles") = 16384);
|
|
368
|
+
|
|
369
|
+
Rice::define_class_under<bullet3::CollisionObject>(rb_mBullet, "CollisionObject")
|
|
370
|
+
.define_constructor(Rice::Constructor<bullet3::CollisionObject>())
|
|
371
|
+
.define_constructor(Rice::Constructor<bullet3::CollisionObject, VALUE>(),
|
|
372
|
+
Rice::Arg("collision_shape").setValue().keepAlive())
|
|
373
|
+
.define_method("world_transform", &bullet3::CollisionObject::world_transform)
|
|
374
|
+
.define_method("world_transform=", &bullet3::CollisionObject::set_world_transform)
|
|
375
|
+
.define_method("collision_shape", &bullet3::CollisionObject::collision_shape)
|
|
376
|
+
.define_method("collision_shape=", &bullet3::CollisionObject::set_collision_shape,
|
|
377
|
+
Rice::Arg("collision_shape").setValue().keepAlive())
|
|
378
|
+
.define_method("friction", &bullet3::CollisionObject::friction)
|
|
379
|
+
.define_method("friction=", &bullet3::CollisionObject::set_friction)
|
|
380
|
+
.define_method("restitution", &bullet3::CollisionObject::restitution)
|
|
381
|
+
.define_method("restitution=", &bullet3::CollisionObject::set_restitution)
|
|
382
|
+
.define_method("collision_flags", &bullet3::CollisionObject::collision_flags)
|
|
383
|
+
.define_method("collision_flags=", &bullet3::CollisionObject::set_collision_flags)
|
|
384
|
+
.define_method("active?", &bullet3::CollisionObject::active)
|
|
385
|
+
.define_method("activate", &bullet3::CollisionObject::activate)
|
|
386
|
+
.define_method("aabb", &bullet3::CollisionObject::aabb);
|
|
387
|
+
|
|
388
|
+
Rice::define_class_under<bullet3::CollisionWorld>(rb_mBullet, "CollisionWorld")
|
|
389
|
+
.define_constructor(Rice::Constructor<bullet3::CollisionWorld>())
|
|
390
|
+
.define_constructor(Rice::Constructor<bullet3::CollisionWorld,
|
|
391
|
+
bullet3::CollisionDispatcher&,
|
|
392
|
+
bullet3::DbvtBroadphase&,
|
|
393
|
+
bullet3::CollisionConfiguration&>(),
|
|
394
|
+
Rice::Arg("dispatcher").keepAlive(),
|
|
395
|
+
Rice::Arg("broadphase").keepAlive(),
|
|
396
|
+
Rice::Arg("configuration").keepAlive())
|
|
397
|
+
.define_constructor(Rice::Constructor<bullet3::CollisionWorld,
|
|
398
|
+
bullet3::CollisionDispatcher&,
|
|
399
|
+
bullet3::AxisSweep3&,
|
|
400
|
+
bullet3::CollisionConfiguration&>(),
|
|
401
|
+
Rice::Arg("dispatcher").keepAlive(),
|
|
402
|
+
Rice::Arg("broadphase").keepAlive(),
|
|
403
|
+
Rice::Arg("configuration").keepAlive())
|
|
404
|
+
.define_singleton_method("create", [](Rice::Object) -> bullet3::CollisionWorld* {
|
|
405
|
+
return new bullet3::CollisionWorld();
|
|
406
|
+
}, Rice::Return().takeOwnership())
|
|
407
|
+
.define_method("add_collision_object", &bullet3::CollisionWorld::add_collision_object,
|
|
408
|
+
Rice::Arg("collision_object").setValue().keepAlive(),
|
|
409
|
+
Rice::Arg("group") = int(btBroadphaseProxy::DefaultFilter),
|
|
410
|
+
Rice::Arg("mask") = int(btBroadphaseProxy::AllFilter))
|
|
411
|
+
.define_method("remove_collision_object", &bullet3::CollisionWorld::remove_collision_object,
|
|
412
|
+
Rice::Arg("collision_object").setValue())
|
|
413
|
+
.define_method("num_collision_objects", &bullet3::CollisionWorld::num_collision_objects)
|
|
414
|
+
.define_method("update_aabbs", &bullet3::CollisionWorld::update_aabbs)
|
|
415
|
+
.define_method("compute_overlapping_pairs", &bullet3::CollisionWorld::compute_overlapping_pairs)
|
|
416
|
+
.define_method("ray_test_closest", &bullet3::CollisionWorld::ray_test_closest)
|
|
417
|
+
.define_method("ray_test", &bullet3::CollisionWorld::ray_test_closest)
|
|
418
|
+
.define_method("ray_test_all", &bullet3::CollisionWorld::ray_test_all)
|
|
419
|
+
.define_method("contact_test", &bullet3::CollisionWorld::contact_test,
|
|
420
|
+
Rice::Arg("collision_object").setValue())
|
|
421
|
+
.define_method("contact_pair_test", &bullet3::CollisionWorld::contact_pair_test,
|
|
422
|
+
Rice::Arg("collision_object_a").setValue(),
|
|
423
|
+
Rice::Arg("collision_object_b").setValue())
|
|
424
|
+
.define_method("closest_points", &bullet3::CollisionWorld::closest_points,
|
|
425
|
+
Rice::Arg("collision_object_a").setValue(),
|
|
426
|
+
Rice::Arg("collision_object_b").setValue(),
|
|
427
|
+
Rice::Arg("distance_threshold") = btScalar(0.0));
|
|
428
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <memory>
|
|
4
|
+
#include <unordered_map>
|
|
5
|
+
#include <unordered_set>
|
|
6
|
+
|
|
7
|
+
#include <BulletCollision/BroadphaseCollision/btAxisSweep3.h>
|
|
8
|
+
#include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
|
|
9
|
+
#include <btBulletDynamicsCommon.h>
|
|
10
|
+
#include <rice/rice.hpp>
|
|
11
|
+
|
|
12
|
+
#include "../linear_math/rb_transform.hpp"
|
|
13
|
+
|
|
14
|
+
namespace bullet3 {
|
|
15
|
+
class CollisionConfiguration;
|
|
16
|
+
class CollisionDispatcher;
|
|
17
|
+
class DbvtBroadphase;
|
|
18
|
+
|
|
19
|
+
class AxisSweep3 {
|
|
20
|
+
public:
|
|
21
|
+
AxisSweep3(VALUE world_aabb_min, VALUE world_aabb_max, int max_handles);
|
|
22
|
+
|
|
23
|
+
btAxisSweep3* get();
|
|
24
|
+
|
|
25
|
+
private:
|
|
26
|
+
std::unique_ptr<btAxisSweep3> broadphase_;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
class CollisionObject {
|
|
30
|
+
public:
|
|
31
|
+
CollisionObject();
|
|
32
|
+
explicit CollisionObject(VALUE collision_shape);
|
|
33
|
+
|
|
34
|
+
btCollisionObject* get();
|
|
35
|
+
const btCollisionObject* get() const;
|
|
36
|
+
Transform world_transform() const;
|
|
37
|
+
Transform set_world_transform(Rice::Object transform);
|
|
38
|
+
btCollisionShape* collision_shape() const;
|
|
39
|
+
void set_collision_shape(VALUE collision_shape);
|
|
40
|
+
btScalar friction() const;
|
|
41
|
+
btScalar set_friction(btScalar friction);
|
|
42
|
+
btScalar restitution() const;
|
|
43
|
+
btScalar set_restitution(btScalar restitution);
|
|
44
|
+
int collision_flags() const;
|
|
45
|
+
int set_collision_flags(int flags);
|
|
46
|
+
bool active() const;
|
|
47
|
+
void activate();
|
|
48
|
+
Rice::Array aabb() const;
|
|
49
|
+
|
|
50
|
+
private:
|
|
51
|
+
std::unique_ptr<btCollisionObject> collision_object_;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
class CollisionWorld {
|
|
55
|
+
public:
|
|
56
|
+
CollisionWorld();
|
|
57
|
+
CollisionWorld(CollisionDispatcher& dispatcher, DbvtBroadphase& broadphase, CollisionConfiguration& configuration);
|
|
58
|
+
CollisionWorld(CollisionDispatcher& dispatcher, AxisSweep3& broadphase, CollisionConfiguration& configuration);
|
|
59
|
+
~CollisionWorld();
|
|
60
|
+
|
|
61
|
+
btCollisionWorld* get();
|
|
62
|
+
void add_collision_object(VALUE collision_object, int group, int mask);
|
|
63
|
+
void remove_collision_object(VALUE collision_object);
|
|
64
|
+
int num_collision_objects() const;
|
|
65
|
+
void update_aabbs();
|
|
66
|
+
void compute_overlapping_pairs();
|
|
67
|
+
Rice::Object ray_test_closest(Rice::Object from, Rice::Object to) const;
|
|
68
|
+
Rice::Array ray_test_all(Rice::Object from, Rice::Object to) const;
|
|
69
|
+
Rice::Array contact_test(VALUE collision_object) const;
|
|
70
|
+
Rice::Array contact_pair_test(VALUE collision_object_a, VALUE collision_object_b) const;
|
|
71
|
+
Rice::Array closest_points(VALUE collision_object_a, VALUE collision_object_b, btScalar distance_threshold) const;
|
|
72
|
+
void mark() const;
|
|
73
|
+
|
|
74
|
+
private:
|
|
75
|
+
void build_owned_world();
|
|
76
|
+
VALUE ruby_object_for(const btCollisionObject* collision_object) const;
|
|
77
|
+
|
|
78
|
+
std::unique_ptr<btDefaultCollisionConfiguration> owned_configuration_;
|
|
79
|
+
std::unique_ptr<btCollisionDispatcher> owned_dispatcher_;
|
|
80
|
+
std::unique_ptr<btDbvtBroadphase> owned_broadphase_;
|
|
81
|
+
std::unique_ptr<btCollisionWorld> world_;
|
|
82
|
+
std::unordered_set<btCollisionObject*> collision_objects_;
|
|
83
|
+
std::unordered_map<const btCollisionObject*, VALUE> collision_object_values_;
|
|
84
|
+
};
|
|
85
|
+
} // namespace bullet3
|
|
86
|
+
|
|
87
|
+
void Init_Collision(Rice::Module rb_mBullet);
|