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,180 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <memory>
|
|
4
|
+
#include <unordered_map>
|
|
5
|
+
#include <unordered_set>
|
|
6
|
+
|
|
7
|
+
#include <btBulletDynamicsCommon.h>
|
|
8
|
+
#include <rice/rice.hpp>
|
|
9
|
+
|
|
10
|
+
#include "../linear_math/rb_transform.hpp"
|
|
11
|
+
#include "../util/rb_debug_draw.hpp"
|
|
12
|
+
|
|
13
|
+
namespace bullet3 {
|
|
14
|
+
class RaycastVehicle;
|
|
15
|
+
|
|
16
|
+
class CollisionConfiguration {
|
|
17
|
+
public:
|
|
18
|
+
CollisionConfiguration();
|
|
19
|
+
|
|
20
|
+
btDefaultCollisionConfiguration* get();
|
|
21
|
+
|
|
22
|
+
private:
|
|
23
|
+
std::unique_ptr<btDefaultCollisionConfiguration> configuration_;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
class CollisionDispatcher {
|
|
27
|
+
public:
|
|
28
|
+
explicit CollisionDispatcher(CollisionConfiguration& configuration);
|
|
29
|
+
|
|
30
|
+
btCollisionDispatcher* get();
|
|
31
|
+
|
|
32
|
+
private:
|
|
33
|
+
std::unique_ptr<btCollisionDispatcher> dispatcher_;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
class DbvtBroadphase {
|
|
37
|
+
public:
|
|
38
|
+
DbvtBroadphase();
|
|
39
|
+
|
|
40
|
+
btDbvtBroadphase* get();
|
|
41
|
+
|
|
42
|
+
private:
|
|
43
|
+
std::unique_ptr<btDbvtBroadphase> broadphase_;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
class SequentialImpulseConstraintSolver {
|
|
47
|
+
public:
|
|
48
|
+
SequentialImpulseConstraintSolver();
|
|
49
|
+
|
|
50
|
+
btSequentialImpulseConstraintSolver* get();
|
|
51
|
+
|
|
52
|
+
private:
|
|
53
|
+
std::unique_ptr<btSequentialImpulseConstraintSolver> solver_;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
class MotionState {
|
|
57
|
+
public:
|
|
58
|
+
MotionState();
|
|
59
|
+
explicit MotionState(VALUE start_transform);
|
|
60
|
+
|
|
61
|
+
btMotionState* get();
|
|
62
|
+
Transform world_transform() const;
|
|
63
|
+
Transform set_world_transform(Rice::Object transform);
|
|
64
|
+
|
|
65
|
+
private:
|
|
66
|
+
std::unique_ptr<btDefaultMotionState> motion_state_;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
class RigidBodyConstructionInfo {
|
|
70
|
+
public:
|
|
71
|
+
RigidBodyConstructionInfo(btScalar mass, MotionState& motion_state, VALUE collision_shape);
|
|
72
|
+
RigidBodyConstructionInfo(btScalar mass, MotionState& motion_state, VALUE collision_shape, VALUE local_inertia);
|
|
73
|
+
|
|
74
|
+
btRigidBody::btRigidBodyConstructionInfo& get();
|
|
75
|
+
btScalar mass() const;
|
|
76
|
+
btVector3 local_inertia() const;
|
|
77
|
+
btScalar friction() const;
|
|
78
|
+
btScalar set_friction(btScalar friction);
|
|
79
|
+
btScalar restitution() const;
|
|
80
|
+
btScalar set_restitution(btScalar restitution);
|
|
81
|
+
|
|
82
|
+
private:
|
|
83
|
+
btVector3 local_inertia_;
|
|
84
|
+
std::unique_ptr<btRigidBody::btRigidBodyConstructionInfo> info_;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
class RigidBody {
|
|
88
|
+
public:
|
|
89
|
+
explicit RigidBody(RigidBodyConstructionInfo& construction_info);
|
|
90
|
+
|
|
91
|
+
btRigidBody* get();
|
|
92
|
+
const btRigidBody* get() const;
|
|
93
|
+
|
|
94
|
+
btScalar mass() const;
|
|
95
|
+
btCollisionShape* collision_shape() const;
|
|
96
|
+
Transform world_transform() const;
|
|
97
|
+
Transform set_world_transform(Rice::Object transform);
|
|
98
|
+
btVector3 linear_velocity() const;
|
|
99
|
+
btVector3 set_linear_velocity(Rice::Object velocity);
|
|
100
|
+
btVector3 angular_velocity() const;
|
|
101
|
+
btVector3 set_angular_velocity(Rice::Object velocity);
|
|
102
|
+
btVector3 total_force() const;
|
|
103
|
+
btVector3 total_torque() const;
|
|
104
|
+
btScalar friction() const;
|
|
105
|
+
btScalar set_friction(btScalar friction);
|
|
106
|
+
btScalar restitution() const;
|
|
107
|
+
btScalar set_restitution(btScalar restitution);
|
|
108
|
+
Rice::Array damping() const;
|
|
109
|
+
Rice::Array set_damping(btScalar linear_damping, btScalar angular_damping);
|
|
110
|
+
void apply_central_force(Rice::Object force);
|
|
111
|
+
void apply_force(Rice::Object force, Rice::Object relative_position);
|
|
112
|
+
void apply_torque(Rice::Object torque);
|
|
113
|
+
void apply_central_impulse(Rice::Object impulse);
|
|
114
|
+
void apply_impulse(Rice::Object impulse, Rice::Object relative_position);
|
|
115
|
+
void clear_forces();
|
|
116
|
+
void activate();
|
|
117
|
+
bool active() const;
|
|
118
|
+
bool static_object() const;
|
|
119
|
+
bool kinematic_object() const;
|
|
120
|
+
|
|
121
|
+
private:
|
|
122
|
+
std::unique_ptr<btRigidBody> rigid_body_;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
class DiscreteDynamicsWorld {
|
|
126
|
+
public:
|
|
127
|
+
DiscreteDynamicsWorld();
|
|
128
|
+
DiscreteDynamicsWorld(CollisionDispatcher& dispatcher,
|
|
129
|
+
DbvtBroadphase& broadphase,
|
|
130
|
+
SequentialImpulseConstraintSolver& solver,
|
|
131
|
+
CollisionConfiguration& configuration);
|
|
132
|
+
~DiscreteDynamicsWorld();
|
|
133
|
+
|
|
134
|
+
btDiscreteDynamicsWorld* get();
|
|
135
|
+
btVector3 gravity() const;
|
|
136
|
+
btVector3 set_gravity(Rice::Object gravity);
|
|
137
|
+
void add_rigid_body(RigidBody& rigid_body);
|
|
138
|
+
void add_rigid_body_object(VALUE rigid_body);
|
|
139
|
+
void remove_rigid_body(RigidBody& rigid_body);
|
|
140
|
+
void remove_rigid_body_object(VALUE rigid_body);
|
|
141
|
+
void add_constraint_object(VALUE constraint, bool disable_collisions_between_linked_bodies);
|
|
142
|
+
void remove_constraint_object(VALUE constraint);
|
|
143
|
+
void add_vehicle_object(VALUE vehicle);
|
|
144
|
+
void remove_vehicle_object(VALUE vehicle);
|
|
145
|
+
int step_simulation(btScalar time_step, int max_sub_steps, btScalar fixed_time_step);
|
|
146
|
+
int num_collision_objects() const;
|
|
147
|
+
int num_constraints() const;
|
|
148
|
+
void clear_forces();
|
|
149
|
+
void synchronize_motion_states();
|
|
150
|
+
Rice::Object ray_test_closest(Rice::Object from, Rice::Object to) const;
|
|
151
|
+
Rice::Array ray_test_all(Rice::Object from, Rice::Object to) const;
|
|
152
|
+
Rice::Array contact_test(VALUE rigid_body) const;
|
|
153
|
+
Rice::Array contact_pair_test(VALUE rigid_body_a, VALUE rigid_body_b) const;
|
|
154
|
+
Rice::Array closest_points(VALUE rigid_body_a, VALUE rigid_body_b, btScalar distance_threshold) const;
|
|
155
|
+
Rice::Array contact_manifolds() const;
|
|
156
|
+
void set_debug_drawer(VALUE debug_drawer);
|
|
157
|
+
VALUE debug_drawer() const;
|
|
158
|
+
void debug_draw_world();
|
|
159
|
+
void mark() const;
|
|
160
|
+
|
|
161
|
+
private:
|
|
162
|
+
void build_owned_world();
|
|
163
|
+
VALUE ruby_object_for(const btCollisionObject* collision_object) const;
|
|
164
|
+
|
|
165
|
+
std::unique_ptr<btDefaultCollisionConfiguration> owned_configuration_;
|
|
166
|
+
std::unique_ptr<btCollisionDispatcher> owned_dispatcher_;
|
|
167
|
+
std::unique_ptr<btDbvtBroadphase> owned_broadphase_;
|
|
168
|
+
std::unique_ptr<btSequentialImpulseConstraintSolver> owned_solver_;
|
|
169
|
+
std::unique_ptr<btDiscreteDynamicsWorld> world_;
|
|
170
|
+
std::unordered_set<btRigidBody*> rigid_bodies_;
|
|
171
|
+
std::unordered_set<btTypedConstraint*> constraints_;
|
|
172
|
+
std::unordered_set<btActionInterface*> actions_;
|
|
173
|
+
std::unordered_map<const btCollisionObject*, VALUE> collision_object_values_;
|
|
174
|
+
std::unordered_map<const btTypedConstraint*, VALUE> constraint_values_;
|
|
175
|
+
std::unordered_map<const btActionInterface*, VALUE> action_values_;
|
|
176
|
+
VALUE debug_drawer_value_ = Qnil;
|
|
177
|
+
};
|
|
178
|
+
} // namespace bullet3
|
|
179
|
+
|
|
180
|
+
void Init_Dynamics(Rice::Module rb_mBullet);
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "mkmf"
|
|
5
|
+
require "rbconfig"
|
|
6
|
+
|
|
7
|
+
extension_name = "bullet3"
|
|
8
|
+
extension_suffix = RbConfig::CONFIG.fetch("DLEXT")
|
|
9
|
+
source_dir = __dir__
|
|
10
|
+
build_dir = File.expand_path("build", source_dir)
|
|
11
|
+
output_dir = File.expand_path("../../lib/bullet3", source_dir)
|
|
12
|
+
staging_extension = File.expand_path("#{extension_name}.#{extension_suffix}", Dir.pwd)
|
|
13
|
+
|
|
14
|
+
cmake_args = [
|
|
15
|
+
"-S", source_dir,
|
|
16
|
+
"-B", build_dir,
|
|
17
|
+
"-DCMAKE_BUILD_TYPE=#{ENV.fetch("BULLET3_BUILD_TYPE", "Release")}",
|
|
18
|
+
"-DRUBY_EXECUTABLE=#{RbConfig.ruby}",
|
|
19
|
+
"-DRUBY_EXTENSION_SUFFIX=.#{extension_suffix}"
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
if ENV["BULLET3_SKIP_NATIVE"] == "1"
|
|
23
|
+
File.write("Makefile", <<~MAKEFILE)
|
|
24
|
+
all:
|
|
25
|
+
|
|
26
|
+
install:
|
|
27
|
+
|
|
28
|
+
clean:
|
|
29
|
+
|
|
30
|
+
MAKEFILE
|
|
31
|
+
exit
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
abort "CMake is required to build bullet3" unless find_executable("cmake")
|
|
35
|
+
|
|
36
|
+
FileUtils.mkdir_p(build_dir)
|
|
37
|
+
system("cmake", *cmake_args) || abort("cmake configure failed")
|
|
38
|
+
system(
|
|
39
|
+
"cmake",
|
|
40
|
+
"--build", build_dir,
|
|
41
|
+
"--target", extension_name,
|
|
42
|
+
"--config", ENV.fetch("BULLET3_BUILD_TYPE", "Release")
|
|
43
|
+
) || abort("cmake build failed")
|
|
44
|
+
|
|
45
|
+
FileUtils.mkdir_p(output_dir)
|
|
46
|
+
built_extension = File.join(build_dir, "#{extension_name}.#{extension_suffix}")
|
|
47
|
+
FileUtils.cp(built_extension, staging_extension)
|
|
48
|
+
FileUtils.cp(built_extension, File.join(output_dir, "#{extension_name}.#{extension_suffix}"))
|
|
49
|
+
|
|
50
|
+
File.write("Makefile", <<~MAKEFILE)
|
|
51
|
+
all:
|
|
52
|
+
|
|
53
|
+
install:
|
|
54
|
+
|
|
55
|
+
clean:
|
|
56
|
+
|
|
57
|
+
MAKEFILE
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#include "rb_io.hpp"
|
|
2
|
+
|
|
3
|
+
#include <fstream>
|
|
4
|
+
#include <stdexcept>
|
|
5
|
+
|
|
6
|
+
#include <LinearMath/btSerializer.h>
|
|
7
|
+
|
|
8
|
+
#ifdef BULLET3_WITH_WORLD_IMPORTER
|
|
9
|
+
#include <btBulletWorldImporter.h>
|
|
10
|
+
#endif
|
|
11
|
+
|
|
12
|
+
namespace bullet3 {
|
|
13
|
+
VALUE DefaultSerializer::serialize_world(DiscreteDynamicsWorld& world) const
|
|
14
|
+
{
|
|
15
|
+
btDefaultSerializer serializer;
|
|
16
|
+
world.get()->serialize(&serializer);
|
|
17
|
+
return rb_str_new(
|
|
18
|
+
reinterpret_cast<const char*>(serializer.getBufferPointer()),
|
|
19
|
+
serializer.getCurrentBufferSize());
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
std::string DefaultSerializer::save_world(DiscreteDynamicsWorld& world, const std::string& filename) const
|
|
23
|
+
{
|
|
24
|
+
VALUE serialized = serialize_world(world);
|
|
25
|
+
std::ofstream output(filename, std::ios::binary);
|
|
26
|
+
if (!output) {
|
|
27
|
+
throw std::runtime_error("failed to open .bullet file for writing: " + filename);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
output.write(RSTRING_PTR(serialized), RSTRING_LEN(serialized));
|
|
31
|
+
if (!output) {
|
|
32
|
+
throw std::runtime_error("failed to write .bullet file: " + filename);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return filename;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
#ifdef BULLET3_WITH_WORLD_IMPORTER
|
|
39
|
+
BulletWorldImporter::BulletWorldImporter(DiscreteDynamicsWorld& world)
|
|
40
|
+
: importer_(std::make_unique<btBulletWorldImporter>(world.get()))
|
|
41
|
+
{
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
BulletWorldImporter::~BulletWorldImporter() = default;
|
|
45
|
+
|
|
46
|
+
bool BulletWorldImporter::load_file(const std::string& filename)
|
|
47
|
+
{
|
|
48
|
+
return importer_->loadFile(filename.c_str());
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
void BulletWorldImporter::delete_all_data()
|
|
52
|
+
{
|
|
53
|
+
importer_->deleteAllData();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
int BulletWorldImporter::verbose_mode() const
|
|
57
|
+
{
|
|
58
|
+
return importer_->getVerboseMode();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
int BulletWorldImporter::set_verbose_mode(int verbose_mode)
|
|
62
|
+
{
|
|
63
|
+
importer_->setVerboseMode(verbose_mode);
|
|
64
|
+
return verbose_mode;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
int BulletWorldImporter::num_collision_shapes() const
|
|
68
|
+
{
|
|
69
|
+
return importer_->getNumCollisionShapes();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
int BulletWorldImporter::num_rigid_bodies() const
|
|
73
|
+
{
|
|
74
|
+
return importer_->getNumRigidBodies();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
int BulletWorldImporter::num_constraints() const
|
|
78
|
+
{
|
|
79
|
+
return importer_->getNumConstraints();
|
|
80
|
+
}
|
|
81
|
+
#endif
|
|
82
|
+
} // namespace bullet3
|
|
83
|
+
|
|
84
|
+
void Init_IO(Rice::Module rb_mBullet)
|
|
85
|
+
{
|
|
86
|
+
Rice::Module rb_mIO = Rice::define_module_under(rb_mBullet, "IO");
|
|
87
|
+
|
|
88
|
+
Rice::define_class_under<bullet3::DefaultSerializer>(rb_mIO, "DefaultSerializer")
|
|
89
|
+
.define_constructor(Rice::Constructor<bullet3::DefaultSerializer>())
|
|
90
|
+
.define_method("serialize_world", &bullet3::DefaultSerializer::serialize_world,
|
|
91
|
+
Rice::Arg("world").keepAlive())
|
|
92
|
+
.define_method("save_world", &bullet3::DefaultSerializer::save_world,
|
|
93
|
+
Rice::Arg("world").keepAlive(),
|
|
94
|
+
Rice::Arg("filename"));
|
|
95
|
+
|
|
96
|
+
#ifdef BULLET3_WITH_WORLD_IMPORTER
|
|
97
|
+
Rice::define_class_under<bullet3::BulletWorldImporter>(rb_mIO, "BulletWorldImporter")
|
|
98
|
+
.define_constructor(Rice::Constructor<bullet3::BulletWorldImporter, bullet3::DiscreteDynamicsWorld&>(),
|
|
99
|
+
Rice::Arg("world").keepAlive())
|
|
100
|
+
.define_method("load_file", &bullet3::BulletWorldImporter::load_file)
|
|
101
|
+
.define_method("delete_all_data", &bullet3::BulletWorldImporter::delete_all_data)
|
|
102
|
+
.define_method("verbose_mode", &bullet3::BulletWorldImporter::verbose_mode)
|
|
103
|
+
.define_method("verbose_mode=", &bullet3::BulletWorldImporter::set_verbose_mode)
|
|
104
|
+
.define_method("num_collision_shapes", &bullet3::BulletWorldImporter::num_collision_shapes)
|
|
105
|
+
.define_method("num_rigid_bodies", &bullet3::BulletWorldImporter::num_rigid_bodies)
|
|
106
|
+
.define_method("num_constraints", &bullet3::BulletWorldImporter::num_constraints);
|
|
107
|
+
#endif
|
|
108
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <memory>
|
|
4
|
+
#include <string>
|
|
5
|
+
|
|
6
|
+
#include <rice/rice.hpp>
|
|
7
|
+
#include <rice/stl.hpp>
|
|
8
|
+
|
|
9
|
+
#include "../dynamics/rb_dynamics.hpp"
|
|
10
|
+
|
|
11
|
+
class btBulletWorldImporter;
|
|
12
|
+
|
|
13
|
+
namespace bullet3 {
|
|
14
|
+
class DefaultSerializer {
|
|
15
|
+
public:
|
|
16
|
+
VALUE serialize_world(DiscreteDynamicsWorld& world) const;
|
|
17
|
+
std::string save_world(DiscreteDynamicsWorld& world, const std::string& filename) const;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
#ifdef BULLET3_WITH_WORLD_IMPORTER
|
|
21
|
+
class BulletWorldImporter {
|
|
22
|
+
public:
|
|
23
|
+
explicit BulletWorldImporter(DiscreteDynamicsWorld& world);
|
|
24
|
+
~BulletWorldImporter();
|
|
25
|
+
|
|
26
|
+
bool load_file(const std::string& filename);
|
|
27
|
+
void delete_all_data();
|
|
28
|
+
int verbose_mode() const;
|
|
29
|
+
int set_verbose_mode(int verbose_mode);
|
|
30
|
+
int num_collision_shapes() const;
|
|
31
|
+
int num_rigid_bodies() const;
|
|
32
|
+
int num_constraints() const;
|
|
33
|
+
|
|
34
|
+
private:
|
|
35
|
+
std::unique_ptr<btBulletWorldImporter> importer_;
|
|
36
|
+
};
|
|
37
|
+
#endif
|
|
38
|
+
} // namespace bullet3
|
|
39
|
+
|
|
40
|
+
void Init_IO(Rice::Module rb_mBullet);
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#include "rb_matrix3x3.hpp"
|
|
2
|
+
|
|
3
|
+
#include <stdexcept>
|
|
4
|
+
|
|
5
|
+
#include <LinearMath/btMatrix3x3.h>
|
|
6
|
+
#include <LinearMath/btQuaternion.h>
|
|
7
|
+
#include <LinearMath/btVector3.h>
|
|
8
|
+
#include <rice/rice.hpp>
|
|
9
|
+
|
|
10
|
+
namespace {
|
|
11
|
+
template <typename Value_T>
|
|
12
|
+
btScalar scalar_from_object(Value_T object)
|
|
13
|
+
{
|
|
14
|
+
return Rice::detail::From_Ruby<btScalar>().convert(object);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
btVector3 vector_from_array(Rice::Object object)
|
|
18
|
+
{
|
|
19
|
+
Rice::Array array(object);
|
|
20
|
+
if (array.size() != 3) {
|
|
21
|
+
throw std::invalid_argument("expected a 3-element Array");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return btVector3(
|
|
25
|
+
scalar_from_object(array[0]),
|
|
26
|
+
scalar_from_object(array[1]),
|
|
27
|
+
scalar_from_object(array[2])
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
btVector3 coerce_vector(Rice::Object object)
|
|
32
|
+
{
|
|
33
|
+
if (rb_obj_is_kind_of(object.value(), rb_cArray)) {
|
|
34
|
+
return vector_from_array(object);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return *Rice::detail::From_Ruby<btVector3*>().convert(object);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
btQuaternion coerce_quaternion(Rice::Object object)
|
|
41
|
+
{
|
|
42
|
+
if (rb_obj_is_kind_of(object.value(), rb_cArray)) {
|
|
43
|
+
Rice::Array array(object);
|
|
44
|
+
if (array.size() != 4) {
|
|
45
|
+
throw std::invalid_argument("expected a 4-element Array");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return btQuaternion(
|
|
49
|
+
scalar_from_object(array[0]),
|
|
50
|
+
scalar_from_object(array[1]),
|
|
51
|
+
scalar_from_object(array[2]),
|
|
52
|
+
scalar_from_object(array[3])
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return *Rice::detail::From_Ruby<btQuaternion*>().convert(object);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
Rice::Array matrix_to_array(const btMatrix3x3& matrix)
|
|
60
|
+
{
|
|
61
|
+
Rice::Array rows;
|
|
62
|
+
for (int row_index = 0; row_index < 3; ++row_index) {
|
|
63
|
+
Rice::Array row;
|
|
64
|
+
const btVector3& vector = matrix.getRow(row_index);
|
|
65
|
+
row.push(vector.getX());
|
|
66
|
+
row.push(vector.getY());
|
|
67
|
+
row.push(vector.getZ());
|
|
68
|
+
rows.push(row);
|
|
69
|
+
}
|
|
70
|
+
return rows;
|
|
71
|
+
}
|
|
72
|
+
} // namespace
|
|
73
|
+
|
|
74
|
+
void Init_Matrix3x3(Rice::Module rb_mBullet)
|
|
75
|
+
{
|
|
76
|
+
Rice::define_class_under<btMatrix3x3>(rb_mBullet, "Matrix3x3")
|
|
77
|
+
.define_constructor(Rice::Constructor<btMatrix3x3,
|
|
78
|
+
btScalar, btScalar, btScalar,
|
|
79
|
+
btScalar, btScalar, btScalar,
|
|
80
|
+
btScalar, btScalar, btScalar>(),
|
|
81
|
+
Rice::Arg("xx") = 1.0, Rice::Arg("xy") = 0.0, Rice::Arg("xz") = 0.0,
|
|
82
|
+
Rice::Arg("yx") = 0.0, Rice::Arg("yy") = 1.0, Rice::Arg("yz") = 0.0,
|
|
83
|
+
Rice::Arg("zx") = 0.0, Rice::Arg("zy") = 0.0, Rice::Arg("zz") = 1.0)
|
|
84
|
+
.define_singleton_method("identity", [](Rice::Object) { return btMatrix3x3::getIdentity(); })
|
|
85
|
+
.define_singleton_method("from_quaternion", [](Rice::Object, Rice::Object quaternion) {
|
|
86
|
+
return btMatrix3x3(coerce_quaternion(quaternion));
|
|
87
|
+
})
|
|
88
|
+
.define_method("*", [](const btMatrix3x3& self, Rice::Object vector) {
|
|
89
|
+
return self * coerce_vector(vector);
|
|
90
|
+
})
|
|
91
|
+
.define_method("transpose", &btMatrix3x3::transpose)
|
|
92
|
+
.define_method("to_a", &matrix_to_array);
|
|
93
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
#include "rb_quaternion.hpp"
|
|
2
|
+
|
|
3
|
+
#include <cmath>
|
|
4
|
+
#include <stdexcept>
|
|
5
|
+
|
|
6
|
+
#include <LinearMath/btMatrix3x3.h>
|
|
7
|
+
#include <LinearMath/btQuaternion.h>
|
|
8
|
+
#include <LinearMath/btVector3.h>
|
|
9
|
+
#include <rice/rice.hpp>
|
|
10
|
+
|
|
11
|
+
namespace {
|
|
12
|
+
constexpr btScalar kEpsilon = btScalar(1e-6);
|
|
13
|
+
|
|
14
|
+
template <typename Value_T>
|
|
15
|
+
btScalar scalar_from_object(Value_T object)
|
|
16
|
+
{
|
|
17
|
+
return Rice::detail::From_Ruby<btScalar>().convert(object);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
btVector3 vector_from_array(Rice::Object object)
|
|
21
|
+
{
|
|
22
|
+
Rice::Array array(object);
|
|
23
|
+
if (array.size() != 3) {
|
|
24
|
+
throw std::invalid_argument("expected a 3-element Array");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return btVector3(
|
|
28
|
+
scalar_from_object(array[0]),
|
|
29
|
+
scalar_from_object(array[1]),
|
|
30
|
+
scalar_from_object(array[2])
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
btVector3 coerce_vector(Rice::Object object)
|
|
35
|
+
{
|
|
36
|
+
if (rb_obj_is_kind_of(object.value(), rb_cArray)) {
|
|
37
|
+
return vector_from_array(object);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return *Rice::detail::From_Ruby<btVector3*>().convert(object);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
btQuaternion quaternion_from_array(Rice::Object object)
|
|
44
|
+
{
|
|
45
|
+
Rice::Array array(object);
|
|
46
|
+
if (array.size() != 4) {
|
|
47
|
+
throw std::invalid_argument("expected a 4-element Array");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return btQuaternion(
|
|
51
|
+
scalar_from_object(array[0]),
|
|
52
|
+
scalar_from_object(array[1]),
|
|
53
|
+
scalar_from_object(array[2]),
|
|
54
|
+
scalar_from_object(array[3])
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
btQuaternion coerce_quaternion(Rice::Object object)
|
|
59
|
+
{
|
|
60
|
+
if (rb_obj_is_kind_of(object.value(), rb_cArray)) {
|
|
61
|
+
return quaternion_from_array(object);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return *Rice::detail::From_Ruby<btQuaternion*>().convert(object);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
Rice::Array quaternion_to_array(const btQuaternion& quaternion)
|
|
68
|
+
{
|
|
69
|
+
Rice::Array array;
|
|
70
|
+
array.push(quaternion.getX());
|
|
71
|
+
array.push(quaternion.getY());
|
|
72
|
+
array.push(quaternion.getZ());
|
|
73
|
+
array.push(quaternion.getW());
|
|
74
|
+
return array;
|
|
75
|
+
}
|
|
76
|
+
} // namespace
|
|
77
|
+
|
|
78
|
+
void Init_Quaternion(Rice::Module rb_mBullet)
|
|
79
|
+
{
|
|
80
|
+
Rice::define_class_under<btQuaternion>(rb_mBullet, "Quaternion")
|
|
81
|
+
.define_constructor(Rice::Constructor<btQuaternion, btScalar, btScalar, btScalar, btScalar>(),
|
|
82
|
+
Rice::Arg("x") = 0.0,
|
|
83
|
+
Rice::Arg("y") = 0.0,
|
|
84
|
+
Rice::Arg("z") = 0.0,
|
|
85
|
+
Rice::Arg("w") = 1.0)
|
|
86
|
+
.define_singleton_method("identity", [](Rice::Object) { return btQuaternion(0, 0, 0, 1); })
|
|
87
|
+
.define_singleton_method("from_axis_angle", [](Rice::Object, Rice::Object axis, btScalar angle) {
|
|
88
|
+
return btQuaternion(coerce_vector(axis), angle);
|
|
89
|
+
})
|
|
90
|
+
.define_singleton_method("from_euler", [](Rice::Object, btScalar roll, btScalar pitch, btScalar yaw) {
|
|
91
|
+
btQuaternion quaternion;
|
|
92
|
+
quaternion.setEulerZYX(yaw, pitch, roll);
|
|
93
|
+
return quaternion;
|
|
94
|
+
})
|
|
95
|
+
.define_method("x", &btQuaternion::getX)
|
|
96
|
+
.define_method("y", &btQuaternion::getY)
|
|
97
|
+
.define_method("z", &btQuaternion::getZ)
|
|
98
|
+
.define_method("w", &btQuaternion::getW)
|
|
99
|
+
.define_method("x=", &btQuaternion::setX)
|
|
100
|
+
.define_method("y=", &btQuaternion::setY)
|
|
101
|
+
.define_method("z=", &btQuaternion::setZ)
|
|
102
|
+
.define_method("w=", &btQuaternion::setW)
|
|
103
|
+
.define_method("*", [](const btQuaternion& self, Rice::Object other) {
|
|
104
|
+
return self * coerce_quaternion(other);
|
|
105
|
+
})
|
|
106
|
+
.define_method("==", [](const btQuaternion& self, Rice::Object other) {
|
|
107
|
+
btQuaternion quaternion = coerce_quaternion(other);
|
|
108
|
+
return std::fabs(self.getX() - quaternion.getX()) <= kEpsilon &&
|
|
109
|
+
std::fabs(self.getY() - quaternion.getY()) <= kEpsilon &&
|
|
110
|
+
std::fabs(self.getZ() - quaternion.getZ()) <= kEpsilon &&
|
|
111
|
+
std::fabs(self.getW() - quaternion.getW()) <= kEpsilon;
|
|
112
|
+
})
|
|
113
|
+
.define_method("inverse", &btQuaternion::inverse)
|
|
114
|
+
.define_method("angle", &btQuaternion::getAngle)
|
|
115
|
+
.define_method("axis", &btQuaternion::getAxis)
|
|
116
|
+
.define_method("slerp", [](const btQuaternion& self, Rice::Object other, btScalar t) {
|
|
117
|
+
return self.slerp(coerce_quaternion(other), t);
|
|
118
|
+
})
|
|
119
|
+
.define_method("to_euler", [](const btQuaternion& self) {
|
|
120
|
+
btScalar yaw;
|
|
121
|
+
btScalar pitch;
|
|
122
|
+
btScalar roll;
|
|
123
|
+
self.getEulerZYX(yaw, pitch, roll);
|
|
124
|
+
|
|
125
|
+
Rice::Array array;
|
|
126
|
+
array.push(roll);
|
|
127
|
+
array.push(pitch);
|
|
128
|
+
array.push(yaw);
|
|
129
|
+
return array;
|
|
130
|
+
})
|
|
131
|
+
.define_method("to_matrix", [](const btQuaternion& self) { return btMatrix3x3(self); })
|
|
132
|
+
.define_method("normalized", &btQuaternion::normalized)
|
|
133
|
+
.define_method("to_a", &quaternion_to_array);
|
|
134
|
+
}
|