Skip to content

Commit

Permalink
Merge pull request #13 from Demindiro/lock
Browse files Browse the repository at this point in the history
  • Loading branch information
Demindiro authored Apr 18, 2021
2 parents 8580c27 + bf1d6e6 commit 325d006
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 45 deletions.
34 changes: 17 additions & 17 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions module/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,10 @@
'free': ('void', [
('index_t', 'id')
]),
'space_get_contact': ('godot_vector3', [
'space_get_contact': ('void', [
('index_t', 'space'),
('size_t', 'id'),
('int', 'id'),
('godot_vector3 *', 'out'),
]),
'space_intersect_ray': ('bool', [
('index_t', 'space'),
Expand Down
2 changes: 1 addition & 1 deletion module/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ Vector<Vector3> PluggablePhysicsServer::space_get_contacts(RID space) const {
contacts.resize(count);
Vector3 *contacts_ptr = contacts.ptrw();
for (size_t i = 0; i < count; i++) {
contacts_ptr[i] = (*this->fn_table.space_get_contact)(id, i);
(*this->fn_table.space_get_contact)(id, i, &contacts_ptr[i]);
}
return contacts;
}
Expand Down
2 changes: 1 addition & 1 deletion rapier3d/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ edition = "2018"
name = "godot_rapier3d"

[dependencies]
rapier3d = { git = "https://github.com/Demindiro/rapier", branch = "interaction-groups-or", version = "*", features = ["simd-nightly"] }
rapier3d = { git = "https://github.com/Demindiro/rapier", branch = "godot", version = "*", features = ["simd-nightly"] }
gdnative = "*"
lazy_static = "*"

Expand Down
40 changes: 38 additions & 2 deletions rapier3d/src/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ use crate::space::Space;
use crate::util::*;
use core::convert::{TryFrom, TryInto};
use gdnative::core_types::*;
use rapier3d::dynamics::{BodyStatus, MassProperties, RigidBody, RigidBodyHandle, RigidBodySet};
use rapier3d::dynamics::{BodyStatus, MassProperties, RigidBody, RigidBodyHandle, RigidBodySet, Axis};
use rapier3d::geometry::{
Collider, ColliderBuilder, ColliderHandle, InteractionGroups, SharedShape,
};
use rapier3d::math::Isometry;
use rapier3d::na::Point3;
use rapier3d::na::{self, Point3};

pub struct BodyShape {
index: ShapeIndex,
Expand Down Expand Up @@ -51,6 +51,8 @@ pub struct Body {
restitution: f32,
friction: f32,

mass_properties: MassProperties,

inertia_stale: bool,

area_gravity: Option<Vector3>,
Expand Down Expand Up @@ -88,6 +90,8 @@ impl Body {
restitution: 0.0,
friction: 1.0,

mass_properties: MassProperties::new(Point3::origin(), 1.0, na::Vector3::zeros()),

inertia_stale: false,

area_gravity: None,
Expand Down Expand Up @@ -703,6 +707,7 @@ impl Body {

/// Sets the mass of this body
pub fn set_mass(&mut self, mass: f32) {
self.mass_properties.set_mass(mass, true);
self.map_rigidbody_mut(|body| {
let mut p = *body.mass_properties();
p.inv_mass = 1.0 / mass;
Expand Down Expand Up @@ -809,6 +814,37 @@ impl Body {
pub fn enable_ccd(&mut self, enable: bool) {
self.map_rigidbody_mut(|body| body.enable_ccd(enable));
}

/// Locks this body in place at it's current position, which prevents it from being pushed
/// by external forces. It may still rotate around it's origin.
pub fn set_translation_lock(&mut self, lock: bool) {
self.map_rigidbody_mut(|body| {
body.set_translation_locked(lock)
});
}

/// Prevents this body from rotating due to external forces. It can
/// still be translated however. The axis is defined in global space.
pub fn set_rotation_lock(&mut self, axis: Axis, lock: bool) {
self.map_rigidbody_mut(|body| {
body.set_rotation_locked(axis, lock)
});
}

/// Returns whether this body is locked in place
pub fn is_translation_locked(&self) -> bool {
self.map_rigidbody(|body| body.is_translation_locked())
}

/// Returns whether the given local axis of this body is locked
pub fn is_rotation_locked(&self, axis: Axis) -> bool {
let axis = match axis {
Axis::X => 0,
Axis::Y => 1,
Axis::Z => 2,
};
self.map_rigidbody(|body| body.is_rotation_locked()[axis])
}
}

impl ContactEvent {
Expand Down
78 changes: 65 additions & 13 deletions rapier3d/src/server/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::body::Body;
use crate::util::*;
use gdnative::core_types::*;
use gdnative::godot_error;
use rapier3d::dynamics::{ActivationStatus, BodyStatus, RigidBody, RigidBodyBuilder};
use rapier3d::dynamics::{ActivationStatus, BodyStatus, RigidBody, RigidBodyBuilder, Axis};

#[derive(Debug)]
enum Type {
Expand Down Expand Up @@ -40,6 +40,11 @@ enum Mode {
Character,
}

enum BodyAxis {
Linear(Axis),
Angular(Axis),
}

#[derive(Debug)]
enum StateError {
InvalidType,
Expand All @@ -49,6 +54,9 @@ enum StateError {
#[derive(Debug)]
struct InvalidMode;

#[derive(Debug)]
struct InvalidAxis;

impl Type {
fn new(n: i32) -> Result<Type, ()> {
Ok(match n {
Expand All @@ -68,8 +76,8 @@ impl Type {
Type::Character => RigidBodyBuilder::new_dynamic(),
}
.sleeping(sleep)
.additional_mass(1.0)
.build()
.additional_mass(1.0)
.build()
}
}

Expand Down Expand Up @@ -112,6 +120,21 @@ impl Mode {
}
}

impl BodyAxis {
fn new(n: i32) -> Result<Self, InvalidAxis> {
// TODO is it possible that multiplpe axises can be specified at once?
Ok(match n {
1 => Self::Linear(Axis::X),
2 => Self::Linear(Axis::Y),
4 => Self::Linear(Axis::Z),
8 => Self::Angular(Axis::X),
16 => Self::Angular(Axis::Y),
32 => Self::Angular(Axis::Z),
_ => return Err(InvalidAxis),
})
}
}

pub fn init(ffi: &mut ffi::FFI) {
ffi!(ffi, body_add_force, add_force);
ffi!(ffi, body_add_shape, add_shape);
Expand All @@ -121,36 +144,38 @@ pub fn init(ffi: &mut ffi::FFI) {
ffi,
body_attach_object_instance_id,
attach_object_instance_id
);
);
ffi!(ffi, body_create, create);
ffi!(
ffi,
body_is_continuous_collision_detection_enabled,
is_continuous_collision_detection_enabled
);
);
ffi!(ffi, body_get_contact, get_contact);
ffi!(ffi, body_get_direct_state, get_direct_state);
ffi!(ffi, body_get_kinematic_safe_margin, |_| 0.0);
ffi!(ffi, body_is_axis_locked, is_axis_locked);
ffi!(ffi, body_remove_shape, remove_shape);
ffi!(ffi, body_set_axis_lock, set_axis_lock);
ffi!(ffi, body_set_collision_layer, set_collision_layer);
ffi!(ffi, body_set_collision_mask, set_collision_mask);
ffi!(
ffi,
body_set_enable_continuous_collision_detection,
set_enable_continuous_collision_detection
);
);
ffi!(ffi, body_set_kinematic_safe_margin, |_, _| ());
ffi!(
ffi,
body_set_max_contacts_reported,
set_max_contacts_reported
);
);
ffi!(ffi, body_set_mode, set_mode);
ffi!(
ffi,
body_set_omit_force_integration,
set_omit_force_integration
);
);
ffi!(ffi, body_set_param, set_param);
ffi!(ffi, body_set_shape_transform, set_shape_transform);
ffi!(ffi, body_set_shape_disabled, set_shape_disabled);
Expand Down Expand Up @@ -225,7 +250,7 @@ fn apply_impulse(body: Index, position: &Vector3, impulse: &Vector3) {

fn attach_object_instance_id(body: Index, id: u32) {
map_or_err!(body, map_body_mut, |b, _| b
.set_object_id(ObjectID::new(id)));
.set_object_id(ObjectID::new(id)));
}

fn get_direct_state(body: Index, state: &mut ffi::PhysicsBodyState) {
Expand Down Expand Up @@ -271,7 +296,7 @@ fn get_contact(body: Index, id: u32, contact: &mut ffi::PhysicsBodyContact) {

fn remove_shape(body: Index, shape: i32) {
map_or_err!(body, map_body_mut, |body, _| body
.remove_shape(shape as u32));
.remove_shape(shape as u32));
}

fn set_param(body: Index, param: i32, value: f32) {
Expand Down Expand Up @@ -319,18 +344,18 @@ fn set_mode(body: Index, mode: i32) {

fn set_omit_force_integration(body: Index, enable: bool) {
map_or_err!(body, map_body_mut, |body, _| body
.set_omit_force_integration(enable));
.set_omit_force_integration(enable));
}

fn set_shape_transform(body: Index, shape: i32, transform: &Transform) {
let shape = shape as u32;
map_or_err!(body, map_body_mut, |body, _| body
.set_shape_transform(shape, transform));
.set_shape_transform(shape, transform));
}

fn set_shape_disabled(body: Index, shape: i32, disable: bool) {
map_or_err!(body, map_body_mut, |body, _| body
.set_shape_enable(shape as u32, !disable));
.set_shape_enable(shape as u32, !disable));
}

fn set_space(body: Index, space: Option<Index>) {
Expand Down Expand Up @@ -379,6 +404,33 @@ fn set_enable_continuous_collision_detection(body: Index, enable: bool) {
map_or_err!(body, map_body_mut, |body, _| body.enable_ccd(enable));
}

fn set_axis_lock(body: Index, axis: i32, lock: bool) {
if let Ok(axis) = BodyAxis::new(axis) {
map_or_err!(body, map_body_mut, |body, _| {
match axis {
BodyAxis::Linear(_) => body.set_translation_lock(lock),
BodyAxis::Angular(axis) => body.set_rotation_lock(axis, lock),
}
});
} else {
godot_error!("Invalid axis");
}
}

fn is_axis_locked(body: Index, axis: i32) -> bool {
if let Ok(axis) = BodyAxis::new(axis) {
map_or_err!(body, map_body, |body, _| {
match axis {
BodyAxis::Linear(_) => body.is_translation_locked(),
BodyAxis::Angular(axis) => body.is_rotation_locked(axis),
}
}).unwrap_or(false)
} else {
godot_error!("Invalid axis");
false
}
}

/// Godot's "It's local position but global rotation" is such a mindfuck that this function exists
/// to help out
fn transform_force_arguments(
Expand Down
Loading

0 comments on commit 325d006

Please sign in to comment.