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.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +194 -0
  4. data/data/cube.urdf +22 -0
  5. data/data/plane.urdf +19 -0
  6. data/ext/bullet3/CMakeLists.txt +224 -0
  7. data/ext/bullet3/bullet3.cpp +34 -0
  8. data/ext/bullet3/collision/rb_collision.cpp +428 -0
  9. data/ext/bullet3/collision/rb_collision.hpp +87 -0
  10. data/ext/bullet3/collision/shapes/rb_collision_shape.cpp +485 -0
  11. data/ext/bullet3/collision/shapes/rb_collision_shape.hpp +5 -0
  12. data/ext/bullet3/constraints/rb_constraints.cpp +1310 -0
  13. data/ext/bullet3/constraints/rb_constraints.hpp +226 -0
  14. data/ext/bullet3/dynamics/rb_dynamics.cpp +862 -0
  15. data/ext/bullet3/dynamics/rb_dynamics.hpp +180 -0
  16. data/ext/bullet3/extconf.rb +57 -0
  17. data/ext/bullet3/io/rb_io.cpp +108 -0
  18. data/ext/bullet3/io/rb_io.hpp +40 -0
  19. data/ext/bullet3/linear_math/rb_matrix3x3.cpp +93 -0
  20. data/ext/bullet3/linear_math/rb_matrix3x3.hpp +5 -0
  21. data/ext/bullet3/linear_math/rb_quaternion.cpp +134 -0
  22. data/ext/bullet3/linear_math/rb_quaternion.hpp +5 -0
  23. data/ext/bullet3/linear_math/rb_transform.cpp +157 -0
  24. data/ext/bullet3/linear_math/rb_transform.hpp +34 -0
  25. data/ext/bullet3/linear_math/rb_vector3.cpp +123 -0
  26. data/ext/bullet3/linear_math/rb_vector3.hpp +5 -0
  27. data/ext/bullet3/multi_body/rb_multi_body.cpp +1000 -0
  28. data/ext/bullet3/multi_body/rb_multi_body.hpp +190 -0
  29. data/ext/bullet3/soft_body/rb_soft_body.cpp +720 -0
  30. data/ext/bullet3/soft_body/rb_soft_body.hpp +122 -0
  31. data/ext/bullet3/util/rb_debug_draw.cpp +250 -0
  32. data/ext/bullet3/util/rb_debug_draw.hpp +47 -0
  33. data/ext/bullet3/util/ruby_cpp_compat.hpp +29 -0
  34. data/ext/bullet3/util/type_conversions.hpp +107 -0
  35. data/ext/bullet3/vehicle/rb_vehicle.cpp +467 -0
  36. data/ext/bullet3/vehicle/rb_vehicle.hpp +115 -0
  37. data/lib/bullet3/collision.rb +6 -0
  38. data/lib/bullet3/constraints.rb +6 -0
  39. data/lib/bullet3/data.rb +39 -0
  40. data/lib/bullet3/debug_draw.rb +73 -0
  41. data/lib/bullet3/dynamics.rb +4 -0
  42. data/lib/bullet3/io.rb +110 -0
  43. data/lib/bullet3/linear_math/matrix3x3.rb +69 -0
  44. data/lib/bullet3/linear_math/quaternion.rb +187 -0
  45. data/lib/bullet3/linear_math/transform.rb +48 -0
  46. data/lib/bullet3/linear_math/vector3.rb +199 -0
  47. data/lib/bullet3/linear_math.rb +6 -0
  48. data/lib/bullet3/multi_body.rb +6 -0
  49. data/lib/bullet3/simulation.rb +1170 -0
  50. data/lib/bullet3/soft_body.rb +6 -0
  51. data/lib/bullet3/vehicle.rb +4 -0
  52. data/lib/bullet3/version.rb +5 -0
  53. data/lib/bullet3.rb +49 -0
  54. metadata +124 -0
@@ -0,0 +1,485 @@
1
+ #include "rb_collision_shape.hpp"
2
+
3
+ #include <algorithm>
4
+ #include <array>
5
+ #include <cctype>
6
+ #include <stdexcept>
7
+ #include <string>
8
+ #include <vector>
9
+
10
+ #include <BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h>
11
+ #include <BulletCollision/CollisionShapes/btCompoundShape.h>
12
+ #include <BulletCollision/CollisionShapes/btConvexHullShape.h>
13
+ #include <BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h>
14
+ #include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
15
+ #include <BulletCollision/CollisionShapes/btMultiSphereShape.h>
16
+ #include <BulletCollision/CollisionShapes/btTriangleMesh.h>
17
+ #include <btBulletDynamicsCommon.h>
18
+ #include <rice/rice.hpp>
19
+
20
+ #include "../../linear_math/rb_transform.hpp"
21
+
22
+ namespace {
23
+ Rice::Object array_item(const Rice::Array& array, long index)
24
+ {
25
+ return Rice::Object(array[index].value());
26
+ }
27
+
28
+ btVector3 vector_from_array(Rice::Object object)
29
+ {
30
+ Rice::Array array(object);
31
+ if (array.size() != 3) {
32
+ throw std::invalid_argument("expected a 3-element Array");
33
+ }
34
+
35
+ return btVector3(
36
+ Rice::detail::From_Ruby<btScalar>().convert(array[0]),
37
+ Rice::detail::From_Ruby<btScalar>().convert(array[1]),
38
+ Rice::detail::From_Ruby<btScalar>().convert(array[2])
39
+ );
40
+ }
41
+
42
+ btVector3 coerce_vector(Rice::Object object)
43
+ {
44
+ if (rb_obj_is_kind_of(object.value(), rb_cArray)) {
45
+ return vector_from_array(object);
46
+ }
47
+
48
+ if (rb_respond_to(object.value(), rb_intern("to_a")) != 0) {
49
+ return vector_from_array(object.call("to_a"));
50
+ }
51
+
52
+ return *Rice::detail::From_Ruby<btVector3*>().convert(object);
53
+ }
54
+
55
+ btCollisionShape* coerce_collision_shape(Rice::Object object)
56
+ {
57
+ btCollisionShape* shape = Rice::detail::From_Ruby<btCollisionShape*>().convert(object);
58
+ if (shape == nullptr) {
59
+ throw std::invalid_argument("expected Bullet3::Shapes::CollisionShape");
60
+ }
61
+ return shape;
62
+ }
63
+
64
+ std::vector<btVector3> vector_list_from_value(VALUE value)
65
+ {
66
+ Rice::Array array{Rice::Object(value)};
67
+ std::vector<btVector3> vectors;
68
+ vectors.reserve(array.size());
69
+
70
+ for (long index = 0; index < array.size(); ++index) {
71
+ vectors.push_back(coerce_vector(array_item(array, index)));
72
+ }
73
+
74
+ return vectors;
75
+ }
76
+
77
+ std::vector<btScalar> scalar_list_from_value(VALUE value)
78
+ {
79
+ Rice::Array array{Rice::Object(value)};
80
+ std::vector<btScalar> scalars;
81
+ scalars.reserve(array.size());
82
+
83
+ for (long index = 0; index < array.size(); ++index) {
84
+ scalars.push_back(Rice::detail::From_Ruby<btScalar>().convert(array[index]));
85
+ }
86
+
87
+ return scalars;
88
+ }
89
+
90
+ std::vector<float> float_list_from_value(VALUE value)
91
+ {
92
+ Rice::Array array{Rice::Object(value)};
93
+ std::vector<float> floats;
94
+ floats.reserve(array.size());
95
+
96
+ for (long index = 0; index < array.size(); ++index) {
97
+ floats.push_back(Rice::detail::From_Ruby<float>().convert(array[index]));
98
+ }
99
+
100
+ return floats;
101
+ }
102
+
103
+ std::array<btVector3, 3> triangle_from_object(Rice::Object object)
104
+ {
105
+ Rice::Array array(object);
106
+ if (array.size() != 3) {
107
+ throw std::invalid_argument("expected a triangle with 3 vertices");
108
+ }
109
+
110
+ return {
111
+ coerce_vector(array_item(array, 0)),
112
+ coerce_vector(array_item(array, 1)),
113
+ coerce_vector(array_item(array, 2))
114
+ };
115
+ }
116
+
117
+ Rice::Symbol shape_type(const btCollisionShape& shape)
118
+ {
119
+ std::string name(shape.getName());
120
+ std::transform(name.begin(), name.end(), name.begin(), [](unsigned char character) {
121
+ return static_cast<char>(std::tolower(character));
122
+ });
123
+
124
+ if (name == "box") {
125
+ return Rice::Symbol("box");
126
+ }
127
+ if (name == "sphere") {
128
+ return Rice::Symbol("sphere");
129
+ }
130
+ if (name == "capsule" || name == "capsuleshape") {
131
+ return Rice::Symbol("capsule");
132
+ }
133
+ if (name.rfind("cylinder", 0) == 0) {
134
+ return Rice::Symbol("cylinder");
135
+ }
136
+ if (name.rfind("cone", 0) == 0) {
137
+ return Rice::Symbol("cone");
138
+ }
139
+ if (name == "staticplane") {
140
+ return Rice::Symbol("static_plane");
141
+ }
142
+ if (name == "compound") {
143
+ return Rice::Symbol("compound");
144
+ }
145
+ if (name == "convex") {
146
+ return Rice::Symbol("convex_hull");
147
+ }
148
+ if (name == "bvhtrianglemesh") {
149
+ return Rice::Symbol("triangle_mesh");
150
+ }
151
+ if (name == "convextrimesh") {
152
+ return Rice::Symbol("convex_triangle_mesh");
153
+ }
154
+ if (name == "multisphere") {
155
+ return Rice::Symbol("multi_sphere");
156
+ }
157
+ if (name == "terrain") {
158
+ return Rice::Symbol("heightfield");
159
+ }
160
+
161
+ return Rice::Symbol(name);
162
+ }
163
+
164
+ btVector3 calculate_local_inertia(const btCollisionShape& shape, btScalar mass)
165
+ {
166
+ btVector3 inertia(0, 0, 0);
167
+ shape.calculateLocalInertia(mass, inertia);
168
+ return inertia;
169
+ }
170
+
171
+ Rice::Array bounding_sphere(const btCollisionShape& shape)
172
+ {
173
+ btVector3 center(0, 0, 0);
174
+ btScalar radius = 0;
175
+ shape.getBoundingSphere(center, radius);
176
+
177
+ Rice::Array result;
178
+ result.push(btVector3(center), true);
179
+ result.push(radius);
180
+ return result;
181
+ }
182
+
183
+ Rice::Array shape_aabb(const btCollisionShape& shape, const btTransform& transform)
184
+ {
185
+ btVector3 min(0, 0, 0);
186
+ btVector3 max(0, 0, 0);
187
+ shape.getAabb(transform, min, max);
188
+
189
+ Rice::Array result;
190
+ result.push(btVector3(min), true);
191
+ result.push(btVector3(max), true);
192
+ return result;
193
+ }
194
+
195
+ class RubyConvexHullShape : public btConvexHullShape {
196
+ public:
197
+ RubyConvexHullShape() = default;
198
+
199
+ explicit RubyConvexHullShape(VALUE points)
200
+ {
201
+ for (const btVector3& point : vector_list_from_value(points)) {
202
+ addPoint(point, false);
203
+ }
204
+ recalcLocalAabb();
205
+ }
206
+ };
207
+
208
+ class TriangleMeshStorage {
209
+ public:
210
+ explicit TriangleMeshStorage(VALUE triangles)
211
+ : mesh_(true, true),
212
+ triangle_count_(0)
213
+ {
214
+ Rice::Array array{Rice::Object(triangles)};
215
+ for (long index = 0; index < array.size(); ++index) {
216
+ std::array<btVector3, 3> triangle = triangle_from_object(array_item(array, index));
217
+ mesh_.addTriangle(triangle[0], triangle[1], triangle[2]);
218
+ ++triangle_count_;
219
+ }
220
+ }
221
+
222
+ int triangle_count() const
223
+ {
224
+ return triangle_count_;
225
+ }
226
+
227
+ protected:
228
+ btTriangleMesh mesh_;
229
+ int triangle_count_;
230
+ };
231
+
232
+ class RubyTriangleMeshShape : private TriangleMeshStorage, public btBvhTriangleMeshShape {
233
+ public:
234
+ explicit RubyTriangleMeshShape(VALUE triangles)
235
+ : TriangleMeshStorage(triangles),
236
+ btBvhTriangleMeshShape(&mesh_, true)
237
+ {
238
+ }
239
+
240
+ int num_triangles() const
241
+ {
242
+ return triangle_count();
243
+ }
244
+ };
245
+
246
+ class RubyConvexTriangleMeshShape : private TriangleMeshStorage, public btConvexTriangleMeshShape {
247
+ public:
248
+ explicit RubyConvexTriangleMeshShape(VALUE triangles)
249
+ : TriangleMeshStorage(triangles),
250
+ btConvexTriangleMeshShape(&mesh_, true)
251
+ {
252
+ }
253
+
254
+ int num_triangles() const
255
+ {
256
+ return triangle_count();
257
+ }
258
+ };
259
+
260
+ class MultiSphereStorage {
261
+ public:
262
+ MultiSphereStorage(VALUE positions, VALUE radii)
263
+ : positions_(vector_list_from_value(positions)),
264
+ radii_(scalar_list_from_value(radii))
265
+ {
266
+ if (positions_.empty()) {
267
+ throw std::invalid_argument("expected at least one sphere");
268
+ }
269
+ if (positions_.size() != radii_.size()) {
270
+ throw std::invalid_argument("positions and radii must have the same length");
271
+ }
272
+ }
273
+
274
+ protected:
275
+ std::vector<btVector3> positions_;
276
+ std::vector<btScalar> radii_;
277
+ };
278
+
279
+ class RubyMultiSphereShape : private MultiSphereStorage, public btMultiSphereShape {
280
+ public:
281
+ RubyMultiSphereShape(VALUE positions, VALUE radii)
282
+ : MultiSphereStorage(positions, radii),
283
+ btMultiSphereShape(positions_.data(), radii_.data(), static_cast<int>(positions_.size()))
284
+ {
285
+ }
286
+ };
287
+
288
+ class HeightfieldStorage {
289
+ public:
290
+ HeightfieldStorage(int width, int length, VALUE heights)
291
+ : width_(width),
292
+ length_(length),
293
+ heights_(float_list_from_value(heights))
294
+ {
295
+ if (width_ <= 0 || length_ <= 0) {
296
+ throw std::invalid_argument("heightfield dimensions must be positive");
297
+ }
298
+ if (heights_.size() != static_cast<std::size_t>(width_ * length_)) {
299
+ throw std::invalid_argument("heightfield data size must equal width * length");
300
+ }
301
+ }
302
+
303
+ float height_at(int x, int y) const
304
+ {
305
+ if (x < 0 || x >= width_ || y < 0 || y >= length_) {
306
+ throw std::out_of_range("heightfield index outside bounds");
307
+ }
308
+ return heights_[static_cast<std::size_t>(y * width_ + x)];
309
+ }
310
+
311
+ protected:
312
+ int width_;
313
+ int length_;
314
+ std::vector<float> heights_;
315
+ };
316
+
317
+ class RubyHeightfieldShape : private HeightfieldStorage, public btHeightfieldTerrainShape {
318
+ public:
319
+ RubyHeightfieldShape(int width,
320
+ int length,
321
+ VALUE heights,
322
+ btScalar min_height,
323
+ btScalar max_height,
324
+ int up_axis,
325
+ bool flip_quad_edges)
326
+ : HeightfieldStorage(width, length, heights),
327
+ btHeightfieldTerrainShape(width_, length_, heights_.data(), min_height, max_height, up_axis, flip_quad_edges)
328
+ {
329
+ }
330
+
331
+ int width() const
332
+ {
333
+ return width_;
334
+ }
335
+
336
+ int length() const
337
+ {
338
+ return length_;
339
+ }
340
+
341
+ float height(int x, int y) const
342
+ {
343
+ return height_at(x, y);
344
+ }
345
+
346
+ btVector3 vertex(int x, int y) const
347
+ {
348
+ btVector3 result(0, 0, 0);
349
+ getVertex(x, y, result);
350
+ return result;
351
+ }
352
+ };
353
+ } // namespace
354
+
355
+ void Init_Shapes(Rice::Module rb_mBullet)
356
+ {
357
+ Rice::Module rb_mShapes = Rice::define_module_under(rb_mBullet, "Shapes");
358
+
359
+ Rice::define_class_under<btCollisionShape>(rb_mShapes, "CollisionShape")
360
+ .define_method("shape_type", &shape_type)
361
+ .define_method("local_scaling", [](const btCollisionShape& self) {
362
+ return btVector3(self.getLocalScaling());
363
+ })
364
+ .define_method("local_scaling=", [](btCollisionShape& self, Rice::Object scaling) {
365
+ btVector3 vector = coerce_vector(scaling);
366
+ self.setLocalScaling(vector);
367
+ return vector;
368
+ })
369
+ .define_method("margin", &btCollisionShape::getMargin)
370
+ .define_method("margin=", [](btCollisionShape& self, btScalar margin) {
371
+ self.setMargin(margin);
372
+ return margin;
373
+ })
374
+ .define_method("calculate_local_inertia", &calculate_local_inertia)
375
+ .define_method("bounding_sphere", &bounding_sphere)
376
+ .define_method("aabb", [](const btCollisionShape& self) {
377
+ return shape_aabb(self, btTransform::getIdentity());
378
+ })
379
+ .define_method("aabb", [](const btCollisionShape& self, VALUE transform) {
380
+ return shape_aabb(self, bullet3::coerce_transform(Rice::Object(transform)));
381
+ }, Rice::Arg("transform").setValue());
382
+
383
+ Rice::define_class_under<btBoxShape, btCollisionShape>(rb_mShapes, "BoxShape")
384
+ .define_constructor(Rice::Constructor<btBoxShape, const btVector3&>());
385
+
386
+ Rice::define_class_under<btSphereShape, btCollisionShape>(rb_mShapes, "SphereShape")
387
+ .define_constructor(Rice::Constructor<btSphereShape, btScalar>());
388
+
389
+ Rice::define_class_under<btCapsuleShape, btCollisionShape>(rb_mShapes, "CapsuleShape")
390
+ .define_constructor(Rice::Constructor<btCapsuleShape, btScalar, btScalar>());
391
+
392
+ Rice::define_class_under<btCylinderShape, btCollisionShape>(rb_mShapes, "CylinderShape")
393
+ .define_constructor(Rice::Constructor<btCylinderShape, const btVector3&>());
394
+
395
+ Rice::define_class_under<btConeShape, btCollisionShape>(rb_mShapes, "ConeShape")
396
+ .define_constructor(Rice::Constructor<btConeShape, btScalar, btScalar>());
397
+
398
+ Rice::define_class_under<btStaticPlaneShape, btCollisionShape>(rb_mShapes, "StaticPlaneShape")
399
+ .define_constructor(Rice::Constructor<btStaticPlaneShape, const btVector3&, btScalar>());
400
+
401
+ Rice::define_class_under<btCompoundShape, btCollisionShape>(rb_mShapes, "CompoundShape")
402
+ .define_constructor(Rice::Constructor<btCompoundShape, bool, int>(),
403
+ Rice::Arg("enable_dynamic_aabb_tree") = true,
404
+ Rice::Arg("initial_child_capacity") = 0)
405
+ .define_method("add_child_shape", [](btCompoundShape& self, Rice::Object transform, Rice::Object shape) {
406
+ self.addChildShape(bullet3::coerce_transform(transform), coerce_collision_shape(shape));
407
+ }, Rice::Arg("transform"), Rice::Arg("shape").keepAlive())
408
+ .define_method("remove_child_shape", [](btCompoundShape& self, Rice::Object shape) {
409
+ self.removeChildShape(coerce_collision_shape(shape));
410
+ })
411
+ .define_method("remove_child_shape_by_index", &btCompoundShape::removeChildShapeByIndex)
412
+ .define_method("num_child_shapes", &btCompoundShape::getNumChildShapes)
413
+ .define_method("child_shape", [](btCompoundShape& self, int index) {
414
+ return self.getChildShape(index);
415
+ })
416
+ .define_method("child_transform", [](const btCompoundShape& self, int index) {
417
+ return bullet3::Transform(self.getChildTransform(index));
418
+ })
419
+ .define_method("update_child_transform", [](btCompoundShape& self, int index, Rice::Object transform, bool recalculate) {
420
+ self.updateChildTransform(index, bullet3::coerce_transform(transform), recalculate);
421
+ }, Rice::Arg("index"), Rice::Arg("transform"), Rice::Arg("recalculate") = true)
422
+ .define_method("recalculate_local_aabb", &btCompoundShape::recalculateLocalAabb);
423
+
424
+ Rice::define_class_under<RubyConvexHullShape, btCollisionShape>(rb_mShapes, "ConvexHullShape")
425
+ .define_constructor(Rice::Constructor<RubyConvexHullShape>())
426
+ .define_constructor(Rice::Constructor<RubyConvexHullShape, VALUE>(),
427
+ Rice::Arg("points").setValue())
428
+ .define_method("add_point", [](RubyConvexHullShape& self, Rice::Object point, bool recalculate) {
429
+ self.addPoint(coerce_vector(point), recalculate);
430
+ }, Rice::Arg("point"), Rice::Arg("recalculate") = true)
431
+ .define_method("num_points", &RubyConvexHullShape::getNumPoints)
432
+ .define_method("point", [](const RubyConvexHullShape& self, int index) {
433
+ if (index < 0 || index >= self.getNumPoints()) {
434
+ throw std::out_of_range("point index outside convex hull");
435
+ }
436
+ return self.getUnscaledPoints()[index];
437
+ })
438
+ .define_method("optimize_convex_hull", &RubyConvexHullShape::optimizeConvexHull);
439
+
440
+ Rice::define_class_under<RubyTriangleMeshShape, btCollisionShape>(rb_mShapes, "TriangleMeshShape")
441
+ .define_constructor(Rice::Constructor<RubyTriangleMeshShape, VALUE>(),
442
+ Rice::Arg("triangles").setValue())
443
+ .define_method("num_triangles", &RubyTriangleMeshShape::num_triangles)
444
+ .define_method("uses_quantized_aabb_compression", &RubyTriangleMeshShape::usesQuantizedAabbCompression);
445
+
446
+ Rice::define_class_under<RubyConvexTriangleMeshShape, btCollisionShape>(rb_mShapes, "ConvexTriangleMeshShape")
447
+ .define_constructor(Rice::Constructor<RubyConvexTriangleMeshShape, VALUE>(),
448
+ Rice::Arg("triangles").setValue())
449
+ .define_method("num_triangles", &RubyConvexTriangleMeshShape::num_triangles);
450
+
451
+ Rice::define_class_under<RubyMultiSphereShape, btCollisionShape>(rb_mShapes, "MultiSphereShape")
452
+ .define_constructor(Rice::Constructor<RubyMultiSphereShape, VALUE, VALUE>(),
453
+ Rice::Arg("positions").setValue(),
454
+ Rice::Arg("radii").setValue())
455
+ .define_method("sphere_count", &RubyMultiSphereShape::getSphereCount)
456
+ .define_method("sphere_position", &RubyMultiSphereShape::getSpherePosition)
457
+ .define_method("sphere_radius", &RubyMultiSphereShape::getSphereRadius);
458
+
459
+ Rice::define_class_under<RubyHeightfieldShape, btCollisionShape>(rb_mShapes, "HeightfieldShape")
460
+ .define_constructor(Rice::Constructor<RubyHeightfieldShape, int, int, VALUE, btScalar, btScalar, int, bool>(),
461
+ Rice::Arg("width"),
462
+ Rice::Arg("length"),
463
+ Rice::Arg("heights").setValue(),
464
+ Rice::Arg("min_height"),
465
+ Rice::Arg("max_height"),
466
+ Rice::Arg("up_axis") = 1,
467
+ Rice::Arg("flip_quad_edges") = false)
468
+ .define_method("width", &RubyHeightfieldShape::width)
469
+ .define_method("length", &RubyHeightfieldShape::length)
470
+ .define_method("height", &RubyHeightfieldShape::height)
471
+ .define_method("up_axis", &RubyHeightfieldShape::getUpAxis)
472
+ .define_method("vertex", &RubyHeightfieldShape::vertex)
473
+ .define_method("use_diamond_subdivision=", [](RubyHeightfieldShape& self, bool enabled) {
474
+ self.setUseDiamondSubdivision(enabled);
475
+ return enabled;
476
+ })
477
+ .define_method("use_zigzag_subdivision=", [](RubyHeightfieldShape& self, bool enabled) {
478
+ self.setUseZigzagSubdivision(enabled);
479
+ return enabled;
480
+ })
481
+ .define_method("flip_triangle_winding=", [](RubyHeightfieldShape& self, bool enabled) {
482
+ self.setFlipTriangleWinding(enabled);
483
+ return enabled;
484
+ });
485
+ }
@@ -0,0 +1,5 @@
1
+ #pragma once
2
+
3
+ #include <rice/rice.hpp>
4
+
5
+ void Init_Shapes(Rice::Module rb_mBullet);