diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 3614f8f9..93d6c865 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -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: @@ -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 diff --git a/bin/addons/godot-rapier2d/godot-rapier2d.gdextension b/bin/addons/godot-rapier2d/godot-rapier2d.gdextension index eb0b8a24..3de98c4a 100644 --- a/bin/addons/godot-rapier2d/godot-rapier2d.gdextension +++ b/bin/addons/godot-rapier2d/godot-rapier2d.gdextension @@ -1,7 +1,7 @@ [configuration] entry_symbol = "physics_server_rapier_2d_library_init" -compatibility_minimum = 4.1 +compatibility_minimum = 4.2 [libraries] diff --git a/src/rapier2d-wrapper/includes/rapier2d_wrapper.h b/src/rapier2d-wrapper/includes/rapier2d_wrapper.h index 2248e4e9..fcef970f 100644 --- a/src/rapier2d-wrapper/includes/rapier2d_wrapper.h +++ b/src/rapier2d-wrapper/includes/rapier2d_wrapper.h @@ -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); diff --git a/src/rapier2d-wrapper/src/collider.rs b/src/rapier2d-wrapper/src/collider.rs index 4e4c65d8..e975eee6 100644 --- a/src/rapier2d-wrapper/src/collider.rs +++ b/src/rapier2d-wrapper/src/collider.rs @@ -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 { + let shape_type = shape.shape_type(); + if shape_type == ShapeType::Ball { + let new_shape = shape.as_ball().unwrap().scaled(&Vector2::::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::::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::::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::::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::::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, 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, @@ -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 { - let shape_type = shape.shape_type(); - if shape_type == ShapeType::Ball { - let new_shape = shape.as_ball().unwrap().scaled(&Vector2::::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::::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::::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::::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::::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, 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) { { @@ -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; diff --git a/src/rapier2d-wrapper/src/query.rs b/src/rapier2d-wrapper/src/query.rs index 31191a37..3658fdb5 100644 --- a/src/rapier2d-wrapper/src/query.rs +++ b/src/rapier2d-wrapper/src/query.rs @@ -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 { @@ -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); diff --git a/src/register_types.cpp b/src/register_types.cpp index 1b093218..ef88b4c6 100644 --- a/src/register_types.cpp +++ b/src/register_types.cpp @@ -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(); - ClassDB::register_class(); + ClassDB::register_class(true); + ClassDB::register_class(true); ClassDB::register_class(); ClassDB::register_class(); diff --git a/src/servers/rapier_body_utils_2d.cpp b/src/servers/rapier_body_utils_2d.cpp index 020adcb3..45c0332c 100644 --- a/src/servers/rapier_body_utils_2d.cpp +++ b/src/servers/rapier_body_utils_2d.cpp @@ -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]; @@ -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; @@ -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; @@ -196,10 +202,12 @@ 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; @@ -207,14 +215,6 @@ void RapierBodyUtils2D::cast_motion( 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); @@ -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? @@ -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) { @@ -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; }