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,720 @@
|
|
|
1
|
+
#include "rb_soft_body.hpp"
|
|
2
|
+
|
|
3
|
+
#include <stdexcept>
|
|
4
|
+
#include <vector>
|
|
5
|
+
|
|
6
|
+
#include <ruby/thread.h>
|
|
7
|
+
|
|
8
|
+
#include "../util/type_conversions.hpp"
|
|
9
|
+
|
|
10
|
+
namespace {
|
|
11
|
+
bullet3::RigidBody* rigid_body_from_value(VALUE value)
|
|
12
|
+
{
|
|
13
|
+
bullet3::RigidBody* body = Rice::detail::From_Ruby<bullet3::RigidBody*>().convert(value);
|
|
14
|
+
if (body == nullptr) {
|
|
15
|
+
throw std::invalid_argument("expected Bullet3::RigidBody");
|
|
16
|
+
}
|
|
17
|
+
return body;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
bullet3::SoftBody* soft_body_from_value(VALUE value)
|
|
21
|
+
{
|
|
22
|
+
bullet3::SoftBody* body = Rice::detail::From_Ruby<bullet3::SoftBody*>().convert(value);
|
|
23
|
+
if (body == nullptr) {
|
|
24
|
+
throw std::invalid_argument("expected Bullet3::SoftBody::SoftBody");
|
|
25
|
+
}
|
|
26
|
+
return body;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
Rice::Object vector_object(const btVector3& vector)
|
|
30
|
+
{
|
|
31
|
+
return Rice::Object(Rice::detail::To_Ruby<btVector3>().convert(btVector3(vector)));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
Rice::Symbol soft_body_feature_symbol(btSoftBody::eFeature::_ feature)
|
|
35
|
+
{
|
|
36
|
+
switch (feature) {
|
|
37
|
+
case btSoftBody::eFeature::Node:
|
|
38
|
+
return Rice::Symbol("node");
|
|
39
|
+
case btSoftBody::eFeature::Link:
|
|
40
|
+
return Rice::Symbol("link");
|
|
41
|
+
case btSoftBody::eFeature::Face:
|
|
42
|
+
return Rice::Symbol("face");
|
|
43
|
+
case btSoftBody::eFeature::Tetra:
|
|
44
|
+
return Rice::Symbol("tetra");
|
|
45
|
+
case btSoftBody::eFeature::None:
|
|
46
|
+
default:
|
|
47
|
+
return Rice::Symbol("none");
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
std::vector<btVector3> vector_array_from_object(Rice::Object object)
|
|
52
|
+
{
|
|
53
|
+
Rice::Array array = bullet3::array_from_object(object);
|
|
54
|
+
std::vector<btVector3> vectors;
|
|
55
|
+
vectors.reserve(array.size());
|
|
56
|
+
for (long index = 0; index < array.size(); ++index) {
|
|
57
|
+
vectors.push_back(bullet3::coerce_vector(Rice::Object(array[index])));
|
|
58
|
+
}
|
|
59
|
+
return vectors;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
std::vector<btScalar> flat_vertices_from_object(Rice::Object object)
|
|
63
|
+
{
|
|
64
|
+
std::vector<btVector3> vectors = vector_array_from_object(object);
|
|
65
|
+
std::vector<btScalar> flat_vertices;
|
|
66
|
+
flat_vertices.reserve(vectors.size() * 3);
|
|
67
|
+
for (const btVector3& vector : vectors) {
|
|
68
|
+
flat_vertices.push_back(vector.getX());
|
|
69
|
+
flat_vertices.push_back(vector.getY());
|
|
70
|
+
flat_vertices.push_back(vector.getZ());
|
|
71
|
+
}
|
|
72
|
+
return flat_vertices;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
std::vector<int> triangle_indices_from_object(Rice::Object object)
|
|
76
|
+
{
|
|
77
|
+
Rice::Array array = bullet3::array_from_object(object);
|
|
78
|
+
std::vector<int> indices;
|
|
79
|
+
indices.reserve(array.size() * 3);
|
|
80
|
+
for (long index = 0; index < array.size(); ++index) {
|
|
81
|
+
Rice::Object item(array[index]);
|
|
82
|
+
if (rb_obj_is_kind_of(item.value(), rb_cArray) || bullet3::object_responds_to(item, "to_a")) {
|
|
83
|
+
Rice::Array triangle = bullet3::array_from_object(item);
|
|
84
|
+
if (triangle.size() != 3) {
|
|
85
|
+
throw std::invalid_argument("triangle indices must have 3 elements");
|
|
86
|
+
}
|
|
87
|
+
indices.push_back(Rice::detail::From_Ruby<int>().convert(triangle[0]));
|
|
88
|
+
indices.push_back(Rice::detail::From_Ruby<int>().convert(triangle[1]));
|
|
89
|
+
indices.push_back(Rice::detail::From_Ruby<int>().convert(triangle[2]));
|
|
90
|
+
} else {
|
|
91
|
+
indices.push_back(Rice::detail::From_Ruby<int>().convert(item));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (indices.size() % 3 != 0) {
|
|
96
|
+
throw std::invalid_argument("triangle index count must be a multiple of 3");
|
|
97
|
+
}
|
|
98
|
+
return indices;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
struct StepSimulationArgs {
|
|
102
|
+
btSoftRigidDynamicsWorld* world;
|
|
103
|
+
btScalar time_step;
|
|
104
|
+
int max_sub_steps;
|
|
105
|
+
btScalar fixed_time_step;
|
|
106
|
+
int result;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
void* step_simulation_without_gvl(void* pointer)
|
|
110
|
+
{
|
|
111
|
+
auto* args = static_cast<StepSimulationArgs*>(pointer);
|
|
112
|
+
args->result = args->world->stepSimulation(args->time_step, args->max_sub_steps, args->fixed_time_step);
|
|
113
|
+
return nullptr;
|
|
114
|
+
}
|
|
115
|
+
} // namespace
|
|
116
|
+
|
|
117
|
+
namespace bullet3 {
|
|
118
|
+
SoftBodyWorldInfo::SoftBodyWorldInfo()
|
|
119
|
+
: owned_world_info_(std::make_unique<btSoftBodyWorldInfo>()),
|
|
120
|
+
world_info_(owned_world_info_.get())
|
|
121
|
+
{
|
|
122
|
+
world_info_->m_sparsesdf.Initialize();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
SoftBodyWorldInfo::SoftBodyWorldInfo(btSoftBodyWorldInfo* world_info)
|
|
126
|
+
: world_info_(world_info)
|
|
127
|
+
{
|
|
128
|
+
if (world_info_ == nullptr) {
|
|
129
|
+
throw std::invalid_argument("expected btSoftBodyWorldInfo");
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
btSoftBodyWorldInfo& SoftBodyWorldInfo::get()
|
|
134
|
+
{
|
|
135
|
+
return *world_info_;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const btSoftBodyWorldInfo& SoftBodyWorldInfo::get() const
|
|
139
|
+
{
|
|
140
|
+
return *world_info_;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
btVector3 SoftBodyWorldInfo::gravity() const
|
|
144
|
+
{
|
|
145
|
+
return world_info_->m_gravity;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
btVector3 SoftBodyWorldInfo::set_gravity(Rice::Object gravity)
|
|
149
|
+
{
|
|
150
|
+
btVector3 vector = coerce_vector(gravity);
|
|
151
|
+
world_info_->m_gravity = vector;
|
|
152
|
+
return vector;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
btScalar SoftBodyWorldInfo::air_density() const
|
|
156
|
+
{
|
|
157
|
+
return world_info_->air_density;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
btScalar SoftBodyWorldInfo::set_air_density(btScalar value)
|
|
161
|
+
{
|
|
162
|
+
world_info_->air_density = value;
|
|
163
|
+
return value;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
btScalar SoftBodyWorldInfo::water_density() const
|
|
167
|
+
{
|
|
168
|
+
return world_info_->water_density;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
btScalar SoftBodyWorldInfo::set_water_density(btScalar value)
|
|
172
|
+
{
|
|
173
|
+
world_info_->water_density = value;
|
|
174
|
+
return value;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
btScalar SoftBodyWorldInfo::water_offset() const
|
|
178
|
+
{
|
|
179
|
+
return world_info_->water_offset;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
btScalar SoftBodyWorldInfo::set_water_offset(btScalar value)
|
|
183
|
+
{
|
|
184
|
+
world_info_->water_offset = value;
|
|
185
|
+
return value;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
btVector3 SoftBodyWorldInfo::water_normal() const
|
|
189
|
+
{
|
|
190
|
+
return world_info_->water_normal;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
btVector3 SoftBodyWorldInfo::set_water_normal(Rice::Object normal)
|
|
194
|
+
{
|
|
195
|
+
btVector3 vector = coerce_vector(normal);
|
|
196
|
+
world_info_->water_normal = vector;
|
|
197
|
+
return vector;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
btScalar SoftBodyWorldInfo::max_displacement() const
|
|
201
|
+
{
|
|
202
|
+
return world_info_->m_maxDisplacement;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
btScalar SoftBodyWorldInfo::set_max_displacement(btScalar value)
|
|
206
|
+
{
|
|
207
|
+
world_info_->m_maxDisplacement = value;
|
|
208
|
+
return value;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
void SoftBodyWorldInfo::reset_sparse_sdf()
|
|
212
|
+
{
|
|
213
|
+
world_info_->m_sparsesdf.Reset();
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
SoftBody::SoftBody(btSoftBody* soft_body)
|
|
217
|
+
: soft_body_(soft_body)
|
|
218
|
+
{
|
|
219
|
+
if (soft_body_ == nullptr) {
|
|
220
|
+
throw std::invalid_argument("expected btSoftBody");
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
btSoftBody* SoftBody::get()
|
|
225
|
+
{
|
|
226
|
+
return soft_body_.get();
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const btSoftBody* SoftBody::get() const
|
|
230
|
+
{
|
|
231
|
+
return soft_body_.get();
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
int SoftBody::validate_node_index(int index) const
|
|
235
|
+
{
|
|
236
|
+
if (index < 0 || index >= soft_body_->m_nodes.size()) {
|
|
237
|
+
throw std::out_of_range("node index is out of range");
|
|
238
|
+
}
|
|
239
|
+
return index;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
int SoftBody::node_count() const
|
|
243
|
+
{
|
|
244
|
+
return soft_body_->m_nodes.size();
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
int SoftBody::link_count() const
|
|
248
|
+
{
|
|
249
|
+
return soft_body_->m_links.size();
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
int SoftBody::face_count() const
|
|
253
|
+
{
|
|
254
|
+
return soft_body_->m_faces.size();
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
int SoftBody::tetra_count() const
|
|
258
|
+
{
|
|
259
|
+
return soft_body_->m_tetras.size();
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
int SoftBody::cluster_count() const
|
|
263
|
+
{
|
|
264
|
+
return soft_body_->clusterCount();
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
btScalar SoftBody::total_mass() const
|
|
268
|
+
{
|
|
269
|
+
return soft_body_->getTotalMass();
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
void SoftBody::set_total_mass(btScalar mass, bool from_faces)
|
|
273
|
+
{
|
|
274
|
+
soft_body_->setTotalMass(mass, from_faces);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
btScalar SoftBody::node_mass(int index) const
|
|
278
|
+
{
|
|
279
|
+
return soft_body_->getMass(validate_node_index(index));
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
btScalar SoftBody::set_node_mass(int index, btScalar mass)
|
|
283
|
+
{
|
|
284
|
+
soft_body_->setMass(validate_node_index(index), mass);
|
|
285
|
+
return mass;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
btVector3 SoftBody::node_position(int index) const
|
|
289
|
+
{
|
|
290
|
+
return soft_body_->m_nodes[validate_node_index(index)].m_x;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
btVector3 SoftBody::node_velocity(int index) const
|
|
294
|
+
{
|
|
295
|
+
return soft_body_->m_nodes[validate_node_index(index)].m_v;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
btVector3 SoftBody::center_of_mass() const
|
|
299
|
+
{
|
|
300
|
+
return soft_body_->getCenterOfMass();
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
btVector3 SoftBody::linear_velocity()
|
|
304
|
+
{
|
|
305
|
+
return soft_body_->getLinearVelocity();
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
void SoftBody::set_linear_velocity(Rice::Object velocity)
|
|
309
|
+
{
|
|
310
|
+
soft_body_->setLinearVelocity(coerce_vector(velocity));
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
void SoftBody::set_velocity(Rice::Object velocity)
|
|
314
|
+
{
|
|
315
|
+
soft_body_->setVelocity(coerce_vector(velocity));
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
void SoftBody::set_angular_velocity(Rice::Object velocity)
|
|
319
|
+
{
|
|
320
|
+
soft_body_->setAngularVelocity(coerce_vector(velocity));
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
void SoftBody::add_force(Rice::Object force)
|
|
324
|
+
{
|
|
325
|
+
soft_body_->addForce(coerce_vector(force));
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
void SoftBody::add_velocity(Rice::Object velocity)
|
|
329
|
+
{
|
|
330
|
+
soft_body_->addVelocity(coerce_vector(velocity));
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
void SoftBody::translate(Rice::Object translation)
|
|
334
|
+
{
|
|
335
|
+
soft_body_->translate(coerce_vector(translation));
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
void SoftBody::rotate(Rice::Object rotation)
|
|
339
|
+
{
|
|
340
|
+
soft_body_->rotate(coerce_quaternion(rotation));
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
void SoftBody::scale(Rice::Object scaling)
|
|
344
|
+
{
|
|
345
|
+
soft_body_->scale(coerce_vector(scaling));
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
void SoftBody::transform(Rice::Object transform)
|
|
349
|
+
{
|
|
350
|
+
soft_body_->transform(coerce_transform(transform));
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
void SoftBody::set_pose(bool volume, bool frame)
|
|
354
|
+
{
|
|
355
|
+
soft_body_->setPose(volume, frame);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
int SoftBody::generate_bending_constraints(int distance)
|
|
359
|
+
{
|
|
360
|
+
return soft_body_->generateBendingConstraints(distance);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
int SoftBody::generate_clusters(int count)
|
|
364
|
+
{
|
|
365
|
+
return soft_body_->generateClusters(count);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
void SoftBody::randomize_constraints()
|
|
369
|
+
{
|
|
370
|
+
soft_body_->randomizeConstraints();
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
btVector3 SoftBody::wind_velocity()
|
|
374
|
+
{
|
|
375
|
+
return soft_body_->getWindVelocity();
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
btVector3 SoftBody::set_wind_velocity(Rice::Object velocity)
|
|
379
|
+
{
|
|
380
|
+
btVector3 vector = coerce_vector(velocity);
|
|
381
|
+
soft_body_->setWindVelocity(vector);
|
|
382
|
+
return vector;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
void SoftBody::set_zero_velocity()
|
|
386
|
+
{
|
|
387
|
+
soft_body_->setZeroVelocity();
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
bool SoftBody::self_collision()
|
|
391
|
+
{
|
|
392
|
+
return soft_body_->useSelfCollision();
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
bool SoftBody::set_self_collision(bool enabled)
|
|
396
|
+
{
|
|
397
|
+
soft_body_->setSelfCollision(enabled);
|
|
398
|
+
return enabled;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
Rice::Array SoftBody::aabb() const
|
|
402
|
+
{
|
|
403
|
+
btVector3 aabb_min;
|
|
404
|
+
btVector3 aabb_max;
|
|
405
|
+
soft_body_->getAabb(aabb_min, aabb_max);
|
|
406
|
+
Rice::Array array;
|
|
407
|
+
array.push(vector_object(aabb_min));
|
|
408
|
+
array.push(vector_object(aabb_max));
|
|
409
|
+
return array;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
Rice::Object SoftBody::ray_test(Rice::Object from, Rice::Object to)
|
|
413
|
+
{
|
|
414
|
+
btSoftBody::sRayCast result;
|
|
415
|
+
if (!soft_body_->rayTest(coerce_vector(from), coerce_vector(to), result)) {
|
|
416
|
+
return Rice::Object(Qnil);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
Rice::Hash hash;
|
|
420
|
+
hash[Rice::Symbol("feature")] = soft_body_feature_symbol(result.feature);
|
|
421
|
+
hash[Rice::Symbol("index")] = result.index;
|
|
422
|
+
hash[Rice::Symbol("fraction")] = result.fraction;
|
|
423
|
+
return hash;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
void SoftBody::append_anchor(int node, RigidBody& rigid_body, bool disable_collision_between_linked_bodies, btScalar influence)
|
|
427
|
+
{
|
|
428
|
+
soft_body_->appendAnchor(validate_node_index(node), rigid_body.get(), disable_collision_between_linked_bodies, influence);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
SoftRigidDynamicsWorld::SoftRigidDynamicsWorld()
|
|
432
|
+
: configuration_(std::make_unique<btSoftBodyRigidBodyCollisionConfiguration>()),
|
|
433
|
+
dispatcher_(std::make_unique<btCollisionDispatcher>(configuration_.get())),
|
|
434
|
+
broadphase_(std::make_unique<btDbvtBroadphase>()),
|
|
435
|
+
solver_(std::make_unique<btSequentialImpulseConstraintSolver>()),
|
|
436
|
+
world_(std::make_unique<btSoftRigidDynamicsWorld>(
|
|
437
|
+
dispatcher_.get(),
|
|
438
|
+
broadphase_.get(),
|
|
439
|
+
solver_.get(),
|
|
440
|
+
configuration_.get()))
|
|
441
|
+
{
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
SoftRigidDynamicsWorld::~SoftRigidDynamicsWorld()
|
|
445
|
+
{
|
|
446
|
+
soft_bodies_.clear();
|
|
447
|
+
rigid_bodies_.clear();
|
|
448
|
+
soft_body_values_.clear();
|
|
449
|
+
collision_object_values_.clear();
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
btSoftRigidDynamicsWorld* SoftRigidDynamicsWorld::get()
|
|
453
|
+
{
|
|
454
|
+
return world_.get();
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
btVector3 SoftRigidDynamicsWorld::gravity() const
|
|
458
|
+
{
|
|
459
|
+
return world_->getGravity();
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
btVector3 SoftRigidDynamicsWorld::set_gravity(Rice::Object gravity)
|
|
463
|
+
{
|
|
464
|
+
btVector3 vector = coerce_vector(gravity);
|
|
465
|
+
world_->setGravity(vector);
|
|
466
|
+
world_->getWorldInfo().m_gravity = vector;
|
|
467
|
+
return vector;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
SoftBodyWorldInfo* SoftRigidDynamicsWorld::world_info()
|
|
471
|
+
{
|
|
472
|
+
return new SoftBodyWorldInfo(&world_->getWorldInfo());
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
void SoftRigidDynamicsWorld::add_rigid_body_object(VALUE rigid_body)
|
|
476
|
+
{
|
|
477
|
+
RigidBody* body = rigid_body_from_value(rigid_body);
|
|
478
|
+
btRigidBody* bullet_body = body->get();
|
|
479
|
+
if (rigid_bodies_.insert(bullet_body).second) {
|
|
480
|
+
world_->addRigidBody(bullet_body);
|
|
481
|
+
collision_object_values_[bullet_body] = rigid_body;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
void SoftRigidDynamicsWorld::remove_rigid_body_object(VALUE rigid_body)
|
|
486
|
+
{
|
|
487
|
+
RigidBody* body = rigid_body_from_value(rigid_body);
|
|
488
|
+
btRigidBody* bullet_body = body->get();
|
|
489
|
+
auto iterator = rigid_bodies_.find(bullet_body);
|
|
490
|
+
if (iterator != rigid_bodies_.end()) {
|
|
491
|
+
world_->removeRigidBody(bullet_body);
|
|
492
|
+
rigid_bodies_.erase(iterator);
|
|
493
|
+
}
|
|
494
|
+
collision_object_values_.erase(bullet_body);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
void SoftRigidDynamicsWorld::add_soft_body_object(VALUE soft_body, int collision_filter_group, int collision_filter_mask)
|
|
498
|
+
{
|
|
499
|
+
SoftBody* body = soft_body_from_value(soft_body);
|
|
500
|
+
btSoftBody* bullet_body = body->get();
|
|
501
|
+
if (soft_bodies_.insert(bullet_body).second) {
|
|
502
|
+
world_->addSoftBody(bullet_body, collision_filter_group, collision_filter_mask);
|
|
503
|
+
soft_body_values_[bullet_body] = soft_body;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
void SoftRigidDynamicsWorld::remove_soft_body_object(VALUE soft_body)
|
|
508
|
+
{
|
|
509
|
+
SoftBody* body = soft_body_from_value(soft_body);
|
|
510
|
+
btSoftBody* bullet_body = body->get();
|
|
511
|
+
auto iterator = soft_bodies_.find(bullet_body);
|
|
512
|
+
if (iterator != soft_bodies_.end()) {
|
|
513
|
+
world_->removeSoftBody(bullet_body);
|
|
514
|
+
soft_bodies_.erase(iterator);
|
|
515
|
+
}
|
|
516
|
+
soft_body_values_.erase(bullet_body);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
int SoftRigidDynamicsWorld::step_simulation(btScalar time_step, int max_sub_steps, btScalar fixed_time_step)
|
|
520
|
+
{
|
|
521
|
+
StepSimulationArgs args{world_.get(), time_step, max_sub_steps, fixed_time_step, 0};
|
|
522
|
+
rb_thread_call_without_gvl(step_simulation_without_gvl, &args, nullptr, nullptr);
|
|
523
|
+
return args.result;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
int SoftRigidDynamicsWorld::num_collision_objects() const
|
|
527
|
+
{
|
|
528
|
+
return world_->getNumCollisionObjects();
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
int SoftRigidDynamicsWorld::num_soft_bodies() const
|
|
532
|
+
{
|
|
533
|
+
return world_->getSoftBodyArray().size();
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
int SoftRigidDynamicsWorld::draw_flags() const
|
|
537
|
+
{
|
|
538
|
+
return world_->getDrawFlags();
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
int SoftRigidDynamicsWorld::set_draw_flags(int flags)
|
|
542
|
+
{
|
|
543
|
+
world_->setDrawFlags(flags);
|
|
544
|
+
return flags;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
void SoftRigidDynamicsWorld::clear_forces()
|
|
548
|
+
{
|
|
549
|
+
world_->clearForces();
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
void SoftRigidDynamicsWorld::mark() const
|
|
553
|
+
{
|
|
554
|
+
for (const auto& entry : collision_object_values_) {
|
|
555
|
+
rb_gc_mark(entry.second);
|
|
556
|
+
}
|
|
557
|
+
for (const auto& entry : soft_body_values_) {
|
|
558
|
+
rb_gc_mark(entry.second);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
} // namespace bullet3
|
|
562
|
+
|
|
563
|
+
namespace Rice {
|
|
564
|
+
template <>
|
|
565
|
+
void ruby_mark<bullet3::SoftRigidDynamicsWorld>(bullet3::SoftRigidDynamicsWorld* world)
|
|
566
|
+
{
|
|
567
|
+
if (world != nullptr) {
|
|
568
|
+
world->mark();
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
} // namespace Rice
|
|
572
|
+
|
|
573
|
+
void Init_SoftBody(Rice::Module rb_mBullet)
|
|
574
|
+
{
|
|
575
|
+
Rice::Module rb_mSoftBody = Rice::define_module_under(rb_mBullet, "SoftBody");
|
|
576
|
+
|
|
577
|
+
Rice::define_class_under<bullet3::SoftBodyWorldInfo>(rb_mSoftBody, "SoftBodyWorldInfo")
|
|
578
|
+
.define_constructor(Rice::Constructor<bullet3::SoftBodyWorldInfo>())
|
|
579
|
+
.define_method("gravity", &bullet3::SoftBodyWorldInfo::gravity)
|
|
580
|
+
.define_method("gravity=", &bullet3::SoftBodyWorldInfo::set_gravity)
|
|
581
|
+
.define_method("air_density", &bullet3::SoftBodyWorldInfo::air_density)
|
|
582
|
+
.define_method("air_density=", &bullet3::SoftBodyWorldInfo::set_air_density)
|
|
583
|
+
.define_method("water_density", &bullet3::SoftBodyWorldInfo::water_density)
|
|
584
|
+
.define_method("water_density=", &bullet3::SoftBodyWorldInfo::set_water_density)
|
|
585
|
+
.define_method("water_offset", &bullet3::SoftBodyWorldInfo::water_offset)
|
|
586
|
+
.define_method("water_offset=", &bullet3::SoftBodyWorldInfo::set_water_offset)
|
|
587
|
+
.define_method("water_normal", &bullet3::SoftBodyWorldInfo::water_normal)
|
|
588
|
+
.define_method("water_normal=", &bullet3::SoftBodyWorldInfo::set_water_normal)
|
|
589
|
+
.define_method("max_displacement", &bullet3::SoftBodyWorldInfo::max_displacement)
|
|
590
|
+
.define_method("max_displacement=", &bullet3::SoftBodyWorldInfo::set_max_displacement)
|
|
591
|
+
.define_method("reset_sparse_sdf", &bullet3::SoftBodyWorldInfo::reset_sparse_sdf);
|
|
592
|
+
|
|
593
|
+
Rice::define_class_under<bullet3::SoftBody>(rb_mSoftBody, "SoftBody")
|
|
594
|
+
.define_method("node_count", &bullet3::SoftBody::node_count)
|
|
595
|
+
.define_method("link_count", &bullet3::SoftBody::link_count)
|
|
596
|
+
.define_method("face_count", &bullet3::SoftBody::face_count)
|
|
597
|
+
.define_method("tetra_count", &bullet3::SoftBody::tetra_count)
|
|
598
|
+
.define_method("cluster_count", &bullet3::SoftBody::cluster_count)
|
|
599
|
+
.define_method("total_mass", &bullet3::SoftBody::total_mass)
|
|
600
|
+
.define_method("set_total_mass", &bullet3::SoftBody::set_total_mass,
|
|
601
|
+
Rice::Arg("mass"),
|
|
602
|
+
Rice::Arg("from_faces") = false)
|
|
603
|
+
.define_method("node_mass", &bullet3::SoftBody::node_mass)
|
|
604
|
+
.define_method("set_node_mass", &bullet3::SoftBody::set_node_mass)
|
|
605
|
+
.define_method("node_position", &bullet3::SoftBody::node_position)
|
|
606
|
+
.define_method("node_velocity", &bullet3::SoftBody::node_velocity)
|
|
607
|
+
.define_method("center_of_mass", &bullet3::SoftBody::center_of_mass)
|
|
608
|
+
.define_method("linear_velocity", &bullet3::SoftBody::linear_velocity)
|
|
609
|
+
.define_method("linear_velocity=", &bullet3::SoftBody::set_linear_velocity)
|
|
610
|
+
.define_method("set_velocity", &bullet3::SoftBody::set_velocity)
|
|
611
|
+
.define_method("set_angular_velocity", &bullet3::SoftBody::set_angular_velocity)
|
|
612
|
+
.define_method("add_force", &bullet3::SoftBody::add_force)
|
|
613
|
+
.define_method("add_velocity", &bullet3::SoftBody::add_velocity)
|
|
614
|
+
.define_method("translate", &bullet3::SoftBody::translate)
|
|
615
|
+
.define_method("rotate", &bullet3::SoftBody::rotate)
|
|
616
|
+
.define_method("scale", &bullet3::SoftBody::scale)
|
|
617
|
+
.define_method("transform", &bullet3::SoftBody::transform)
|
|
618
|
+
.define_method("set_pose", &bullet3::SoftBody::set_pose)
|
|
619
|
+
.define_method("generate_bending_constraints", &bullet3::SoftBody::generate_bending_constraints)
|
|
620
|
+
.define_method("generate_clusters", &bullet3::SoftBody::generate_clusters)
|
|
621
|
+
.define_method("randomize_constraints", &bullet3::SoftBody::randomize_constraints)
|
|
622
|
+
.define_method("wind_velocity", &bullet3::SoftBody::wind_velocity)
|
|
623
|
+
.define_method("wind_velocity=", &bullet3::SoftBody::set_wind_velocity)
|
|
624
|
+
.define_method("set_zero_velocity", &bullet3::SoftBody::set_zero_velocity)
|
|
625
|
+
.define_method("self_collision?", &bullet3::SoftBody::self_collision)
|
|
626
|
+
.define_method("self_collision=", &bullet3::SoftBody::set_self_collision)
|
|
627
|
+
.define_method("aabb", &bullet3::SoftBody::aabb)
|
|
628
|
+
.define_method("ray_test", &bullet3::SoftBody::ray_test)
|
|
629
|
+
.define_method("append_anchor", &bullet3::SoftBody::append_anchor,
|
|
630
|
+
Rice::Arg("node"),
|
|
631
|
+
Rice::Arg("rigid_body").keepAlive(),
|
|
632
|
+
Rice::Arg("disable_collision_between_linked_bodies") = false,
|
|
633
|
+
Rice::Arg("influence") = btScalar(1.0));
|
|
634
|
+
|
|
635
|
+
Rice::define_class_under<bullet3::SoftRigidDynamicsWorld>(rb_mSoftBody, "SoftRigidDynamicsWorld")
|
|
636
|
+
.define_constructor(Rice::Constructor<bullet3::SoftRigidDynamicsWorld>())
|
|
637
|
+
.define_singleton_method("create", [](Rice::Object) -> bullet3::SoftRigidDynamicsWorld* {
|
|
638
|
+
return new bullet3::SoftRigidDynamicsWorld();
|
|
639
|
+
}, Rice::Return().takeOwnership())
|
|
640
|
+
.define_method("gravity", &bullet3::SoftRigidDynamicsWorld::gravity)
|
|
641
|
+
.define_method("gravity=", &bullet3::SoftRigidDynamicsWorld::set_gravity)
|
|
642
|
+
.define_method("world_info", &bullet3::SoftRigidDynamicsWorld::world_info, Rice::Return().takeOwnership())
|
|
643
|
+
.define_method("add_rigid_body", &bullet3::SoftRigidDynamicsWorld::add_rigid_body_object,
|
|
644
|
+
Rice::Arg("rigid_body").setValue().keepAlive())
|
|
645
|
+
.define_method("remove_rigid_body", &bullet3::SoftRigidDynamicsWorld::remove_rigid_body_object,
|
|
646
|
+
Rice::Arg("rigid_body").setValue())
|
|
647
|
+
.define_method("add_soft_body", &bullet3::SoftRigidDynamicsWorld::add_soft_body_object,
|
|
648
|
+
Rice::Arg("soft_body").setValue().keepAlive(),
|
|
649
|
+
Rice::Arg("collision_filter_group") = int(btBroadphaseProxy::DefaultFilter),
|
|
650
|
+
Rice::Arg("collision_filter_mask") = int(btBroadphaseProxy::AllFilter))
|
|
651
|
+
.define_method("remove_soft_body", &bullet3::SoftRigidDynamicsWorld::remove_soft_body_object,
|
|
652
|
+
Rice::Arg("soft_body").setValue())
|
|
653
|
+
.define_method("step_simulation", &bullet3::SoftRigidDynamicsWorld::step_simulation,
|
|
654
|
+
Rice::Arg("time_step"),
|
|
655
|
+
Rice::Arg("max_sub_steps") = 1,
|
|
656
|
+
Rice::Arg("fixed_time_step") = btScalar(1.0 / 60.0))
|
|
657
|
+
.define_method("num_collision_objects", &bullet3::SoftRigidDynamicsWorld::num_collision_objects)
|
|
658
|
+
.define_method("num_soft_bodies", &bullet3::SoftRigidDynamicsWorld::num_soft_bodies)
|
|
659
|
+
.define_method("draw_flags", &bullet3::SoftRigidDynamicsWorld::draw_flags)
|
|
660
|
+
.define_method("draw_flags=", &bullet3::SoftRigidDynamicsWorld::set_draw_flags)
|
|
661
|
+
.define_method("clear_forces", &bullet3::SoftRigidDynamicsWorld::clear_forces);
|
|
662
|
+
|
|
663
|
+
Rice::Module rb_mHelpers = Rice::define_module_under(rb_mSoftBody, "Helpers");
|
|
664
|
+
rb_mHelpers.define_singleton_method("create_rope", [](Rice::Object, bullet3::SoftBodyWorldInfo& world_info, Rice::Object from, Rice::Object to, int resolution, int fixed_nodes) {
|
|
665
|
+
return new bullet3::SoftBody(btSoftBodyHelpers::CreateRope(
|
|
666
|
+
world_info.get(),
|
|
667
|
+
bullet3::coerce_vector(from),
|
|
668
|
+
bullet3::coerce_vector(to),
|
|
669
|
+
resolution,
|
|
670
|
+
fixed_nodes));
|
|
671
|
+
}, Rice::Return().takeOwnership());
|
|
672
|
+
rb_mHelpers.define_singleton_method("create_patch", [](Rice::Object,
|
|
673
|
+
bullet3::SoftBodyWorldInfo& world_info,
|
|
674
|
+
Rice::Object corner00,
|
|
675
|
+
Rice::Object corner10,
|
|
676
|
+
Rice::Object corner01,
|
|
677
|
+
Rice::Object corner11,
|
|
678
|
+
int resolution_x,
|
|
679
|
+
int resolution_y,
|
|
680
|
+
int fixed_nodes,
|
|
681
|
+
bool generate_diagonals,
|
|
682
|
+
btScalar perturbation) {
|
|
683
|
+
return new bullet3::SoftBody(btSoftBodyHelpers::CreatePatch(
|
|
684
|
+
world_info.get(),
|
|
685
|
+
bullet3::coerce_vector(corner00),
|
|
686
|
+
bullet3::coerce_vector(corner10),
|
|
687
|
+
bullet3::coerce_vector(corner01),
|
|
688
|
+
bullet3::coerce_vector(corner11),
|
|
689
|
+
resolution_x,
|
|
690
|
+
resolution_y,
|
|
691
|
+
fixed_nodes,
|
|
692
|
+
generate_diagonals,
|
|
693
|
+
perturbation));
|
|
694
|
+
}, Rice::Return().takeOwnership(), Rice::Arg("world_info"), Rice::Arg("corner00"), Rice::Arg("corner10"), Rice::Arg("corner01"), Rice::Arg("corner11"), Rice::Arg("resolution_x"), Rice::Arg("resolution_y"), Rice::Arg("fixed_nodes"), Rice::Arg("generate_diagonals"), Rice::Arg("perturbation") = btScalar(0.0));
|
|
695
|
+
rb_mHelpers.define_singleton_method("create_ellipsoid", [](Rice::Object, bullet3::SoftBodyWorldInfo& world_info, Rice::Object center, Rice::Object radius, int resolution) {
|
|
696
|
+
return new bullet3::SoftBody(btSoftBodyHelpers::CreateEllipsoid(
|
|
697
|
+
world_info.get(),
|
|
698
|
+
bullet3::coerce_vector(center),
|
|
699
|
+
bullet3::coerce_vector(radius),
|
|
700
|
+
resolution));
|
|
701
|
+
}, Rice::Return().takeOwnership());
|
|
702
|
+
rb_mHelpers.define_singleton_method("create_from_tri_mesh", [](Rice::Object, bullet3::SoftBodyWorldInfo& world_info, Rice::Object vertices, Rice::Object triangles, bool randomize_constraints) {
|
|
703
|
+
std::vector<btScalar> flat_vertices = flat_vertices_from_object(vertices);
|
|
704
|
+
std::vector<int> indices = triangle_indices_from_object(triangles);
|
|
705
|
+
return new bullet3::SoftBody(btSoftBodyHelpers::CreateFromTriMesh(
|
|
706
|
+
world_info.get(),
|
|
707
|
+
flat_vertices.data(),
|
|
708
|
+
indices.data(),
|
|
709
|
+
static_cast<int>(indices.size() / 3),
|
|
710
|
+
randomize_constraints));
|
|
711
|
+
}, Rice::Return().takeOwnership(), Rice::Arg("world_info"), Rice::Arg("vertices"), Rice::Arg("triangles"), Rice::Arg("randomize_constraints") = true);
|
|
712
|
+
rb_mHelpers.define_singleton_method("create_from_convex_hull", [](Rice::Object, bullet3::SoftBodyWorldInfo& world_info, Rice::Object points, bool randomize_constraints) {
|
|
713
|
+
std::vector<btVector3> vectors = vector_array_from_object(points);
|
|
714
|
+
return new bullet3::SoftBody(btSoftBodyHelpers::CreateFromConvexHull(
|
|
715
|
+
world_info.get(),
|
|
716
|
+
vectors.data(),
|
|
717
|
+
static_cast<int>(vectors.size()),
|
|
718
|
+
randomize_constraints));
|
|
719
|
+
}, Rice::Return().takeOwnership(), Rice::Arg("world_info"), Rice::Arg("points"), Rice::Arg("randomize_constraints") = true);
|
|
720
|
+
}
|