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,862 @@
|
|
|
1
|
+
#include "rb_dynamics.hpp"
|
|
2
|
+
|
|
3
|
+
#include <functional>
|
|
4
|
+
#include <stdexcept>
|
|
5
|
+
#include <utility>
|
|
6
|
+
|
|
7
|
+
#include <ruby/thread.h>
|
|
8
|
+
|
|
9
|
+
#include "../constraints/rb_constraints.hpp"
|
|
10
|
+
#include "../util/type_conversions.hpp"
|
|
11
|
+
#include "../vehicle/rb_vehicle.hpp"
|
|
12
|
+
|
|
13
|
+
namespace {
|
|
14
|
+
btCollisionShape* coerce_collision_shape(Rice::Object object)
|
|
15
|
+
{
|
|
16
|
+
btCollisionShape* shape = Rice::detail::From_Ruby<btCollisionShape*>().convert(object);
|
|
17
|
+
if (shape == nullptr) {
|
|
18
|
+
throw std::invalid_argument("expected Bullet3::Shapes::CollisionShape");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return shape;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
btVector3 calculate_local_inertia(btCollisionShape& shape, btScalar mass)
|
|
25
|
+
{
|
|
26
|
+
btVector3 inertia(0, 0, 0);
|
|
27
|
+
if (mass != btScalar(0)) {
|
|
28
|
+
shape.calculateLocalInertia(mass, inertia);
|
|
29
|
+
}
|
|
30
|
+
return inertia;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
struct StepSimulationArgs {
|
|
34
|
+
btDiscreteDynamicsWorld* world;
|
|
35
|
+
btScalar time_step;
|
|
36
|
+
int max_sub_steps;
|
|
37
|
+
btScalar fixed_time_step;
|
|
38
|
+
int result;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
void* step_simulation_without_gvl(void* pointer)
|
|
42
|
+
{
|
|
43
|
+
auto* args = static_cast<StepSimulationArgs*>(pointer);
|
|
44
|
+
args->result = args->world->stepSimulation(args->time_step, args->max_sub_steps, args->fixed_time_step);
|
|
45
|
+
return nullptr;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
void set_vector_hash_value(Rice::Hash& hash, const char* key, const btVector3& value)
|
|
49
|
+
{
|
|
50
|
+
hash[Rice::Symbol(key)] = Rice::Object(Rice::detail::To_Ruby<btVector3>().convert(btVector3(value)));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
bullet3::RigidBody* rigid_body_from_value(VALUE value)
|
|
54
|
+
{
|
|
55
|
+
bullet3::RigidBody* body = Rice::detail::From_Ruby<bullet3::RigidBody*>().convert(value);
|
|
56
|
+
if (body == nullptr) {
|
|
57
|
+
throw std::invalid_argument("expected Bullet3::RigidBody");
|
|
58
|
+
}
|
|
59
|
+
return body;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
class ContactCollector : public btCollisionWorld::ContactResultCallback {
|
|
63
|
+
public:
|
|
64
|
+
explicit ContactCollector(std::function<VALUE(const btCollisionObject*)> ruby_object_for)
|
|
65
|
+
: ruby_object_for_(std::move(ruby_object_for))
|
|
66
|
+
{
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
btScalar addSingleResult(btManifoldPoint& contact_point,
|
|
70
|
+
const btCollisionObjectWrapper* object0,
|
|
71
|
+
int part_id0,
|
|
72
|
+
int index0,
|
|
73
|
+
const btCollisionObjectWrapper* object1,
|
|
74
|
+
int part_id1,
|
|
75
|
+
int index1) override
|
|
76
|
+
{
|
|
77
|
+
Rice::Hash contact;
|
|
78
|
+
contact[Rice::Symbol("body0")] = Rice::Object(ruby_object_for_(object0->getCollisionObject()));
|
|
79
|
+
contact[Rice::Symbol("body1")] = Rice::Object(ruby_object_for_(object1->getCollisionObject()));
|
|
80
|
+
set_vector_hash_value(contact, "position_world_on_a", contact_point.getPositionWorldOnA());
|
|
81
|
+
set_vector_hash_value(contact, "position_world_on_b", contact_point.getPositionWorldOnB());
|
|
82
|
+
set_vector_hash_value(contact, "normal_world_on_b", contact_point.m_normalWorldOnB);
|
|
83
|
+
contact[Rice::Symbol("distance")] = contact_point.getDistance();
|
|
84
|
+
contact[Rice::Symbol("part_id0")] = part_id0;
|
|
85
|
+
contact[Rice::Symbol("index0")] = index0;
|
|
86
|
+
contact[Rice::Symbol("part_id1")] = part_id1;
|
|
87
|
+
contact[Rice::Symbol("index1")] = index1;
|
|
88
|
+
contacts.push(contact);
|
|
89
|
+
return btScalar(0);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
Rice::Array contacts;
|
|
93
|
+
|
|
94
|
+
private:
|
|
95
|
+
std::function<VALUE(const btCollisionObject*)> ruby_object_for_;
|
|
96
|
+
};
|
|
97
|
+
} // namespace
|
|
98
|
+
|
|
99
|
+
namespace bullet3 {
|
|
100
|
+
CollisionConfiguration::CollisionConfiguration()
|
|
101
|
+
: configuration_(std::make_unique<btDefaultCollisionConfiguration>())
|
|
102
|
+
{
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
btDefaultCollisionConfiguration* CollisionConfiguration::get()
|
|
106
|
+
{
|
|
107
|
+
return configuration_.get();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
CollisionDispatcher::CollisionDispatcher(CollisionConfiguration& configuration)
|
|
111
|
+
: dispatcher_(std::make_unique<btCollisionDispatcher>(configuration.get()))
|
|
112
|
+
{
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
btCollisionDispatcher* CollisionDispatcher::get()
|
|
116
|
+
{
|
|
117
|
+
return dispatcher_.get();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
DbvtBroadphase::DbvtBroadphase()
|
|
121
|
+
: broadphase_(std::make_unique<btDbvtBroadphase>())
|
|
122
|
+
{
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
btDbvtBroadphase* DbvtBroadphase::get()
|
|
126
|
+
{
|
|
127
|
+
return broadphase_.get();
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
SequentialImpulseConstraintSolver::SequentialImpulseConstraintSolver()
|
|
131
|
+
: solver_(std::make_unique<btSequentialImpulseConstraintSolver>())
|
|
132
|
+
{
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
btSequentialImpulseConstraintSolver* SequentialImpulseConstraintSolver::get()
|
|
136
|
+
{
|
|
137
|
+
return solver_.get();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
MotionState::MotionState()
|
|
141
|
+
: motion_state_(std::make_unique<btDefaultMotionState>(btTransform::getIdentity()))
|
|
142
|
+
{
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
MotionState::MotionState(VALUE start_transform)
|
|
146
|
+
: motion_state_(std::make_unique<btDefaultMotionState>(coerce_transform(Rice::Object(start_transform))))
|
|
147
|
+
{
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
btMotionState* MotionState::get()
|
|
151
|
+
{
|
|
152
|
+
return motion_state_.get();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
Transform MotionState::world_transform() const
|
|
156
|
+
{
|
|
157
|
+
btTransform transform;
|
|
158
|
+
motion_state_->getWorldTransform(transform);
|
|
159
|
+
return Transform(transform);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
Transform MotionState::set_world_transform(Rice::Object transform)
|
|
163
|
+
{
|
|
164
|
+
btTransform value = coerce_transform(transform);
|
|
165
|
+
motion_state_->setWorldTransform(value);
|
|
166
|
+
return Transform(value);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
RigidBodyConstructionInfo::RigidBodyConstructionInfo(btScalar mass,
|
|
170
|
+
MotionState& motion_state,
|
|
171
|
+
VALUE collision_shape)
|
|
172
|
+
: local_inertia_(calculate_local_inertia(*coerce_collision_shape(Rice::Object(collision_shape)), mass)),
|
|
173
|
+
info_(std::make_unique<btRigidBody::btRigidBodyConstructionInfo>(
|
|
174
|
+
mass,
|
|
175
|
+
motion_state.get(),
|
|
176
|
+
coerce_collision_shape(Rice::Object(collision_shape)),
|
|
177
|
+
local_inertia_))
|
|
178
|
+
{
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
RigidBodyConstructionInfo::RigidBodyConstructionInfo(btScalar mass,
|
|
182
|
+
MotionState& motion_state,
|
|
183
|
+
VALUE collision_shape,
|
|
184
|
+
VALUE local_inertia)
|
|
185
|
+
: local_inertia_(coerce_vector(Rice::Object(local_inertia))),
|
|
186
|
+
info_(std::make_unique<btRigidBody::btRigidBodyConstructionInfo>(
|
|
187
|
+
mass,
|
|
188
|
+
motion_state.get(),
|
|
189
|
+
coerce_collision_shape(Rice::Object(collision_shape)),
|
|
190
|
+
local_inertia_))
|
|
191
|
+
{
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
btRigidBody::btRigidBodyConstructionInfo& RigidBodyConstructionInfo::get()
|
|
195
|
+
{
|
|
196
|
+
return *info_;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
btScalar RigidBodyConstructionInfo::mass() const
|
|
200
|
+
{
|
|
201
|
+
return info_->m_mass;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
btVector3 RigidBodyConstructionInfo::local_inertia() const
|
|
205
|
+
{
|
|
206
|
+
return info_->m_localInertia;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
btScalar RigidBodyConstructionInfo::friction() const
|
|
210
|
+
{
|
|
211
|
+
return info_->m_friction;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
btScalar RigidBodyConstructionInfo::set_friction(btScalar friction)
|
|
215
|
+
{
|
|
216
|
+
info_->m_friction = friction;
|
|
217
|
+
return friction;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
btScalar RigidBodyConstructionInfo::restitution() const
|
|
221
|
+
{
|
|
222
|
+
return info_->m_restitution;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
btScalar RigidBodyConstructionInfo::set_restitution(btScalar restitution)
|
|
226
|
+
{
|
|
227
|
+
info_->m_restitution = restitution;
|
|
228
|
+
return restitution;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
RigidBody::RigidBody(RigidBodyConstructionInfo& construction_info)
|
|
232
|
+
: rigid_body_(std::make_unique<btRigidBody>(construction_info.get()))
|
|
233
|
+
{
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
btRigidBody* RigidBody::get()
|
|
237
|
+
{
|
|
238
|
+
return rigid_body_.get();
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const btRigidBody* RigidBody::get() const
|
|
242
|
+
{
|
|
243
|
+
return rigid_body_.get();
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
btScalar RigidBody::mass() const
|
|
247
|
+
{
|
|
248
|
+
btScalar inverse_mass = rigid_body_->getInvMass();
|
|
249
|
+
return inverse_mass == btScalar(0) ? btScalar(0) : btScalar(1) / inverse_mass;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
btCollisionShape* RigidBody::collision_shape() const
|
|
253
|
+
{
|
|
254
|
+
return rigid_body_->getCollisionShape();
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
Transform RigidBody::world_transform() const
|
|
258
|
+
{
|
|
259
|
+
btTransform transform;
|
|
260
|
+
if (rigid_body_->getMotionState() != nullptr) {
|
|
261
|
+
rigid_body_->getMotionState()->getWorldTransform(transform);
|
|
262
|
+
} else {
|
|
263
|
+
transform = rigid_body_->getWorldTransform();
|
|
264
|
+
}
|
|
265
|
+
return Transform(transform);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
Transform RigidBody::set_world_transform(Rice::Object transform)
|
|
269
|
+
{
|
|
270
|
+
btTransform value = coerce_transform(transform);
|
|
271
|
+
rigid_body_->setWorldTransform(value);
|
|
272
|
+
rigid_body_->setCenterOfMassTransform(value);
|
|
273
|
+
if (rigid_body_->getMotionState() != nullptr) {
|
|
274
|
+
rigid_body_->getMotionState()->setWorldTransform(value);
|
|
275
|
+
}
|
|
276
|
+
return Transform(value);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
btVector3 RigidBody::linear_velocity() const
|
|
280
|
+
{
|
|
281
|
+
return rigid_body_->getLinearVelocity();
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
btVector3 RigidBody::set_linear_velocity(Rice::Object velocity)
|
|
285
|
+
{
|
|
286
|
+
btVector3 vector = coerce_vector(velocity);
|
|
287
|
+
rigid_body_->setLinearVelocity(vector);
|
|
288
|
+
return vector;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
btVector3 RigidBody::angular_velocity() const
|
|
292
|
+
{
|
|
293
|
+
return rigid_body_->getAngularVelocity();
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
btVector3 RigidBody::set_angular_velocity(Rice::Object velocity)
|
|
297
|
+
{
|
|
298
|
+
btVector3 vector = coerce_vector(velocity);
|
|
299
|
+
rigid_body_->setAngularVelocity(vector);
|
|
300
|
+
return vector;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
btVector3 RigidBody::total_force() const
|
|
304
|
+
{
|
|
305
|
+
return rigid_body_->getTotalForce();
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
btVector3 RigidBody::total_torque() const
|
|
309
|
+
{
|
|
310
|
+
return rigid_body_->getTotalTorque();
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
btScalar RigidBody::friction() const
|
|
314
|
+
{
|
|
315
|
+
return rigid_body_->getFriction();
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
btScalar RigidBody::set_friction(btScalar friction)
|
|
319
|
+
{
|
|
320
|
+
rigid_body_->setFriction(friction);
|
|
321
|
+
return friction;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
btScalar RigidBody::restitution() const
|
|
325
|
+
{
|
|
326
|
+
return rigid_body_->getRestitution();
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
btScalar RigidBody::set_restitution(btScalar restitution)
|
|
330
|
+
{
|
|
331
|
+
rigid_body_->setRestitution(restitution);
|
|
332
|
+
return restitution;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
Rice::Array RigidBody::damping() const
|
|
336
|
+
{
|
|
337
|
+
Rice::Array array;
|
|
338
|
+
array.push(rigid_body_->getLinearDamping());
|
|
339
|
+
array.push(rigid_body_->getAngularDamping());
|
|
340
|
+
return array;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
Rice::Array RigidBody::set_damping(btScalar linear_damping, btScalar angular_damping)
|
|
344
|
+
{
|
|
345
|
+
rigid_body_->setDamping(linear_damping, angular_damping);
|
|
346
|
+
return damping();
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
void RigidBody::apply_central_force(Rice::Object force)
|
|
350
|
+
{
|
|
351
|
+
rigid_body_->applyCentralForce(coerce_vector(force));
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
void RigidBody::apply_force(Rice::Object force, Rice::Object relative_position)
|
|
355
|
+
{
|
|
356
|
+
rigid_body_->applyForce(coerce_vector(force), coerce_vector(relative_position));
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
void RigidBody::apply_torque(Rice::Object torque)
|
|
360
|
+
{
|
|
361
|
+
rigid_body_->applyTorque(coerce_vector(torque));
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
void RigidBody::apply_central_impulse(Rice::Object impulse)
|
|
365
|
+
{
|
|
366
|
+
rigid_body_->applyCentralImpulse(coerce_vector(impulse));
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
void RigidBody::apply_impulse(Rice::Object impulse, Rice::Object relative_position)
|
|
370
|
+
{
|
|
371
|
+
rigid_body_->applyImpulse(coerce_vector(impulse), coerce_vector(relative_position));
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
void RigidBody::clear_forces()
|
|
375
|
+
{
|
|
376
|
+
rigid_body_->clearForces();
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
void RigidBody::activate()
|
|
380
|
+
{
|
|
381
|
+
rigid_body_->activate(true);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
bool RigidBody::active() const
|
|
385
|
+
{
|
|
386
|
+
return rigid_body_->isActive();
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
bool RigidBody::static_object() const
|
|
390
|
+
{
|
|
391
|
+
return rigid_body_->isStaticObject();
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
bool RigidBody::kinematic_object() const
|
|
395
|
+
{
|
|
396
|
+
return rigid_body_->isKinematicObject();
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
DiscreteDynamicsWorld::DiscreteDynamicsWorld()
|
|
400
|
+
{
|
|
401
|
+
build_owned_world();
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
DiscreteDynamicsWorld::DiscreteDynamicsWorld(CollisionDispatcher& dispatcher,
|
|
405
|
+
DbvtBroadphase& broadphase,
|
|
406
|
+
SequentialImpulseConstraintSolver& solver,
|
|
407
|
+
CollisionConfiguration& configuration)
|
|
408
|
+
: world_(std::make_unique<btDiscreteDynamicsWorld>(
|
|
409
|
+
dispatcher.get(),
|
|
410
|
+
broadphase.get(),
|
|
411
|
+
solver.get(),
|
|
412
|
+
configuration.get()))
|
|
413
|
+
{
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
DiscreteDynamicsWorld::~DiscreteDynamicsWorld()
|
|
417
|
+
{
|
|
418
|
+
actions_.clear();
|
|
419
|
+
constraints_.clear();
|
|
420
|
+
rigid_bodies_.clear();
|
|
421
|
+
action_values_.clear();
|
|
422
|
+
constraint_values_.clear();
|
|
423
|
+
collision_object_values_.clear();
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
void DiscreteDynamicsWorld::build_owned_world()
|
|
427
|
+
{
|
|
428
|
+
owned_configuration_ = std::make_unique<btDefaultCollisionConfiguration>();
|
|
429
|
+
owned_dispatcher_ = std::make_unique<btCollisionDispatcher>(owned_configuration_.get());
|
|
430
|
+
owned_broadphase_ = std::make_unique<btDbvtBroadphase>();
|
|
431
|
+
owned_solver_ = std::make_unique<btSequentialImpulseConstraintSolver>();
|
|
432
|
+
world_ = std::make_unique<btDiscreteDynamicsWorld>(
|
|
433
|
+
owned_dispatcher_.get(),
|
|
434
|
+
owned_broadphase_.get(),
|
|
435
|
+
owned_solver_.get(),
|
|
436
|
+
owned_configuration_.get());
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
btDiscreteDynamicsWorld* DiscreteDynamicsWorld::get()
|
|
440
|
+
{
|
|
441
|
+
return world_.get();
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
btVector3 DiscreteDynamicsWorld::gravity() const
|
|
445
|
+
{
|
|
446
|
+
return world_->getGravity();
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
btVector3 DiscreteDynamicsWorld::set_gravity(Rice::Object gravity)
|
|
450
|
+
{
|
|
451
|
+
btVector3 vector = coerce_vector(gravity);
|
|
452
|
+
world_->setGravity(vector);
|
|
453
|
+
return vector;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
void DiscreteDynamicsWorld::add_rigid_body(RigidBody& rigid_body)
|
|
457
|
+
{
|
|
458
|
+
btRigidBody* body = rigid_body.get();
|
|
459
|
+
if (rigid_bodies_.insert(body).second) {
|
|
460
|
+
world_->addRigidBody(body);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
void DiscreteDynamicsWorld::add_rigid_body_object(VALUE rigid_body)
|
|
465
|
+
{
|
|
466
|
+
RigidBody* body = Rice::detail::From_Ruby<RigidBody*>().convert(rigid_body);
|
|
467
|
+
add_rigid_body(*body);
|
|
468
|
+
collision_object_values_[body->get()] = rigid_body;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
void DiscreteDynamicsWorld::remove_rigid_body(RigidBody& rigid_body)
|
|
472
|
+
{
|
|
473
|
+
btRigidBody* body = rigid_body.get();
|
|
474
|
+
auto iterator = rigid_bodies_.find(body);
|
|
475
|
+
if (iterator != rigid_bodies_.end()) {
|
|
476
|
+
world_->removeRigidBody(body);
|
|
477
|
+
rigid_bodies_.erase(iterator);
|
|
478
|
+
}
|
|
479
|
+
collision_object_values_.erase(body);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
void DiscreteDynamicsWorld::remove_rigid_body_object(VALUE rigid_body)
|
|
483
|
+
{
|
|
484
|
+
RigidBody* body = Rice::detail::From_Ruby<RigidBody*>().convert(rigid_body);
|
|
485
|
+
remove_rigid_body(*body);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
void DiscreteDynamicsWorld::add_constraint_object(VALUE constraint, bool disable_collisions_between_linked_bodies)
|
|
489
|
+
{
|
|
490
|
+
TypedConstraint* typed_constraint = Rice::detail::From_Ruby<TypedConstraint*>().convert(constraint);
|
|
491
|
+
if (typed_constraint == nullptr) {
|
|
492
|
+
throw std::invalid_argument("expected Bullet3::Constraints::TypedConstraint");
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
btTypedConstraint* bullet_constraint = typed_constraint->get();
|
|
496
|
+
if (constraints_.insert(bullet_constraint).second) {
|
|
497
|
+
world_->addConstraint(bullet_constraint, disable_collisions_between_linked_bodies);
|
|
498
|
+
constraint_values_[bullet_constraint] = constraint;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
void DiscreteDynamicsWorld::remove_constraint_object(VALUE constraint)
|
|
503
|
+
{
|
|
504
|
+
TypedConstraint* typed_constraint = Rice::detail::From_Ruby<TypedConstraint*>().convert(constraint);
|
|
505
|
+
if (typed_constraint == nullptr) {
|
|
506
|
+
throw std::invalid_argument("expected Bullet3::Constraints::TypedConstraint");
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
btTypedConstraint* bullet_constraint = typed_constraint->get();
|
|
510
|
+
auto iterator = constraints_.find(bullet_constraint);
|
|
511
|
+
if (iterator != constraints_.end()) {
|
|
512
|
+
world_->removeConstraint(bullet_constraint);
|
|
513
|
+
constraints_.erase(iterator);
|
|
514
|
+
}
|
|
515
|
+
constraint_values_.erase(bullet_constraint);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
void DiscreteDynamicsWorld::add_vehicle_object(VALUE vehicle)
|
|
519
|
+
{
|
|
520
|
+
RaycastVehicle* raycast_vehicle = Rice::detail::From_Ruby<RaycastVehicle*>().convert(vehicle);
|
|
521
|
+
if (raycast_vehicle == nullptr) {
|
|
522
|
+
throw std::invalid_argument("expected Bullet3::RaycastVehicle");
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
btRaycastVehicle* bullet_vehicle = raycast_vehicle->get();
|
|
526
|
+
if (actions_.insert(bullet_vehicle).second) {
|
|
527
|
+
world_->addAction(bullet_vehicle);
|
|
528
|
+
action_values_[bullet_vehicle] = vehicle;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
void DiscreteDynamicsWorld::remove_vehicle_object(VALUE vehicle)
|
|
533
|
+
{
|
|
534
|
+
RaycastVehicle* raycast_vehicle = Rice::detail::From_Ruby<RaycastVehicle*>().convert(vehicle);
|
|
535
|
+
if (raycast_vehicle == nullptr) {
|
|
536
|
+
throw std::invalid_argument("expected Bullet3::RaycastVehicle");
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
btRaycastVehicle* bullet_vehicle = raycast_vehicle->get();
|
|
540
|
+
auto iterator = actions_.find(bullet_vehicle);
|
|
541
|
+
if (iterator != actions_.end()) {
|
|
542
|
+
world_->removeAction(bullet_vehicle);
|
|
543
|
+
actions_.erase(iterator);
|
|
544
|
+
}
|
|
545
|
+
action_values_.erase(bullet_vehicle);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
int DiscreteDynamicsWorld::step_simulation(btScalar time_step, int max_sub_steps, btScalar fixed_time_step)
|
|
549
|
+
{
|
|
550
|
+
StepSimulationArgs args{world_.get(), time_step, max_sub_steps, fixed_time_step, 0};
|
|
551
|
+
rb_thread_call_without_gvl(step_simulation_without_gvl, &args, nullptr, nullptr);
|
|
552
|
+
return args.result;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
int DiscreteDynamicsWorld::num_collision_objects() const
|
|
556
|
+
{
|
|
557
|
+
return world_->getNumCollisionObjects();
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
int DiscreteDynamicsWorld::num_constraints() const
|
|
561
|
+
{
|
|
562
|
+
return world_->getNumConstraints();
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
void DiscreteDynamicsWorld::clear_forces()
|
|
566
|
+
{
|
|
567
|
+
world_->clearForces();
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
void DiscreteDynamicsWorld::synchronize_motion_states()
|
|
571
|
+
{
|
|
572
|
+
world_->synchronizeMotionStates();
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
VALUE DiscreteDynamicsWorld::ruby_object_for(const btCollisionObject* collision_object) const
|
|
576
|
+
{
|
|
577
|
+
auto iterator = collision_object_values_.find(collision_object);
|
|
578
|
+
if (iterator == collision_object_values_.end()) {
|
|
579
|
+
return Qnil;
|
|
580
|
+
}
|
|
581
|
+
return iterator->second;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
Rice::Object DiscreteDynamicsWorld::ray_test_closest(Rice::Object from, Rice::Object to) const
|
|
585
|
+
{
|
|
586
|
+
btVector3 ray_from = coerce_vector(from);
|
|
587
|
+
btVector3 ray_to = coerce_vector(to);
|
|
588
|
+
btCollisionWorld::ClosestRayResultCallback callback(ray_from, ray_to);
|
|
589
|
+
world_->rayTest(ray_from, ray_to, callback);
|
|
590
|
+
|
|
591
|
+
if (!callback.hasHit()) {
|
|
592
|
+
return Rice::Object(Qnil);
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
Rice::Hash hit;
|
|
596
|
+
hit[Rice::Symbol("body")] = Rice::Object(ruby_object_for(callback.m_collisionObject));
|
|
597
|
+
hit[Rice::Symbol("fraction")] = callback.m_closestHitFraction;
|
|
598
|
+
set_vector_hash_value(hit, "point", callback.m_hitPointWorld);
|
|
599
|
+
set_vector_hash_value(hit, "normal", callback.m_hitNormalWorld);
|
|
600
|
+
return hit;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
Rice::Array DiscreteDynamicsWorld::ray_test_all(Rice::Object from, Rice::Object to) const
|
|
604
|
+
{
|
|
605
|
+
btVector3 ray_from = coerce_vector(from);
|
|
606
|
+
btVector3 ray_to = coerce_vector(to);
|
|
607
|
+
btCollisionWorld::AllHitsRayResultCallback callback(ray_from, ray_to);
|
|
608
|
+
world_->rayTest(ray_from, ray_to, callback);
|
|
609
|
+
|
|
610
|
+
Rice::Array hits;
|
|
611
|
+
for (int index = 0; index < callback.m_collisionObjects.size(); ++index) {
|
|
612
|
+
Rice::Hash hit;
|
|
613
|
+
hit[Rice::Symbol("body")] = Rice::Object(ruby_object_for(callback.m_collisionObjects[index]));
|
|
614
|
+
hit[Rice::Symbol("fraction")] = callback.m_hitFractions[index];
|
|
615
|
+
set_vector_hash_value(hit, "point", callback.m_hitPointWorld[index]);
|
|
616
|
+
set_vector_hash_value(hit, "normal", callback.m_hitNormalWorld[index]);
|
|
617
|
+
hits.push(hit);
|
|
618
|
+
}
|
|
619
|
+
return hits;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
Rice::Array DiscreteDynamicsWorld::contact_test(VALUE rigid_body) const
|
|
623
|
+
{
|
|
624
|
+
RigidBody* body = rigid_body_from_value(rigid_body);
|
|
625
|
+
ContactCollector callback([this](const btCollisionObject* collision_object) {
|
|
626
|
+
return ruby_object_for(collision_object);
|
|
627
|
+
});
|
|
628
|
+
world_->contactTest(body->get(), callback);
|
|
629
|
+
return callback.contacts;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
Rice::Array DiscreteDynamicsWorld::contact_pair_test(VALUE rigid_body_a, VALUE rigid_body_b) const
|
|
633
|
+
{
|
|
634
|
+
RigidBody* body_a = rigid_body_from_value(rigid_body_a);
|
|
635
|
+
RigidBody* body_b = rigid_body_from_value(rigid_body_b);
|
|
636
|
+
ContactCollector callback([this](const btCollisionObject* collision_object) {
|
|
637
|
+
return ruby_object_for(collision_object);
|
|
638
|
+
});
|
|
639
|
+
world_->contactPairTest(body_a->get(), body_b->get(), callback);
|
|
640
|
+
return callback.contacts;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
Rice::Array DiscreteDynamicsWorld::closest_points(VALUE rigid_body_a, VALUE rigid_body_b, btScalar distance_threshold) const
|
|
644
|
+
{
|
|
645
|
+
RigidBody* body_a = rigid_body_from_value(rigid_body_a);
|
|
646
|
+
RigidBody* body_b = rigid_body_from_value(rigid_body_b);
|
|
647
|
+
ContactCollector callback([this](const btCollisionObject* collision_object) {
|
|
648
|
+
return ruby_object_for(collision_object);
|
|
649
|
+
});
|
|
650
|
+
callback.m_closestDistanceThreshold = distance_threshold;
|
|
651
|
+
world_->contactPairTest(body_a->get(), body_b->get(), callback);
|
|
652
|
+
return callback.contacts;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
Rice::Array DiscreteDynamicsWorld::contact_manifolds() const
|
|
656
|
+
{
|
|
657
|
+
Rice::Array manifolds;
|
|
658
|
+
btDispatcher* dispatcher = world_->getDispatcher();
|
|
659
|
+
int manifold_count = dispatcher->getNumManifolds();
|
|
660
|
+
|
|
661
|
+
for (int manifold_index = 0; manifold_index < manifold_count; ++manifold_index) {
|
|
662
|
+
btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(manifold_index);
|
|
663
|
+
Rice::Hash manifold_hash;
|
|
664
|
+
manifold_hash[Rice::Symbol("body0")] = Rice::Object(ruby_object_for(static_cast<const btCollisionObject*>(manifold->getBody0())));
|
|
665
|
+
manifold_hash[Rice::Symbol("body1")] = Rice::Object(ruby_object_for(static_cast<const btCollisionObject*>(manifold->getBody1())));
|
|
666
|
+
|
|
667
|
+
Rice::Array points;
|
|
668
|
+
for (int point_index = 0; point_index < manifold->getNumContacts(); ++point_index) {
|
|
669
|
+
const btManifoldPoint& point = manifold->getContactPoint(point_index);
|
|
670
|
+
Rice::Hash point_hash;
|
|
671
|
+
set_vector_hash_value(point_hash, "position_world_on_a", point.getPositionWorldOnA());
|
|
672
|
+
set_vector_hash_value(point_hash, "position_world_on_b", point.getPositionWorldOnB());
|
|
673
|
+
set_vector_hash_value(point_hash, "normal_world_on_b", point.m_normalWorldOnB);
|
|
674
|
+
point_hash[Rice::Symbol("distance")] = point.getDistance();
|
|
675
|
+
point_hash[Rice::Symbol("life_time")] = point.getLifeTime();
|
|
676
|
+
points.push(point_hash);
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
manifold_hash[Rice::Symbol("points")] = points;
|
|
680
|
+
manifolds.push(manifold_hash);
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
return manifolds;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
void DiscreteDynamicsWorld::set_debug_drawer(VALUE debug_drawer)
|
|
687
|
+
{
|
|
688
|
+
DebugDraw* drawer = Rice::detail::From_Ruby<DebugDraw*>().convert(debug_drawer);
|
|
689
|
+
if (drawer == nullptr) {
|
|
690
|
+
throw std::invalid_argument("expected Bullet3::DebugDraw");
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
debug_drawer_value_ = debug_drawer;
|
|
694
|
+
world_->setDebugDrawer(drawer->get());
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
VALUE DiscreteDynamicsWorld::debug_drawer() const
|
|
698
|
+
{
|
|
699
|
+
return debug_drawer_value_;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
void DiscreteDynamicsWorld::debug_draw_world()
|
|
703
|
+
{
|
|
704
|
+
world_->debugDrawWorld();
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
void DiscreteDynamicsWorld::mark() const
|
|
708
|
+
{
|
|
709
|
+
for (const auto& entry : collision_object_values_) {
|
|
710
|
+
rb_gc_mark(entry.second);
|
|
711
|
+
}
|
|
712
|
+
for (const auto& entry : constraint_values_) {
|
|
713
|
+
rb_gc_mark(entry.second);
|
|
714
|
+
}
|
|
715
|
+
for (const auto& entry : action_values_) {
|
|
716
|
+
rb_gc_mark(entry.second);
|
|
717
|
+
}
|
|
718
|
+
rb_gc_mark(debug_drawer_value_);
|
|
719
|
+
}
|
|
720
|
+
} // namespace bullet3
|
|
721
|
+
|
|
722
|
+
namespace Rice {
|
|
723
|
+
template <>
|
|
724
|
+
void ruby_mark<bullet3::DiscreteDynamicsWorld>(bullet3::DiscreteDynamicsWorld* world)
|
|
725
|
+
{
|
|
726
|
+
if (world != nullptr) {
|
|
727
|
+
world->mark();
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
} // namespace Rice
|
|
731
|
+
|
|
732
|
+
void Init_Dynamics(Rice::Module rb_mBullet)
|
|
733
|
+
{
|
|
734
|
+
Rice::define_class_under<bullet3::CollisionConfiguration>(rb_mBullet, "CollisionConfiguration")
|
|
735
|
+
.define_constructor(Rice::Constructor<bullet3::CollisionConfiguration>());
|
|
736
|
+
|
|
737
|
+
Rice::define_class_under<bullet3::CollisionDispatcher>(rb_mBullet, "CollisionDispatcher")
|
|
738
|
+
.define_constructor(Rice::Constructor<bullet3::CollisionDispatcher, bullet3::CollisionConfiguration&>(),
|
|
739
|
+
Rice::Arg("configuration").keepAlive());
|
|
740
|
+
|
|
741
|
+
Rice::define_class_under<bullet3::DbvtBroadphase>(rb_mBullet, "DbvtBroadphase")
|
|
742
|
+
.define_constructor(Rice::Constructor<bullet3::DbvtBroadphase>());
|
|
743
|
+
|
|
744
|
+
Rice::define_class_under<bullet3::SequentialImpulseConstraintSolver>(rb_mBullet, "SequentialImpulseConstraintSolver")
|
|
745
|
+
.define_constructor(Rice::Constructor<bullet3::SequentialImpulseConstraintSolver>());
|
|
746
|
+
|
|
747
|
+
Rice::define_class_under<bullet3::MotionState>(rb_mBullet, "MotionState")
|
|
748
|
+
.define_constructor(Rice::Constructor<bullet3::MotionState>())
|
|
749
|
+
.define_constructor(Rice::Constructor<bullet3::MotionState, VALUE>(),
|
|
750
|
+
Rice::Arg("start_transform").setValue())
|
|
751
|
+
.define_method("world_transform", &bullet3::MotionState::world_transform)
|
|
752
|
+
.define_method("world_transform=", &bullet3::MotionState::set_world_transform);
|
|
753
|
+
|
|
754
|
+
Rice::define_class_under<bullet3::RigidBodyConstructionInfo>(rb_mBullet, "RigidBodyConstructionInfo")
|
|
755
|
+
.define_constructor(Rice::Constructor<bullet3::RigidBodyConstructionInfo,
|
|
756
|
+
btScalar,
|
|
757
|
+
bullet3::MotionState&,
|
|
758
|
+
VALUE>(),
|
|
759
|
+
Rice::Arg("mass"),
|
|
760
|
+
Rice::Arg("motion_state").keepAlive(),
|
|
761
|
+
Rice::Arg("collision_shape").setValue().keepAlive())
|
|
762
|
+
.define_constructor(Rice::Constructor<bullet3::RigidBodyConstructionInfo,
|
|
763
|
+
btScalar,
|
|
764
|
+
bullet3::MotionState&,
|
|
765
|
+
VALUE,
|
|
766
|
+
VALUE>(),
|
|
767
|
+
Rice::Arg("mass"),
|
|
768
|
+
Rice::Arg("motion_state").keepAlive(),
|
|
769
|
+
Rice::Arg("collision_shape").setValue().keepAlive(),
|
|
770
|
+
Rice::Arg("local_inertia").setValue())
|
|
771
|
+
.define_method("mass", &bullet3::RigidBodyConstructionInfo::mass)
|
|
772
|
+
.define_method("local_inertia", &bullet3::RigidBodyConstructionInfo::local_inertia)
|
|
773
|
+
.define_method("friction", &bullet3::RigidBodyConstructionInfo::friction)
|
|
774
|
+
.define_method("friction=", &bullet3::RigidBodyConstructionInfo::set_friction)
|
|
775
|
+
.define_method("restitution", &bullet3::RigidBodyConstructionInfo::restitution)
|
|
776
|
+
.define_method("restitution=", &bullet3::RigidBodyConstructionInfo::set_restitution);
|
|
777
|
+
|
|
778
|
+
Rice::define_class_under<bullet3::RigidBody>(rb_mBullet, "RigidBody")
|
|
779
|
+
.define_constructor(Rice::Constructor<bullet3::RigidBody, bullet3::RigidBodyConstructionInfo&>(),
|
|
780
|
+
Rice::Arg("construction_info").keepAlive())
|
|
781
|
+
.define_method("mass", &bullet3::RigidBody::mass)
|
|
782
|
+
.define_method("collision_shape", &bullet3::RigidBody::collision_shape)
|
|
783
|
+
.define_method("world_transform", &bullet3::RigidBody::world_transform)
|
|
784
|
+
.define_method("world_transform=", &bullet3::RigidBody::set_world_transform)
|
|
785
|
+
.define_method("linear_velocity", &bullet3::RigidBody::linear_velocity)
|
|
786
|
+
.define_method("linear_velocity=", &bullet3::RigidBody::set_linear_velocity)
|
|
787
|
+
.define_method("angular_velocity", &bullet3::RigidBody::angular_velocity)
|
|
788
|
+
.define_method("angular_velocity=", &bullet3::RigidBody::set_angular_velocity)
|
|
789
|
+
.define_method("total_force", &bullet3::RigidBody::total_force)
|
|
790
|
+
.define_method("total_torque", &bullet3::RigidBody::total_torque)
|
|
791
|
+
.define_method("friction", &bullet3::RigidBody::friction)
|
|
792
|
+
.define_method("friction=", &bullet3::RigidBody::set_friction)
|
|
793
|
+
.define_method("restitution", &bullet3::RigidBody::restitution)
|
|
794
|
+
.define_method("restitution=", &bullet3::RigidBody::set_restitution)
|
|
795
|
+
.define_method("damping", &bullet3::RigidBody::damping)
|
|
796
|
+
.define_method("set_damping", &bullet3::RigidBody::set_damping)
|
|
797
|
+
.define_method("apply_central_force", &bullet3::RigidBody::apply_central_force)
|
|
798
|
+
.define_method("apply_force", &bullet3::RigidBody::apply_force)
|
|
799
|
+
.define_method("apply_torque", &bullet3::RigidBody::apply_torque)
|
|
800
|
+
.define_method("apply_central_impulse", &bullet3::RigidBody::apply_central_impulse)
|
|
801
|
+
.define_method("apply_impulse", &bullet3::RigidBody::apply_impulse)
|
|
802
|
+
.define_method("clear_forces", &bullet3::RigidBody::clear_forces)
|
|
803
|
+
.define_method("activate", &bullet3::RigidBody::activate)
|
|
804
|
+
.define_method("active?", &bullet3::RigidBody::active)
|
|
805
|
+
.define_method("static?", &bullet3::RigidBody::static_object)
|
|
806
|
+
.define_method("kinematic?", &bullet3::RigidBody::kinematic_object);
|
|
807
|
+
|
|
808
|
+
Rice::define_class_under<bullet3::DiscreteDynamicsWorld>(rb_mBullet, "DiscreteDynamicsWorld")
|
|
809
|
+
.define_constructor(Rice::Constructor<bullet3::DiscreteDynamicsWorld>())
|
|
810
|
+
.define_constructor(Rice::Constructor<bullet3::DiscreteDynamicsWorld,
|
|
811
|
+
bullet3::CollisionDispatcher&,
|
|
812
|
+
bullet3::DbvtBroadphase&,
|
|
813
|
+
bullet3::SequentialImpulseConstraintSolver&,
|
|
814
|
+
bullet3::CollisionConfiguration&>(),
|
|
815
|
+
Rice::Arg("dispatcher").keepAlive(),
|
|
816
|
+
Rice::Arg("broadphase").keepAlive(),
|
|
817
|
+
Rice::Arg("solver").keepAlive(),
|
|
818
|
+
Rice::Arg("configuration").keepAlive())
|
|
819
|
+
.define_singleton_method("create", [](Rice::Object) -> bullet3::DiscreteDynamicsWorld* {
|
|
820
|
+
return new bullet3::DiscreteDynamicsWorld();
|
|
821
|
+
}, Rice::Return().takeOwnership())
|
|
822
|
+
.define_method("gravity", &bullet3::DiscreteDynamicsWorld::gravity)
|
|
823
|
+
.define_method("gravity=", &bullet3::DiscreteDynamicsWorld::set_gravity)
|
|
824
|
+
.define_method("add_rigid_body", &bullet3::DiscreteDynamicsWorld::add_rigid_body_object,
|
|
825
|
+
Rice::Arg("rigid_body").setValue().keepAlive())
|
|
826
|
+
.define_method("remove_rigid_body", &bullet3::DiscreteDynamicsWorld::remove_rigid_body_object,
|
|
827
|
+
Rice::Arg("rigid_body").setValue())
|
|
828
|
+
.define_method("add_constraint", &bullet3::DiscreteDynamicsWorld::add_constraint_object,
|
|
829
|
+
Rice::Arg("constraint").setValue().keepAlive(),
|
|
830
|
+
Rice::Arg("disable_collisions_between_linked_bodies") = false)
|
|
831
|
+
.define_method("remove_constraint", &bullet3::DiscreteDynamicsWorld::remove_constraint_object,
|
|
832
|
+
Rice::Arg("constraint").setValue())
|
|
833
|
+
.define_method("add_vehicle", &bullet3::DiscreteDynamicsWorld::add_vehicle_object,
|
|
834
|
+
Rice::Arg("vehicle").setValue().keepAlive())
|
|
835
|
+
.define_method("remove_vehicle", &bullet3::DiscreteDynamicsWorld::remove_vehicle_object,
|
|
836
|
+
Rice::Arg("vehicle").setValue())
|
|
837
|
+
.define_method("step_simulation", &bullet3::DiscreteDynamicsWorld::step_simulation,
|
|
838
|
+
Rice::Arg("time_step"),
|
|
839
|
+
Rice::Arg("max_sub_steps") = 1,
|
|
840
|
+
Rice::Arg("fixed_time_step") = btScalar(1.0 / 60.0))
|
|
841
|
+
.define_method("num_collision_objects", &bullet3::DiscreteDynamicsWorld::num_collision_objects)
|
|
842
|
+
.define_method("num_constraints", &bullet3::DiscreteDynamicsWorld::num_constraints)
|
|
843
|
+
.define_method("clear_forces", &bullet3::DiscreteDynamicsWorld::clear_forces)
|
|
844
|
+
.define_method("synchronize_motion_states", &bullet3::DiscreteDynamicsWorld::synchronize_motion_states)
|
|
845
|
+
.define_method("ray_test_closest", &bullet3::DiscreteDynamicsWorld::ray_test_closest)
|
|
846
|
+
.define_method("ray_test", &bullet3::DiscreteDynamicsWorld::ray_test_closest)
|
|
847
|
+
.define_method("ray_test_all", &bullet3::DiscreteDynamicsWorld::ray_test_all)
|
|
848
|
+
.define_method("contact_test", &bullet3::DiscreteDynamicsWorld::contact_test,
|
|
849
|
+
Rice::Arg("rigid_body").setValue())
|
|
850
|
+
.define_method("contact_pair_test", &bullet3::DiscreteDynamicsWorld::contact_pair_test,
|
|
851
|
+
Rice::Arg("rigid_body_a").setValue(),
|
|
852
|
+
Rice::Arg("rigid_body_b").setValue())
|
|
853
|
+
.define_method("closest_points", &bullet3::DiscreteDynamicsWorld::closest_points,
|
|
854
|
+
Rice::Arg("rigid_body_a").setValue(),
|
|
855
|
+
Rice::Arg("rigid_body_b").setValue(),
|
|
856
|
+
Rice::Arg("distance_threshold") = btScalar(0.0))
|
|
857
|
+
.define_method("contact_manifolds", &bullet3::DiscreteDynamicsWorld::contact_manifolds)
|
|
858
|
+
.define_method("debug_drawer", &bullet3::DiscreteDynamicsWorld::debug_drawer)
|
|
859
|
+
.define_method("debug_drawer=", &bullet3::DiscreteDynamicsWorld::set_debug_drawer,
|
|
860
|
+
Rice::Arg("debug_drawer").setValue().keepAlive())
|
|
861
|
+
.define_method("debug_draw_world", &bullet3::DiscreteDynamicsWorld::debug_draw_world);
|
|
862
|
+
}
|