Skip to content

Commit

Permalink
Fix CharacterBody2D Scale and Crash in v4.2 (#12)
Browse files Browse the repository at this point in the history
- Fixes #13
- Fixes #6
  • Loading branch information
Ughuuu authored Oct 26, 2023
1 parent 97f291d commit 4b6d034
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 64 deletions.
4 changes: 2 additions & 2 deletions .github/actions/build/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ runs:
path: |
${{ github.workspace }}/.scons-cache/
${{ github.workspace }}/godot-cpp/.scons-cache/
key: ${{ inputs.platform }}_${{ inputs.arch }}_${{ inputs.target }}_cache
key: ${{ inputs.platform }}_${{ inputs.arch }}_${{ inputs.target }}_${{ inputs.precision }}_cache
- uses: paulhatch/semantic-version@v5.3.0
id: version
with:
Expand All @@ -44,7 +44,7 @@ runs:
- name: Print version
shell: sh
run:
echo ${{ steps.version.outputs.version }} > bin/addons/godot-rapier2d/VERSION.txt
echo v${{ steps.version.outputs.version }} > bin/addons/godot-rapier2d/VERSION.txt
- name: Setup python and scons
uses: ./.github/actions/deps
- name: Lint
Expand Down
2 changes: 1 addition & 1 deletion bin/addons/godot-rapier2d/godot-rapier2d.gdextension
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[configuration]

entry_symbol = "physics_server_rapier_2d_library_init"
compatibility_minimum = 4.1
compatibility_minimum = 4.2


[libraries]
Expand Down
2 changes: 2 additions & 0 deletions src/rapier2d-wrapper/includes/rapier2d_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -459,9 +459,11 @@ ContactResult shapes_contact(Handle world_handle,
Handle shape_handle1,
const Vector *position1,
Real rotation1,
Vector scale1,
Handle shape_handle2,
const Vector *position2,
Real rotation2,
Vector scale2,
Real margin);

Handle world_create(const WorldSettings *settings);
Expand Down
86 changes: 43 additions & 43 deletions src/rapier2d-wrapper/src/collider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,48 @@ use crate::user_data::*;
use crate::vector::Vector;
use crate::physics_world::*;

pub fn scale_shape(shape: &SharedShape, scale: &Vector) -> Option<SharedShape> {
let shape_type = shape.shape_type();
if shape_type == ShapeType::Ball {
let new_shape = shape.as_ball().unwrap().scaled(&Vector2::<Real>::new(scale.x, scale.y), 20).unwrap();
if new_shape.is_left() {
let shape = new_shape.unwrap_left();
return Some(SharedShape::new(shape));
} else {
let shape = new_shape.unwrap_right();
return Some(SharedShape::new(shape));
}
}
else if shape_type == ShapeType::Cuboid {
let new_shape = shape.as_cuboid().unwrap().scaled(&Vector2::<Real>::new(scale.x, scale.y));
return Some(SharedShape::new(new_shape));
}
else if shape_type == ShapeType::HalfSpace {
let new_shape = shape.as_halfspace().unwrap().scaled(&Vector2::<Real>::new(scale.x, scale.y)).unwrap();
return Some(SharedShape::new(new_shape));
}
else if shape_type == ShapeType::Polyline {
let new_shape = shape.as_polyline().unwrap().clone().scaled(&Vector2::<Real>::new(scale.x, scale.y));
return Some(SharedShape::new(new_shape));
}
else if shape_type == ShapeType::ConvexPolygon {
let new_shape = shape.as_convex_polygon().unwrap().clone().scaled(&Vector2::<Real>::new(scale.x, scale.y)).unwrap();
return Some(SharedShape::new(new_shape));
}
else if shape_type == ShapeType::Compound {
let new_shapes = shape.as_compound().unwrap().shapes();
let mut shapes_vec = Vec::<(Isometry<Real>, SharedShape)>::new();
for shape in new_shapes {
let new_shape = scale_shape(&shape.1, scale);
if let Some(shape_extracted) = new_shape {
shapes_vec.push((shape.0, shape_extracted));
}
}
return Some(SharedShape::compound(shapes_vec));
}
return None;
}

#[repr(C)]
pub struct Material {
pub friction : Real,
Expand Down Expand Up @@ -79,48 +121,6 @@ pub extern "C" fn collider_get_angle(world_handle : Handle, handle : Handle) ->
return collider.unwrap().rotation().angle();
}

fn _scale_shape(shape: &SharedShape, scale: &Vector) -> Option<SharedShape> {
let shape_type = shape.shape_type();
if shape_type == ShapeType::Ball {
let new_shape = shape.as_ball().unwrap().scaled(&Vector2::<Real>::new(scale.x, scale.y), 20).unwrap();
if new_shape.is_left() {
let shape = new_shape.unwrap_left();
return Some(SharedShape::new(shape));
} else {
let shape = new_shape.unwrap_right();
return Some(SharedShape::new(shape));
}
}
else if shape_type == ShapeType::Cuboid {
let new_shape = shape.as_cuboid().unwrap().scaled(&Vector2::<Real>::new(scale.x, scale.y));
return Some(SharedShape::new(new_shape));
}
else if shape_type == ShapeType::HalfSpace {
let new_shape = shape.as_halfspace().unwrap().scaled(&Vector2::<Real>::new(scale.x, scale.y)).unwrap();
return Some(SharedShape::new(new_shape));
}
else if shape_type == ShapeType::Polyline {
let new_shape = shape.as_polyline().unwrap().clone().scaled(&Vector2::<Real>::new(scale.x, scale.y));
return Some(SharedShape::new(new_shape));
}
else if shape_type == ShapeType::ConvexPolygon {
let new_shape = shape.as_convex_polygon().unwrap().clone().scaled(&Vector2::<Real>::new(scale.x, scale.y)).unwrap();
return Some(SharedShape::new(new_shape));
}
else if shape_type == ShapeType::Compound {
let new_shapes = shape.as_compound().unwrap().shapes();
let mut shapes_vec = Vec::<(Isometry<Real>, SharedShape)>::new();
for shape in new_shapes {
let new_shape = _scale_shape(&shape.1, scale);
if let Some(shape_extracted) = new_shape {
shapes_vec.push((shape.0, shape_extracted));
}
}
return Some(SharedShape::compound(shapes_vec));
}
return None;
}

#[no_mangle]
pub extern "C" fn collider_set_transform(world_handle : Handle, handle : Handle, shape_handle : Handle, pos : &Vector, rot : Real, scale: &Vector) {
{
Expand All @@ -137,7 +137,7 @@ pub extern "C" fn collider_set_transform(world_handle : Handle, handle : Handle,
{
let mut physics_engine = SINGLETON.lock().unwrap();
let shape = physics_engine.get_shape(shape_handle);
if let Some(extracted_shape) = _scale_shape(shape, scale) {
if let Some(extracted_shape) = scale_shape(shape, scale) {
new_shape = extracted_shape;
} else {
return;
Expand Down
17 changes: 13 additions & 4 deletions src/rapier2d-wrapper/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::handle::*;
use crate::user_data::*;
use crate::physics_world::*;
use crate::vector::Vector;
use crate::collider::*;

#[repr(C)]
pub struct RayHitInfo {
Expand Down Expand Up @@ -355,16 +356,24 @@ pub extern "C" fn intersect_aabb(world_handle : Handle, aabb_min : &Vector, aabb
}

#[no_mangle]
pub extern "C" fn shapes_contact(world_handle : Handle, shape_handle1 : Handle, position1: &Vector, rotation1: Real, shape_handle2 : Handle, position2: &Vector, rotation2: Real, margin: Real) -> ContactResult {
pub extern "C" fn shapes_contact(world_handle : Handle, shape_handle1 : Handle, position1: &Vector, rotation1: Real, scale1: Vector, shape_handle2 : Handle, position2: &Vector, rotation2: Real, scale2: Vector, margin: Real) -> ContactResult {
let mut physics_engine = SINGLETON.lock().unwrap();

let physics_world = physics_engine.get_world(world_handle);

let prediction = Real::max(physics_world.solver_prediction_distance, margin);

let shared_shape1 = physics_engine.get_shape(shape_handle1).clone();
let shared_shape2 = physics_engine.get_shape(shape_handle2).clone();

let mut shared_shape1 = physics_engine.get_shape(shape_handle1).clone();
let shared_shape1_scaled = scale_shape(&shared_shape1, &scale1);
if shared_shape1_scaled.is_some() {
shared_shape1 = shared_shape1_scaled.unwrap();
}
let mut shared_shape2 = physics_engine.get_shape(shape_handle2).clone();
let shared_shape2_scaled = scale_shape(&shared_shape2, &scale2);
if shared_shape2_scaled.is_some() {
shared_shape2 = shared_shape2_scaled.unwrap();
}

let shape_transform1 = Isometry::new(vector![position1.x, position1.y], rotation1);
let shape_transform2 = Isometry::new(vector![position2.x, position2.y], rotation2);

Expand Down
4 changes: 2 additions & 2 deletions src/register_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ static RapierPhysicsServer2DFactory *rapier_2d_factory = nullptr;
void initialize_rapier_2d_module(ModuleInitializationLevel p_level) {
switch (p_level) {
case MODULE_INITIALIZATION_LEVEL_SERVERS: {
ClassDB::register_class<RapierDirectBodyState2D>();
ClassDB::register_class<RapierDirectSpaceState2D>();
ClassDB::register_class<RapierDirectBodyState2D>(true);
ClassDB::register_class<RapierDirectSpaceState2D>(true);
ClassDB::register_class<RapierPhysicsServer2D>();
ClassDB::register_class<RapierPhysicsServer2DFactory>();

Expand Down
28 changes: 16 additions & 12 deletions src/servers/rapier_body_utils_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ bool RapierBodyUtils2D::body_motion_recover(
Vector2 body_shape_pos = body_shape_transform.get_origin();
rapier2d::Vector rapier_body_shape_pos{ body_shape_pos.x, body_shape_pos.y };
real_t rapier_body_shape_rot = body_shape_transform.get_rotation();
Vector2 body_shape_scale = body_shape_transform.get_scale();
rapier2d::Vector rapier_body_shape_scale{ body_shape_scale.x, body_shape_scale.y };

for (int result_idx = 0; result_idx < result_count; ++result_idx) {
rapier2d::PointHitInfo &result = results[result_idx];
Expand All @@ -83,10 +85,12 @@ bool RapierBodyUtils2D::body_motion_recover(
rapier2d::Handle col_shape_handle = col_shape->get_rapier_shape();
Transform2D const &col_shape_transform = collision_body->get_transform() * collision_body->get_shape_transform(shape_index);
Vector2 col_shape_pos = col_shape_transform.get_origin();
Vector2 col_shape_scale = col_shape_transform.get_scale();
rapier2d::Vector rapier_col_shape_pos{ col_shape_pos.x, col_shape_pos.y };
rapier2d::Vector rapier_col_shape_scale{ col_shape_scale.x, col_shape_scale.y };
real_t rapier_col_shape_rot = col_shape_transform.get_rotation();

rapier2d::ContactResult contact = rapier2d::shapes_contact(p_space.get_handle(), body_shape_handle, &rapier_body_shape_pos, rapier_body_shape_rot, col_shape_handle, &rapier_col_shape_pos, rapier_col_shape_rot, p_margin);
rapier2d::ContactResult contact = rapier2d::shapes_contact(p_space.get_handle(), body_shape_handle, &rapier_body_shape_pos, rapier_body_shape_rot, rapier_body_shape_scale, col_shape_handle, &rapier_col_shape_pos, rapier_col_shape_rot, rapier_col_shape_scale, p_margin);

if (!contact.collided) {
continue;
Expand Down Expand Up @@ -157,6 +161,8 @@ void RapierBodyUtils2D::cast_motion(
rapier2d::Handle body_shape_handle = body_shape->get_rapier_shape();
Transform2D const &body_shape_transform = p_transform * p_body.get_shape_transform(body_shape_idx);
Vector2 body_shape_pos = body_shape_transform.get_origin();
Vector2 body_shape_scale = body_shape_transform.get_scale();
rapier2d::Vector rapier_body_shape_scale{ body_shape_scale.x, body_shape_scale.y };
real_t body_shape_rot = body_shape_transform.get_rotation();

bool stuck = false;
Expand Down Expand Up @@ -196,25 +202,19 @@ void RapierBodyUtils2D::cast_motion(
Vector2 col_shape_pos = col_shape_transform.get_origin();
rapier2d::Vector rapier_col_shape_pos{ col_shape_pos.x, col_shape_pos.y };
real_t rapier_col_shape_rot = col_shape_transform.get_rotation();
Vector2 col_shape_scale = col_shape_transform.get_scale();
rapier2d::Vector rapier_col_shape_scale{ col_shape_scale.x, col_shape_scale.y };
{
// stuck logic, check if body collides in place
rapier2d::Vector rapier_body_shape_step_pos_initial{ body_shape_pos.x, body_shape_pos.y };
rapier2d::ContactResult step_contact = rapier2d::shapes_contact(p_space.get_handle(), body_shape_handle, &rapier_body_shape_step_pos_initial, body_shape_rot, col_shape_handle, &rapier_col_shape_pos, rapier_col_shape_rot, 0.0);
rapier2d::ContactResult step_contact = rapier2d::shapes_contact(p_space.get_handle(), body_shape_handle, &rapier_body_shape_step_pos_initial, body_shape_rot, rapier_body_shape_scale, col_shape_handle, &rapier_col_shape_pos, rapier_col_shape_rot, rapier_col_shape_scale, 0.0);
if (step_contact.collided && !step_contact.within_margin) {
p_closest_safe = 0;
p_closest_unsafe = 0;
p_best_body_shape = body_shape_idx; //sadly it's the best
break;
}
}
{
// no collision logic at end of motion. Disabling this as it seems to cause jitter
//rapier2d::Vector rapier_body_shape_pos{ body_shape_pos.x + p_motion.x, body_shape_pos.y + p_motion.y };
//rapier2d::ContactResult step_contact = rapier2d::shapes_contact(p_space.get_handle(), body_shape_handle, &rapier_body_shape_pos, body_shape_rot, col_shape_handle, &rapier_col_shape_pos, rapier_col_shape_rot, 0.0);
//if (!step_contact.collided || (step_contact.collided && step_contact.within_margin)) {
//continue;
//}
}

//just do kinematic solving
//real_t low = MAX(shape_cast_result.toi - 0.01, 0.0);
Expand All @@ -233,7 +233,7 @@ void RapierBodyUtils2D::cast_motion(
real_t fraction = low + (hi - low) * fraction_coeff;

rapier2d::Vector rapier_body_shape_step_pos{ body_shape_pos.x + p_motion.x * fraction, body_shape_pos.y + p_motion.y * fraction };
rapier2d::ContactResult step_contact = rapier2d::shapes_contact(p_space.get_handle(), body_shape_handle, &rapier_body_shape_step_pos, body_shape_rot, col_shape_handle, &rapier_col_shape_pos, rapier_col_shape_rot, 0.0);
rapier2d::ContactResult step_contact = rapier2d::shapes_contact(p_space.get_handle(), body_shape_handle, &rapier_body_shape_step_pos, body_shape_rot, rapier_body_shape_scale, col_shape_handle, &rapier_col_shape_pos, rapier_col_shape_rot, rapier_col_shape_scale, 0.0);
if (step_contact.collided && !step_contact.within_margin) {
hi = fraction;
if ((k == 0) || (low > 0.0)) { // Did it not collide before?
Expand Down Expand Up @@ -340,6 +340,8 @@ bool RapierBodyUtils2D::body_motion_collide(
Transform2D const &body_shape_transform = p_transform * p_body.get_shape_transform(body_shape_idx);
Vector2 body_shape_pos = body_shape_transform.get_origin();
rapier2d::Vector rapier_body_shape_pos{ body_shape_pos.x, body_shape_pos.y };
Vector2 body_shape_scale = body_shape_transform.get_scale();
rapier2d::Vector rapier_body_shape_scale{ body_shape_scale.x, body_shape_scale.y };
real_t rapier_body_shape_rot = body_shape_transform.get_rotation();

for (int result_idx = 0; result_idx < result_count; ++result_idx) {
Expand All @@ -358,9 +360,11 @@ bool RapierBodyUtils2D::body_motion_collide(
Transform2D const &col_shape_transform = collision_body->get_transform() * collision_body->get_shape_transform(shape_index);
Vector2 col_shape_pos = col_shape_transform.get_origin();
rapier2d::Vector rapier_col_shape_pos{ col_shape_pos.x, col_shape_pos.y };
Vector2 col_shape_scale = col_shape_transform.get_scale();
rapier2d::Vector rapier_col_shape_scale{ col_shape_scale.x, col_shape_scale.y };
real_t rapier_col_shape_rot = col_shape_transform.get_rotation();

rapier2d::ContactResult contact = rapier2d::shapes_contact(p_space.get_handle(), body_shape_handle, &rapier_body_shape_pos, rapier_body_shape_rot, col_shape_handle, &rapier_col_shape_pos, rapier_col_shape_rot, p_margin);
rapier2d::ContactResult contact = rapier2d::shapes_contact(p_space.get_handle(), body_shape_handle, &rapier_body_shape_pos, rapier_body_shape_rot, rapier_body_shape_scale, col_shape_handle, &rapier_col_shape_pos, rapier_col_shape_rot, rapier_col_shape_scale, p_margin);
if (!contact.collided) {
continue;
}
Expand Down

0 comments on commit 4b6d034

Please sign in to comment.