From 3d4ad97df8bab08e96d775c20da388366265b7fa Mon Sep 17 00:00:00 2001 From: alex-karev Date: Thu, 5 Jan 2023 21:00:51 +0800 Subject: [PATCH] Fix 'Collisions between 2 connected PhysicalBone3d' Add exclude_nodes_from_collision option to PhysicalBone3D --- doc/classes/PhysicalBone3D.xml | 3 +++ scene/3d/physics_body_3d.cpp | 20 ++++++++++++++++++++ scene/3d/physics_body_3d.h | 4 ++++ 3 files changed, 27 insertions(+) diff --git a/doc/classes/PhysicalBone3D.xml b/doc/classes/PhysicalBone3D.xml index b69fb7050e7f..f363a9bfa8a2 100644 --- a/doc/classes/PhysicalBone3D.xml +++ b/doc/classes/PhysicalBone3D.xml @@ -74,6 +74,9 @@ This is multiplied by the global 3D gravity setting found in [b]Project > Project Settings > Physics > 3d[/b] to produce the body's gravity. For example, a value of 1 will be normal gravity, 2 will apply double gravity, and 0.5 will apply half gravity to this object. + + If [code]true[/code], the bone is not able to collide with the parent bone. + Sets the joint's transform. diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index 71ab96f6e7e4..dd2a51b4baaa 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -2964,6 +2964,8 @@ void PhysicalBone3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_joint_offset"), &PhysicalBone3D::get_joint_offset); ClassDB::bind_method(D_METHOD("set_joint_rotation", "euler"), &PhysicalBone3D::set_joint_rotation); ClassDB::bind_method(D_METHOD("get_joint_rotation"), &PhysicalBone3D::get_joint_rotation); + ClassDB::bind_method(D_METHOD("set_joint_exclude_nodes_from_collision", "exclude_nodes_from_collision"), &PhysicalBone3D::set_joint_exclude_nodes_from_collision); + ClassDB::bind_method(D_METHOD("get_joint_exclude_nodes_from_collision"), &PhysicalBone3D::get_joint_exclude_nodes_from_collision); ClassDB::bind_method(D_METHOD("set_body_offset", "offset"), &PhysicalBone3D::set_body_offset); ClassDB::bind_method(D_METHOD("get_body_offset"), &PhysicalBone3D::get_body_offset); @@ -3016,6 +3018,7 @@ void PhysicalBone3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "joint_type", PROPERTY_HINT_ENUM, "None,PinJoint,ConeJoint,HingeJoint,SliderJoint,6DOFJoint"), "set_joint_type", "get_joint_type"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "joint_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_joint_offset", "get_joint_offset"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "joint_rotation", PROPERTY_HINT_RANGE, "-360,360,0.01,or_less,or_greater,radians"), "set_joint_rotation", "get_joint_rotation"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "joint_exclude_nodes_from_collision"), "set_joint_exclude_nodes_from_collision", "get_joint_exclude_nodes_from_collision"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "body_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_body_offset", "get_body_offset"); @@ -3093,6 +3096,7 @@ void PhysicalBone3D::_reload_joint() { PhysicsServer3D::get_singleton()->pin_joint_set_param(joint, PhysicsServer3D::PIN_JOINT_BIAS, pjd->bias); PhysicsServer3D::get_singleton()->pin_joint_set_param(joint, PhysicsServer3D::PIN_JOINT_DAMPING, pjd->damping); PhysicsServer3D::get_singleton()->pin_joint_set_param(joint, PhysicsServer3D::PIN_JOINT_IMPULSE_CLAMP, pjd->impulse_clamp); + PhysicsServer3D::get_singleton()->joint_disable_collisions_between_bodies(joint, joint_exclude_nodes_from_collision); } break; case JOINT_TYPE_CONE: { @@ -3103,6 +3107,7 @@ void PhysicalBone3D::_reload_joint() { PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer3D::CONE_TWIST_JOINT_BIAS, cjd->bias); PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer3D::CONE_TWIST_JOINT_SOFTNESS, cjd->softness); PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer3D::CONE_TWIST_JOINT_RELAXATION, cjd->relaxation); + PhysicsServer3D::get_singleton()->joint_disable_collisions_between_bodies(joint, joint_exclude_nodes_from_collision); } break; case JOINT_TYPE_HINGE: { @@ -3114,6 +3119,7 @@ void PhysicalBone3D::_reload_joint() { PhysicsServer3D::get_singleton()->hinge_joint_set_param(joint, PhysicsServer3D::HINGE_JOINT_LIMIT_BIAS, hjd->angular_limit_bias); PhysicsServer3D::get_singleton()->hinge_joint_set_param(joint, PhysicsServer3D::HINGE_JOINT_LIMIT_SOFTNESS, hjd->angular_limit_softness); PhysicsServer3D::get_singleton()->hinge_joint_set_param(joint, PhysicsServer3D::HINGE_JOINT_LIMIT_RELAXATION, hjd->angular_limit_relaxation); + PhysicsServer3D::get_singleton()->joint_disable_collisions_between_bodies(joint, joint_exclude_nodes_from_collision); } break; case JOINT_TYPE_SLIDER: { @@ -3129,6 +3135,7 @@ void PhysicalBone3D::_reload_joint() { PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, sjd->angular_limit_softness); PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, sjd->angular_limit_softness); PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING, sjd->angular_limit_damping); + PhysicsServer3D::get_singleton()->joint_disable_collisions_between_bodies(joint, joint_exclude_nodes_from_collision); } break; case JOINT_TYPE_6DOF: { @@ -3156,6 +3163,7 @@ void PhysicalBone3D::_reload_joint() { PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, g6dofjd->axis_data[axis].angular_spring_stiffness); PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, g6dofjd->axis_data[axis].angular_spring_damping); PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, g6dofjd->axis_data[axis].angular_equilibrium_point); + PhysicsServer3D::get_singleton()->joint_disable_collisions_between_bodies(joint, joint_exclude_nodes_from_collision); } } break; @@ -3251,6 +3259,18 @@ Vector3 PhysicalBone3D::get_joint_rotation() const { return joint_offset.basis.get_euler_normalized(); } +void PhysicalBone3D::set_joint_exclude_nodes_from_collision(bool p_exclude_nodes_from_collision) { + if (joint_exclude_nodes_from_collision == p_exclude_nodes_from_collision) { + return; + } + joint_exclude_nodes_from_collision = p_exclude_nodes_from_collision; + _reload_joint(); +} + +bool PhysicalBone3D::get_joint_exclude_nodes_from_collision() const { + return joint_exclude_nodes_from_collision; +} + const Transform3D &PhysicalBone3D::get_body_offset() const { return body_offset; } diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h index 9798fc48450c..97187337756b 100644 --- a/scene/3d/physics_body_3d.h +++ b/scene/3d/physics_body_3d.h @@ -656,6 +656,7 @@ class PhysicalBone3D : public PhysicsBody3D { JointData *joint_data = nullptr; Transform3D joint_offset; + bool joint_exclude_nodes_from_collision = true; RID joint; Skeleton3D *parent_skeleton = nullptr; @@ -738,6 +739,9 @@ class PhysicalBone3D : public PhysicsBody3D { void set_body_offset(const Transform3D &p_offset); const Transform3D &get_body_offset() const; + void set_joint_exclude_nodes_from_collision(bool p_exclude_nodes_from_collision); + bool get_joint_exclude_nodes_from_collision() const; + void set_simulate_physics(bool p_simulate); bool get_simulate_physics(); bool is_simulating_physics();