diff --git a/doc/classes/Area.xml b/doc/classes/Area.xml index 6bd138248806..23cc9cb9b1bd 100644 --- a/doc/classes/Area.xml +++ b/doc/classes/Area.xml @@ -9,24 +9,6 @@ - - - - - - - Returns an individual bit on the layer mask. - - - - - - - - - Returns an individual bit on the collision mask. - - @@ -62,28 +44,6 @@ The [code]body[/code] argument can either be a [PhysicsBody] or a [GridMap] instance (while GridMaps are not physics body themselves, they register their tiles with collision shapes as a virtual physics body). - - - - - - - - - Set/clear individual bits on the layer mask. This simplifies editing this [Area]'s layers. - - - - - - - - - - - Set/clear individual bits on the collision mask. This simplifies editing which [Area] layers this [Area] scans. - - @@ -95,12 +55,6 @@ If [code]true[/code], the area's audio bus overrides the default audio bus. - - The area's physics layer(s). Collidable objects can exist in any of 32 different layers. A contact is detected if object A is in any of the layers that object B scans, or object B is in any layers that object A scans. See also [member collision_mask]. - - - The physics layers this area scans to determine collision detection. - The area's gravity intensity (ranges from -1024 to 1024). This value multiplies the gravity vector. This is useful to alter the force of gravity without altering its direction. diff --git a/doc/classes/BoneBulletPhysicsDirectBodyState.xml b/doc/classes/BoneBulletPhysicsDirectBodyState.xml new file mode 100644 index 000000000000..3361a036fe34 --- /dev/null +++ b/doc/classes/BoneBulletPhysicsDirectBodyState.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/doc/classes/CollisionObject.xml b/doc/classes/CollisionObject.xml index c30aeafcf387..47a37961d062 100644 --- a/doc/classes/CollisionObject.xml +++ b/doc/classes/CollisionObject.xml @@ -26,6 +26,14 @@ Accepts unhandled [InputEvent]s. [code]click_position[/code] is the clicked location in world space and [code]click_normal[/code] is the normal vector extending from the clicked surface of the [Shape] at [code]shape_idx[/code]. Connect to the [code]input_event[/code] signal to easily pick up these events. + + + + + + + + @@ -35,6 +43,28 @@ Creates a new shape owner for the given object. Returns [code]owner_id[/code] of the new owner for future reference. + + + + + + + + + + + + + + + + + + + + + + @@ -58,6 +88,14 @@ If [code]true[/code], the shape owner and its shapes are disabled. + + + + + + + + @@ -67,6 +105,26 @@ Removes the given shape owner. + + + + + + + + + + + + + + + + + + + + @@ -180,6 +238,10 @@ + + + + If [code]true[/code], the [CollisionObject] will continue to receive input events as the mouse is dragged across its shapes. diff --git a/doc/classes/PhysicalBone.xml b/doc/classes/PhysicalBone.xml index 583c24e2c03a..346375df1aa3 100644 --- a/doc/classes/PhysicalBone.xml +++ b/doc/classes/PhysicalBone.xml @@ -1,5 +1,5 @@ - + @@ -13,8 +13,26 @@ - - + + + + + + + + + + + + + + + + + + + + @@ -25,9 +43,99 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -37,31 +145,73 @@ - + + + - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + diff --git a/doc/classes/PhysicsBody.xml b/doc/classes/PhysicsBody.xml index ee50f5a6c389..962b40001e2a 100644 --- a/doc/classes/PhysicsBody.xml +++ b/doc/classes/PhysicsBody.xml @@ -10,82 +10,7 @@ https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html - - - - - - - Adds a body to the list of bodies that this body can't collide with. - - - - - - - Returns an array of nodes that were added as collision exceptions for this body. - - - - - - - - - Returns an individual bit on the [member collision_layer]. - - - - - - - - - Returns an individual bit on the [member collision_mask]. - - - - - - - - - Removes a body from the list of bodies that this body can't collide with. - - - - - - - - - - - Sets individual bits on the [member collision_layer] bitmask. Use this if you only need to change one layer's value. - - - - - - - - - - - Sets individual bits on the [member collision_mask] bitmask. Use this if you only need to change one layer's value. - - - - - The physics layers this area is in. - Collidable objects can exist in any of 32 different layers. These layers work like a tagging system, and are not visual. A collidable can use these layers to select with which objects it can collide, using the [member collision_mask] property. - A contact is detected if object A is in any of the layers that object B scans, or object B is in any layer scanned by object A. - - - The physics layers this area scans for collisions. - - diff --git a/doc/classes/PhysicsServer.xml b/doc/classes/PhysicsServer.xml index a779a34e6ac5..a6a18229a1fd 100644 --- a/doc/classes/PhysicsServer.xml +++ b/doc/classes/PhysicsServer.xml @@ -306,430 +306,1100 @@ Sets the transform matrix for an area. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + Adds a body to the list of bodies exempt from collisions. + + + + + + + + + + + + + + + + + + + + + + + + + + + Adds a shape to the body, along with a transform matrix. Shapes are usually referenced by their index, so you should track which shape has a given index. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Gives the body a push at a [code]position[/code] in the direction of the [code]impulse[/code]. + + + + + + + + + + + Gives the body a push to rotate it. + + + + + + + + + + + Assigns the area to a descendant of [Object], so it can exist in the node tree. + + + + + + + + + Removes all shapes from a body. + + + + + + + + + + + Creates a physics body. The first parameter can be any value from constants BODY_MODE*, for the type of body created. Additionally, the body can be created in sleeping state to save processing time. + + + + + + + + + Returns the physics layer or layers a body belongs to. + + + + + + + + + Returns the physics layer or layers a body can collide with. +- + + + + + + + + + Returns the [PhysicsDirectBodyState] of the body. + + + + + + + + + + + + + + + + + Returns the maximum contacts that can be reported. See [method body_set_max_contacts_reported]. + + + + + + + + + Returns the body mode. + + + + + + + + + Gets the instance ID of the object the area is assigned to. + + + + + + + + + + + Returns the value of a body parameter. A list of available parameters is on the [code]BODY_PARAM_*[/code] constants. + + + + + + + + + + + Returns the [RID] of the nth shape of a body. + + + + + + + + + Returns the number of shapes assigned to a body. + + + + + + + + + + + Returns the transform matrix of a body shape. + + + + + + + + + Returns the [RID] of the space assigned to a body. + + + + + + + + + + + Returns a body state. + + + + + + + + + + + + + + + + + + + If [code]true[/code], the continuous collision detection mode is enabled. + + + + + + + + + Returns whether a body uses a callback function to calculate its own physics (see [method body_set_force_integration_callback]). + + + + + + + + + If [code]true[/code], the body can be detected by rays. + + + + + + + + + + + Removes a body from the list of bodies exempt from collisions. + Continuous collision detection tries to predict where a moving body will collide, instead of moving it and correcting its movement if it collided. + + + + + + + + + + + Removes a shape from a body. The shape is not deleted, so it can be reused afterwards. + + + + + + + + + + + + + + + + + + + + + + + Sets an axis velocity. The velocity in the given vector axis will be set as the given vector length. This is useful for jumping behavior. + + + + + + + + + + + Sets the physics layer or layers a body belongs to. + + + + + + + + + + + Sets the physics layer or layers a body can collide with. + + + + + + + + + + + If [code]true[/code], the continuous collision detection mode is enabled. + Continuous collision detection tries to predict where a moving body will collide, instead of moving it and correcting its movement if it collided. + + + + + + + + + + + + + + + Sets the function used to calculate physics for an object, if that object allows it (see [method body_set_omit_force_integration]). + + + + + + + + + + + + + + + + + + + + + Sets the maximum contacts to report. Bodies can keep a log of the contacts with other bodies, this is enabled by setting the maximum amount of contacts reported to a number greater than 0. + + + + + + + + + + + Sets the body mode, from one of the constants BODY_MODE*. + + + + + + + + + + + Sets whether a body uses a callback function to calculate its own physics (see [method body_set_force_integration_callback]). + + + + + + + + + + + + + Sets a body parameter. A list of available parameters is on the [code]BODY_PARAM_*[/code] constants. + + + + + + + + + + + Sets the body pickable with rays if [code]enabled[/code] is set. + + + + + + + + + + + + + Substitutes a given body shape by another. The old shape is selected by its index, the new one by its [RID]. + + + + + + + + + + + + + + + + + + + + + + + + + Sets the transform matrix for a body shape. + + + + + + + + + + + Assigns a space to the body (see [method space_create]). + + + + + + + + + + + + + Sets a body state (see BODY_STATE* constants). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - Adds a body to the list of bodies exempt from collisions. - - + + - - - - - - + + - - - - - - - Adds a shape to the body, along with a transform matrix. Shapes are usually referenced by their index, so you should track which shape has a given index. - - + + - - - - + + - - - - + + - - - - - Gives the body a push at a [code]position[/code] in the direction of the [code]impulse[/code]. - - + + - + - Gives the body a push to rotate it. - - + + - + + + + + + + - Assigns the area to a descendant of [Object], so it can exist in the node tree. - - + + - Removes all shapes from a body. - + - + - + - Creates a physics body. The first parameter can be any value from constants BODY_MODE*, for the type of body created. Additionally, the body can be created in sleeping state to save processing time. - + - Returns the physics layer or layers a body belongs to. - - + + + + - Returns the physics layer or layers a body can collide with. -- - - + + - Returns the [PhysicsDirectBodyState] of the body. - - + + - - + + - Returns the maximum contacts that can be reported. See [method body_set_max_contacts_reported]. - - + + - Returns the body mode. - - + + - Gets the instance ID of the object the area is assigned to. - - + + - - - Returns the value of a body parameter. A list of available parameters is on the [code]BODY_PARAM_*[/code] constants. - - + + - - - Returns the [RID] of the nth shape of a body. - - + + - Returns the number of shapes assigned to a body. - - + + - + + + + + + + - Returns the transform matrix of a body shape. - - + + + + - Returns the [RID] of the space assigned to a body. - - + + - + - Returns a body state. - - + + - + - - + + + + - If [code]true[/code], the continuous collision detection mode is enabled. - - + + + + - Returns whether a body uses a callback function to calculate its own physics (see [method body_set_force_integration_callback]). - - + + + + - If [code]true[/code], the body can be detected by rays. - + - + - Removes a body from the list of bodies exempt from collisions. - Continuous collision detection tries to predict where a moving body will collide, instead of moving it and correcting its movement if it collided. - + - + - Removes a shape from a body. The shape is not deleted, so it can be reused afterwards. - + - + - + + + - + - + - Sets an axis velocity. The velocity in the given vector axis will be set as the given vector length. This is useful for jumping behavior. - + - + - Sets the physics layer or layers a body belongs to. - + - + - Sets the physics layer or layers a body can collide with. - + - + - If [code]true[/code], the continuous collision detection mode is enabled. - Continuous collision detection tries to predict where a moving body will collide, instead of moving it and correcting its movement if it collided. - + - + - + + + + + + + - + - Sets the function used to calculate physics for an object, if that object allows it (see [method body_set_omit_force_integration]). - + - + - + - + - Sets the maximum contacts to report. Bodies can keep a log of the contacts with other bodies, this is enabled by setting the maximum amount of contacts reported to a number greater than 0. - + - + - Sets the body mode, from one of the constants BODY_MODE*. - + - + - Sets whether a body uses a callback function to calculate its own physics (see [method body_set_force_integration_callback]). - + @@ -739,21 +1409,39 @@ - Sets a body parameter. A list of available parameters is on the [code]BODY_PARAM_*[/code] constants. - + - + - Sets the body pickable with rays if [code]enabled[/code] is set. - + + + + + + + + + + + + + + + + + + + + + @@ -763,10 +1451,9 @@ - Substitutes a given body shape by another. The old shape is selected by its index, the new one by its [RID]. - + @@ -778,7 +1465,7 @@ - + @@ -788,31 +1475,36 @@ - Sets the transform matrix for a body shape. - + - + - Assigns a space to the body (see [method space_create]). - + - + - + + + + + + + + + - Sets a body state (see BODY_STATE* constants). @@ -1262,6 +1954,10 @@ + + + + The [Joint] is a [PinJoint]. diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 3e9e063c0c66..95ed4d7755f9 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -755,13 +755,15 @@ Sets whether physics is run on the main thread or a separate one. Running the server on a thread increases performance, but restricts API access to only physics process. - - + + Sets which physics engine to use. + + Frames per second used in the physics. Physics always needs a fixed amount of frames per second. diff --git a/doc/classes/Skeleton.xml b/doc/classes/Skeleton.xml index b1e71ee92424..32dcf7b63e33 100644 --- a/doc/classes/Skeleton.xml +++ b/doc/classes/Skeleton.xml @@ -157,20 +157,6 @@ - - - - - - - - - - - - - - @@ -266,8 +252,12 @@ + + + + diff --git a/editor/plugins/physical_bone_plugin.cpp b/editor/plugins/physical_bone_plugin.cpp index 96681a105f3f..5ff3d998e1c7 100644 --- a/editor/plugins/physical_bone_plugin.cpp +++ b/editor/plugins/physical_bone_plugin.cpp @@ -47,8 +47,8 @@ void PhysicalBoneEditor::_set_move_joint() { } } -PhysicalBoneEditor::PhysicalBoneEditor(EditorNode *p_editor) : - editor(p_editor), +PhysicalBoneEditor::PhysicalBoneEditor() : + editor(NULL), selected(NULL) { spatial_editor_hb = memnew(HBoxContainer); @@ -91,16 +91,20 @@ void PhysicalBoneEditor::show() { PhysicalBonePlugin::PhysicalBonePlugin(EditorNode *p_editor) : editor(p_editor), selected(NULL), - physical_bone_editor(editor) {} + physical_bone_editor(NULL) { + + physical_bone_editor = memnew(PhysicalBoneEditor); + physical_bone_editor->editor = p_editor; +} void PhysicalBonePlugin::make_visible(bool p_visible) { if (p_visible) { - physical_bone_editor.show(); + physical_bone_editor->show(); } else { - physical_bone_editor.hide(); - physical_bone_editor.set_selected(NULL); + physical_bone_editor->hide(); + physical_bone_editor->set_selected(NULL); selected = NULL; } } @@ -109,5 +113,5 @@ void PhysicalBonePlugin::edit(Object *p_node) { selected = static_cast(p_node); // Trust it ERR_FAIL_COND(!selected); - physical_bone_editor.set_selected(selected); + physical_bone_editor->set_selected(selected); } diff --git a/editor/plugins/physical_bone_plugin.h b/editor/plugins/physical_bone_plugin.h index 78c1c331a0ae..617f8ed4d672 100644 --- a/editor/plugins/physical_bone_plugin.h +++ b/editor/plugins/physical_bone_plugin.h @@ -33,8 +33,10 @@ #include "editor/editor_node.h" -class PhysicalBoneEditor : public Object { - GDCLASS(PhysicalBoneEditor, Object); +class PhysicalBoneEditor : public Control { + GDCLASS(PhysicalBoneEditor, Control); + + friend class PhysicalBonePlugin; EditorNode *editor; HBoxContainer *spatial_editor_hb; @@ -50,7 +52,7 @@ class PhysicalBoneEditor : public Object { void _set_move_joint(); public: - PhysicalBoneEditor(EditorNode *p_editor); + PhysicalBoneEditor(); ~PhysicalBoneEditor(); void set_selected(PhysicalBone *p_pb); @@ -64,7 +66,7 @@ class PhysicalBonePlugin : public EditorPlugin { EditorNode *editor; PhysicalBone *selected; - PhysicalBoneEditor physical_bone_editor; + PhysicalBoneEditor *physical_bone_editor; public: virtual String get_name() const { return "PhysicalBone"; } diff --git a/editor/plugins/skeleton_editor_plugin.cpp b/editor/plugins/skeleton_editor_plugin.cpp index cd360d4caf2e..d6581c0bc56c 100644 --- a/editor/plugins/skeleton_editor_plugin.cpp +++ b/editor/plugins/skeleton_editor_plugin.cpp @@ -93,7 +93,7 @@ void SkeletonEditor::create_physical_skeleton() { /// Create joint between parent of parent if (-1 != parent_parent) { - bones_infos[parent].physical_bone->set_joint_type(PhysicalBone::JOINT_TYPE_PIN); + bones_infos[parent].physical_bone->set_joint_type(PhysicalBone::JOINT_TYPE_FIXED); } } } diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp index cbfd0f3742e2..22f641b0df46 100644 --- a/editor/spatial_editor_gizmos.cpp +++ b/editor/spatial_editor_gizmos.cpp @@ -1833,22 +1833,27 @@ void PhysicalBoneSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { Vector points; switch (physical_bone->get_joint_type()) { - case PhysicalBone::JOINT_TYPE_PIN: { + case PhysicalBone::JOINT_TYPE_FIXED: { JointSpatialGizmoPlugin::CreatePinJointGizmo(physical_bone->get_joint_offset(), points); + } break; - case PhysicalBone::JOINT_TYPE_CONE: { + case PhysicalBone::JOINT_TYPE_SLIDER: { - const PhysicalBone::ConeJointData *cjd(static_cast(physical_bone->get_joint_data())); - JointSpatialGizmoPlugin::CreateConeTwistJointGizmo( + const PhysicalBone::SliderJointData *sjd(static_cast(physical_bone->get_joint_data())); + JointSpatialGizmoPlugin::CreateSliderJointGizmo( physical_bone->get_joint_offset(), physical_bone->get_global_transform() * physical_bone->get_joint_offset(), pb->get_global_transform(), pbp->get_global_transform(), - cjd->swing_span, - cjd->twist_span, + 0, + 0, + sjd->limit_active ? sjd->upper_limit * -1 : -1000, + sjd->limit_active ? sjd->lower_limit * -1 : 1000, + points, &points, &points); + } break; case PhysicalBone::JOINT_TYPE_HINGE: { @@ -1858,64 +1863,57 @@ void PhysicalBoneSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { physical_bone->get_global_transform() * physical_bone->get_joint_offset(), pb->get_global_transform(), pbp->get_global_transform(), - hjd->angular_limit_lower, - hjd->angular_limit_upper, - hjd->angular_limit_enabled, + Math::deg2rad(hjd->lower_limit), + Math::deg2rad(hjd->upper_limit), + hjd->limit_active, points, &points, &points); + } break; - case PhysicalBone::JOINT_TYPE_SLIDER: { + case PhysicalBone::JOINT_TYPE_SPHERICAL: { - const PhysicalBone::SliderJointData *sjd(static_cast(physical_bone->get_joint_data())); - JointSpatialGizmoPlugin::CreateSliderJointGizmo( + const real_t radius(0.25); + JointGizmosDrawer::draw_circle( + Vector3::AXIS_X, + radius, physical_bone->get_joint_offset(), - physical_bone->get_global_transform() * physical_bone->get_joint_offset(), - pb->get_global_transform(), - pbp->get_global_transform(), - sjd->angular_limit_lower, - sjd->angular_limit_upper, - sjd->linear_limit_lower, - sjd->linear_limit_upper, - points, - &points, - &points); - } break; - case PhysicalBone::JOINT_TYPE_6DOF: { + Basis(), + 0, + -1, + points); - const PhysicalBone::SixDOFJointData *sdofjd(static_cast(physical_bone->get_joint_data())); - JointSpatialGizmoPlugin::CreateGeneric6DOFJointGizmo( + JointGizmosDrawer::draw_circle( + Vector3::AXIS_Y, + radius, physical_bone->get_joint_offset(), + Basis(), + 0, + -1, + points); - physical_bone->get_global_transform() * physical_bone->get_joint_offset(), - pb->get_global_transform(), - pbp->get_global_transform(), + JointGizmosDrawer::draw_circle( + Vector3::AXIS_Z, + radius, + physical_bone->get_joint_offset(), + Basis(), + 0, + -1, + points); - sdofjd->axis_data[0].angular_limit_lower, - sdofjd->axis_data[0].angular_limit_upper, - sdofjd->axis_data[0].linear_limit_lower, - sdofjd->axis_data[0].linear_limit_upper, - sdofjd->axis_data[0].angular_limit_enabled, - sdofjd->axis_data[0].linear_limit_enabled, - - sdofjd->axis_data[1].angular_limit_lower, - sdofjd->axis_data[1].angular_limit_upper, - sdofjd->axis_data[1].linear_limit_lower, - sdofjd->axis_data[1].linear_limit_upper, - sdofjd->axis_data[1].angular_limit_enabled, - sdofjd->axis_data[1].linear_limit_enabled, - - sdofjd->axis_data[2].angular_limit_lower, - sdofjd->axis_data[2].angular_limit_upper, - sdofjd->axis_data[2].linear_limit_lower, - sdofjd->axis_data[2].linear_limit_upper, - sdofjd->axis_data[2].angular_limit_enabled, - sdofjd->axis_data[2].linear_limit_enabled, + } break; - points, - &points, - &points); + case PhysicalBone::JOINT_TYPE_PLANAR: { + + // Draw a plane + real_t plane_size(0.25); + JointGizmosDrawer::draw_plane( + physical_bone->get_joint_offset(), + Basis(), + plane_size, + points); } break; + case PhysicalBone::JOINT_TYPE_NONE: default: return; } @@ -4113,6 +4111,24 @@ void JointGizmosDrawer::draw_cone(const Transform &p_offset, const Basis &p_base } } +void JointGizmosDrawer::draw_plane(const Transform &p_offset, const Basis &p_base, real_t p_plane_size, Vector &r_points) { + + r_points.push_back(p_offset.translated(p_base.xform(Vector3(-1, 0, -1) * p_plane_size)).origin); + r_points.push_back(p_offset.translated(p_base.xform(Vector3(1, 0, -1) * p_plane_size)).origin); + + r_points.push_back(p_offset.translated(p_base.xform(Vector3(1, 0, -1) * p_plane_size)).origin); + r_points.push_back(p_offset.translated(p_base.xform(Vector3(1, 0, 1) * p_plane_size)).origin); + + r_points.push_back(p_offset.translated(p_base.xform(Vector3(1, 0, 1) * p_plane_size)).origin); + r_points.push_back(p_offset.translated(p_base.xform(Vector3(-1, 0, 1) * p_plane_size)).origin); + + r_points.push_back(p_offset.translated(p_base.xform(Vector3(-1, 0, 1) * p_plane_size)).origin); + r_points.push_back(p_offset.translated(p_base.xform(Vector3(-1, 0, -1) * p_plane_size)).origin); + + r_points.push_back(p_offset.translated(p_base.xform(Vector3(0, 0, 0) * p_plane_size)).origin); + r_points.push_back(p_offset.translated(p_base.xform(Vector3(0, 1, 0) * p_plane_size)).origin); +} + //// JointSpatialGizmoPlugin::JointSpatialGizmoPlugin() { diff --git a/editor/spatial_editor_gizmos.h b/editor/spatial_editor_gizmos.h index 3661df4bad35..60d9f13f4e07 100644 --- a/editor/spatial_editor_gizmos.h +++ b/editor/spatial_editor_gizmos.h @@ -385,6 +385,7 @@ class JointGizmosDrawer { // Draw circle around p_axis static void draw_circle(Vector3::Axis p_axis, real_t p_radius, const Transform &p_offset, const Basis &p_base, real_t p_limit_lower, real_t p_limit_upper, Vector &r_points, bool p_inverse = false); static void draw_cone(const Transform &p_offset, const Basis &p_base, real_t p_swing, real_t p_twist, Vector &r_points); + static void draw_plane(const Transform &p_offset, const Basis &p_base, real_t p_plane_size, Vector &r_points); }; class JointSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { diff --git a/modules/bullet/SCsub b/modules/bullet/SCsub index ecc8a9b481a3..3b4d57a29d51 100644 --- a/modules/bullet/SCsub +++ b/modules/bullet/SCsub @@ -145,8 +145,10 @@ if env['builtin_bullet']: , "BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp" , "BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp" , "BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp" - , "BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp" + , "BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp" + , "BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.cpp" , "BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp" + , "BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.cpp" , "BulletDynamics/MLCPSolvers/btDantzigLCP.cpp" , "BulletDynamics/MLCPSolvers/btMLCPSolver.cpp" , "BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp" diff --git a/modules/bullet/area_bullet.cpp b/modules/bullet/area_bullet.cpp index a6872d81d707..8b3ebb0e838b 100644 --- a/modules/bullet/area_bullet.cpp +++ b/modules/bullet/area_bullet.cpp @@ -37,7 +37,6 @@ #include "space_bullet.h" #include -#include /** @author AndreaCatania @@ -103,7 +102,23 @@ void AreaBullet::dispatch_callbacks() { void AreaBullet::call_event(CollisionObjectBullet *p_otherObject, PhysicsServer::AreaBodyStatus p_status) { - InOutEventCallback &event = eventsCallbacks[static_cast(p_otherObject->getType())]; + int event_type; + switch (p_otherObject->getType()) { + case TYPE_AREA: + event_type = 0; + break; + case TYPE_RIGID_BODY: + case TYPE_BONE_BODY: + event_type = 1; + break; + case TYPE_SOFT_BODY: + case TYPE_KINEMATIC_GHOST_BODY: + default: + ERR_EXPLAIN("Event not supported") + ERR_FAIL() + } + + InOutEventCallback &event = eventsCallbacks[event_type]; Object *areaGodoObject = ObjectDB::get_instance(event.event_callback_id); if (!areaGodoObject) { @@ -274,7 +289,24 @@ Variant AreaBullet::get_param(PhysicsServer::AreaParameter p_param) const { } void AreaBullet::set_event_callback(Type p_callbackObjectType, ObjectID p_id, const StringName &p_method) { - InOutEventCallback &ev = eventsCallbacks[static_cast(p_callbackObjectType)]; + + int event_type; + switch (p_callbackObjectType) { + case TYPE_AREA: + event_type = 0; + break; + case TYPE_RIGID_BODY: + case TYPE_BONE_BODY: + event_type = 1; + break; + case TYPE_SOFT_BODY: + case TYPE_KINEMATIC_GHOST_BODY: + default: + ERR_EXPLAIN("Event not supported") + ERR_FAIL() + } + + InOutEventCallback &ev = eventsCallbacks[event_type]; ev.event_callback_id = p_id; ev.event_callback_method = p_method; @@ -287,7 +319,24 @@ void AreaBullet::set_event_callback(Type p_callbackObjectType, ObjectID p_id, co } bool AreaBullet::has_event_callback(Type p_callbackObjectType) { - return eventsCallbacks[static_cast(p_callbackObjectType)].event_callback_id; + + int event_type; + switch (p_callbackObjectType) { + case TYPE_AREA: + event_type = 0; + break; + case TYPE_RIGID_BODY: + case TYPE_BONE_BODY: + event_type = 1; + break; + case TYPE_SOFT_BODY: + case TYPE_KINEMATIC_GHOST_BODY: + default: + ERR_EXPLAIN("Event not supported") + ERR_FAIL_V(false) + } + + return eventsCallbacks[event_type].event_callback_id; } void AreaBullet::on_enter_area(AreaBullet *p_area) { diff --git a/modules/bullet/armature_bullet.cpp b/modules/bullet/armature_bullet.cpp new file mode 100644 index 000000000000..b8bba33a49b9 --- /dev/null +++ b/modules/bullet/armature_bullet.cpp @@ -0,0 +1,1251 @@ +/*************************************************************************/ +/* bullet_physics_server.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "armature_bullet.h" + +#include "bullet_physics_server.h" +#include "bullet_types_converter.h" +#include "bullet_utilities.h" +#include "joint_bullet.h" + +#include +#include +#include +#include +#include + +/** + @author AndreaCatania +*/ + +ArmatureBullet::ArmatureBullet() : + space(NULL), + active(false), + force_integration_callback(NULL) { + + bt_body = bulletnew(btMultiBody( + 0, // N of links + 1, // mass + btVector3(1, 1, 1), // inertia + false, // fixed base + true // Can sleep + )); + + bt_body->finalizeMultiDof(); +} + +ArmatureBullet::~ArmatureBullet() { + if (force_integration_callback) { + memdelete(force_integration_callback); + force_integration_callback = NULL; + } + + clear_links(); +} + +btMultiBody *ArmatureBullet::get_bt_body() const { + return bt_body; +} + +void ArmatureBullet::set_bone_count(int p_count) { + if (p_count > 0) { + + bt_body->setNumLinks(p_count - 1); + + } else { + bt_body->setNumLinks(0); + } + bt_body->finalizeMultiDof(); +} + +int ArmatureBullet::get_bone_count() const { + return bt_body->getNumLinks(); +} + +void ArmatureBullet::set_space(SpaceBullet *p_space) { + if (space == p_space) + return; //pointles + + if (space) { + space->remove_armature(this); + } + + space = p_space; + + update_activation(); +} + +SpaceBullet *ArmatureBullet::get_space() const { + return space; +} + +void ArmatureBullet::set_active(bool p_active) { + active = p_active; + update_activation(); +} + +void ArmatureBullet::set_transform(const Transform &p_global_transform) { + //set_body_scale(p_global_transform.basis.get_scale_abs()); + + btTransform bt_transform; + G_TO_B(p_global_transform, bt_transform); + UNSCALE_BT_BASIS(bt_transform); + + set_transform__bullet(bt_transform); +} + +Transform ArmatureBullet::get_transform() const { + Transform t; + B_TO_G(get_transform__bullet(), t); + //t.basis.scale(body_scale); + return t; +} + +void ArmatureBullet::set_transform__bullet(const btTransform &p_global_transform) { + transform = p_global_transform; + bt_body->setBaseWorldTransform(p_global_transform); +} + +const btTransform &ArmatureBullet::get_transform__bullet() const { + return transform; +} + +void ArmatureBullet::set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata) { + + if (force_integration_callback) { + memdelete(force_integration_callback); + force_integration_callback = NULL; + } + + if (p_id != 0) { + force_integration_callback = memnew(ForceIntegrationCallback); + force_integration_callback->id = p_id; + force_integration_callback->method = p_method; + force_integration_callback->udata = p_udata; + } +} + +void ArmatureBullet::set_bone(BoneBullet *p_bone) { + if (p_bone->get_link_id() == -1) { + + bt_body->setBaseCollider(p_bone->get_bt_body()); + set_transform__bullet(p_bone->get_transform__bullet()); + update_base_inertia(); + + } else { + + bt_body->getLink(p_bone->get_link_id()).m_collider = p_bone->get_bt_body(); + } + update_ext_joints(); +} + +BoneBullet *ArmatureBullet::get_bone(int p_link_id) const { + if (p_link_id == -1) { + if (bt_body->getBaseCollider()) + return static_cast(bt_body->getBaseCollider()->getUserPointer()); + return NULL; + } else { + ERR_FAIL_INDEX_V(p_link_id, bt_body->getNumLinks(), NULL); + return static_cast(bt_body->getLink(p_link_id).m_collider->getUserPointer()); + } +} + +void ArmatureBullet::remove_bone(int p_link_id) { + BoneBullet *bone = get_bone(p_link_id); + + if (bone) { + for (int i = 0; i < ext_joints.size(); ++i) { + if (ext_joints[i]->get_body_a() == bone || ext_joints[i]->get_body_b() == bone) { + + ext_joints[i]->clear_internal_joint(); + } + } + } + + if (p_link_id == -1) { + + bt_body->setBaseCollider(NULL); + + } else { + bt_body->getLink(p_link_id).m_collider = NULL; + } +} + +void ArmatureBullet::update_base_inertia() { + + btVector3 inertia(0, 0, 0); + + if (bt_body->getBaseCollider()) { + if (bt_body->getBaseCollider()->getCollisionShape()) { + bt_body->getBaseCollider()->getCollisionShape()->calculateLocalInertia( + bt_body->getBaseMass(), + inertia); + } + } + + bt_body->setBaseInertia(inertia); +} + +void ArmatureBullet::update_link_mass_and_inertia(int p_link_id) { + + ERR_FAIL_COND(p_link_id == -1); + + BoneBullet *bone = get_bone(p_link_id); + ERR_FAIL_COND(bone == NULL); + + btVector3 inertia(0, 0, 0); + + bone->calc_link_inertia( + bt_body->getLink(p_link_id).m_jointType, + bone->link_mass, + bone->link_half_size, + inertia); + + bt_body->getLink(p_link_id).m_mass = bone->link_mass; + bt_body->getLink(p_link_id).m_inertiaLocal = inertia; +} + +void ArmatureBullet::set_param(PhysicsServer::ArmatureParameter p_param, real_t p_value) { + switch (p_param) { + case PhysicsServer::ARMATURE_PARAM_MASS: { + + if (p_value > CMP_EPSILON) { + bt_body->setBaseMass(p_value); + } else { + ERR_FAIL_COND(p_value < 0); + bt_body->setBaseMass(0); + // bt_body->setBaseFixed(true) TODO add this + } + update_base_inertia(); + + } break; + case PhysicsServer::ARMATURE_PARAM_MAX: + default: + WARN_PRINTS("Parameter " + itos(p_param) + " not supported by bullet. Value: " + itos(p_value)); + } +} + +real_t ArmatureBullet::get_param(PhysicsServer::ArmatureParameter p_param) const { + switch (p_param) { + case PhysicsServer::ARMATURE_PARAM_MASS: + return bt_body->getBaseMass(); + case PhysicsServer::ARMATURE_PARAM_MAX: + default: + WARN_PRINTS("Parameter " + itos(p_param) + " not supported by bullet."); + return 0; + } +} + +void ArmatureBullet::register_ext_joint(JointBullet *p_joint) { + if (ext_joints.find(p_joint) == -1) + ext_joints.push_back(p_joint); +} + +void ArmatureBullet::erase_ext_joint(JointBullet *p_joint) { + ext_joints.erase(p_joint); +} + +void ArmatureBullet::clear_links() { + const int link_count = bt_body->getNumLinks(); + for (int i = 0; i < link_count; ++i) { + if (bt_body->getLink(i).m_collider) { + BoneBullet *bb = get_bone(i); + bb->set_armature(NULL); + bt_body->getLink(i).m_collider = NULL; + } + } +} + +void ArmatureBullet::update_activation() { + + if (space) { + space->remove_armature(this); + if (active) { + space->add_armature(this); + get_bt_body()->wakeUp(); + } else { + get_bt_body()->goToSleep(); + } + } + + // -1 to take care of the base + for (int i = -1; i < get_bone_count(); ++i) { + + BoneBullet *bp = get_bone(i); + if (!bp) + continue; + + bp->reload_body(); + if (active) { + bp->get_bt_body()->setActivationState(ACTIVE_TAG); + } + } +} + +void ArmatureBullet::update_ext_joints() { + for (int i = 0; i < ext_joints.size(); ++i) { + ext_joints[i]->reload_internal(); + } +} + +BoneBulletPhysicsDirectBodyState *BoneBulletPhysicsDirectBodyState::singleton = NULL; + +Vector3 BoneBulletPhysicsDirectBodyState::get_total_gravity() const { + return bone->get_space()->get_gravity_direction() * bone->get_space()->get_gravity_magnitude(); +} + +float BoneBulletPhysicsDirectBodyState::get_total_angular_damp() const { + return 0; +} + +float BoneBulletPhysicsDirectBodyState::get_total_linear_damp() const { + return 0; +} + +Vector3 BoneBulletPhysicsDirectBodyState::get_center_of_mass() const { + return bone->get_transform().get_origin(); +} + +Basis BoneBulletPhysicsDirectBodyState::get_principal_inertia_axes() const { + return Basis(); +} + +float BoneBulletPhysicsDirectBodyState::get_inverse_mass() const { + return 0; +} + +Vector3 BoneBulletPhysicsDirectBodyState::get_inverse_inertia() const { + return Vector3(); +} + +Basis BoneBulletPhysicsDirectBodyState::get_inverse_inertia_tensor() const { + return Basis(); +} + +void BoneBulletPhysicsDirectBodyState::set_linear_velocity(const Vector3 &p_velocity) { +} + +Vector3 BoneBulletPhysicsDirectBodyState::get_linear_velocity() const { + return Vector3(); +} + +void BoneBulletPhysicsDirectBodyState::set_angular_velocity(const Vector3 &p_velocity) { +} + +Vector3 BoneBulletPhysicsDirectBodyState::get_angular_velocity() const { + return Vector3(); +} + +void BoneBulletPhysicsDirectBodyState::set_transform(const Transform &p_transform) { + bone->set_transform(p_transform); +} + +Transform BoneBulletPhysicsDirectBodyState::get_transform() const { + return bone->get_transform(); +} + +void BoneBulletPhysicsDirectBodyState::add_central_force(const Vector3 &p_force) { +} + +void BoneBulletPhysicsDirectBodyState::add_force(const Vector3 &p_force, const Vector3 &p_pos) { +} + +void BoneBulletPhysicsDirectBodyState::add_torque(const Vector3 &p_torque) { +} + +void BoneBulletPhysicsDirectBodyState::apply_central_impulse(const Vector3 &p_j) { +} + +void BoneBulletPhysicsDirectBodyState::apply_impulse(const Vector3 &p_pos, const Vector3 &p_j) { +} + +void BoneBulletPhysicsDirectBodyState::apply_torque_impulse(const Vector3 &p_j) { +} + +void BoneBulletPhysicsDirectBodyState::set_sleep_state(bool p_enable) { +} + +bool BoneBulletPhysicsDirectBodyState::is_sleeping() const { + return !bone->get_bt_body()->isActive(); +} + +int BoneBulletPhysicsDirectBodyState::get_contact_count() const { + return bone->collisionsCount; +} + +Vector3 BoneBulletPhysicsDirectBodyState::get_contact_local_position(int p_contact_idx) const { + return bone->collisions[p_contact_idx].hitLocalLocation; +} + +Vector3 BoneBulletPhysicsDirectBodyState::get_contact_local_normal(int p_contact_idx) const { + return bone->collisions[p_contact_idx].hitNormal; +} + +float BoneBulletPhysicsDirectBodyState::get_contact_impulse(int p_contact_idx) const { + return bone->collisions[p_contact_idx].appliedImpulse; +} + +int BoneBulletPhysicsDirectBodyState::get_contact_local_shape(int p_contact_idx) const { + return bone->collisions[p_contact_idx].local_shape; +} + +RID BoneBulletPhysicsDirectBodyState::get_contact_collider(int p_contact_idx) const { + return bone->collisions[p_contact_idx].otherObject->get_self(); +} + +Vector3 BoneBulletPhysicsDirectBodyState::get_contact_collider_position(int p_contact_idx) const { + return bone->collisions[p_contact_idx].hitWorldLocation; +} + +ObjectID BoneBulletPhysicsDirectBodyState::get_contact_collider_id(int p_contact_idx) const { + return bone->collisions[p_contact_idx].otherObject->get_instance_id(); +} + +int BoneBulletPhysicsDirectBodyState::get_contact_collider_shape(int p_contact_idx) const { + return bone->collisions[p_contact_idx].other_object_shape; +} + +Vector3 BoneBulletPhysicsDirectBodyState::get_contact_collider_velocity_at_position(int p_contact_idx) const { + BoneBullet::CollisionData &colDat = bone->collisions.write[p_contact_idx]; + + btVector3 hitLocation; + G_TO_B(colDat.hitLocalLocation, hitLocation); + + btCollisionObject *co = colDat.otherObject->get_bt_collision_object(); + btRigidBody *rb = btRigidBody::upcast(co); + + Vector3 velocityAtPoint; + if (rb) + B_TO_G(rb->getVelocityInLocalPoint(hitLocation), velocityAtPoint); + + return velocityAtPoint; +} + +PhysicsDirectSpaceState *BoneBulletPhysicsDirectBodyState::get_space_state() { + return bone->get_space()->get_direct_state(); +} + +BoneBullet::BoneBullet() : + RigidCollisionObjectBullet(TYPE_BONE_BODY), + bt_body(NULL), + bt_joint_limiter(NULL), + bt_joint_motor(NULL), + armature(NULL), + force_integration_callback(NULL), + link_mass(1), + link_half_size(0), + parent_link_id(-1), + disable_parent_collision(true), + lower_limit(-45), + upper_limit(45), + is_motor_enabled(false), + velocity_target(0, 0, 0), + position_target(0), + rotation_target(0, 0, 0), + max_motor_impulse(1), + error_reduction_parameter(1.), + spring_constant(0.1), + damping_constant(1.), + maximum_error(FLT_MAX), + is_root(false) { + + bt_body = bulletnew( + btMultiBodyLinkCollider( + NULL, + -1)); + + setupBulletCollisionObject(bt_body); + reload_shapes(); +} + +BoneBullet::~BoneBullet() { + if (force_integration_callback) { + memdelete(force_integration_callback); + force_integration_callback = NULL; + } + if (armature) { + set_armature(NULL); + } +} + +void BoneBullet::reload_body() { + if (space) { + space->remove_bone(this); + space->add_bone(this); + } +} + +void BoneBullet::set_space(SpaceBullet *p_space) { + if (p_space == space) + return; + + if (space) { + space->remove_bone(this); + + if (bt_joint_limiter) + space->remove_bone_joint_limit(this); + + if (bt_joint_motor) + space->remove_bone_joint_motor(this); + } + + space = p_space; + + if (space) { + space->add_bone(this); + + if (bt_joint_limiter) + space->add_bone_joint_limit(this); + + if (bt_joint_motor) + space->add_bone_joint_motor(this); + } +} + +void BoneBullet::on_collision_filters_change() { + if (space) { + space->reload_collision_filters(this); + } +} + +void BoneBullet::on_collision_checker_end() { + isTransformChanged = true; +} + +void BoneBullet::dispatch_callbacks() { + + if (!force_integration_callback) + return; + + BoneBulletPhysicsDirectBodyState *bodyDirect = BoneBulletPhysicsDirectBodyState::get_singleton(this); + + Variant variantBodyDirect = bodyDirect; + + Object *obj = ObjectDB::get_instance(force_integration_callback->id); + if (!obj) { + // Remove integration callback + set_force_integration_callback(0, StringName()); + } else { + const Variant *vp[2] = { &variantBodyDirect, &force_integration_callback->udata }; + + Variant::CallError responseCallError; + int argc = (force_integration_callback->udata.get_type() == Variant::NIL) ? 1 : 2; + obj->call(force_integration_callback->method, vp, argc, responseCallError); + } +} + +void BoneBullet::on_enter_area(AreaBullet *p_area) { +} + +void BoneBullet::main_shape_changed() { + CRASH_COND(!get_main_shape()) + bt_body->setCollisionShape(get_main_shape()); + if (armature) { + if (get_link_id() == -1) + armature->update_base_inertia(); + } +} + +void BoneBullet::set_transform__bullet(const btTransform &p_global_transform) { + bt_body->setWorldTransform(p_global_transform); + CollisionObjectBullet::set_transform__bullet(p_global_transform); + + if (is_root) { + if (armature) { + armature->set_transform__bullet(p_global_transform); + } + } +} + +const btTransform &BoneBullet::get_transform__bullet() const { + return bt_body->getWorldTransform(); +} + +btMultiBodyLinkCollider *BoneBullet::get_bt_body() const { + return bt_body; +} + +btMultiBodyConstraint *BoneBullet::get_bt_joint_limiter() const { + return bt_joint_limiter; +} + +btMultiBodyConstraint *BoneBullet::get_bt_joint_motor() const { + return bt_joint_motor; +} + +void BoneBullet::set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata) { + + if (force_integration_callback) { + memdelete(force_integration_callback); + force_integration_callback = NULL; + } + + if (p_id != 0) { + force_integration_callback = memnew(ForceIntegrationCallback); + force_integration_callback->id = p_id; + force_integration_callback->method = p_method; + force_integration_callback->udata = p_udata; + } +} + +void BoneBullet::set_armature(ArmatureBullet *p_armature) { + + if (armature == p_armature) + return; + + if (armature) { + armature->remove_bone(get_link_id()); + } + + armature = p_armature; + bt_body->m_link = -1; + is_root = false; + + if (armature) { + + bt_body->m_multiBody = armature->get_bt_body(); + set_space(armature->get_space()); + + } else { + + set_space(NULL); + bt_body->m_multiBody = NULL; + } + + update_joint_limits(); + update_joint_motor(); +} + +ArmatureBullet *BoneBullet::get_armature() const { + return armature; +} + +void BoneBullet::set_bone_id(int p_bone_id) { + ERR_FAIL_COND(!armature); + ERR_FAIL_COND(p_bone_id < 0); + is_root = false; + bt_body->m_link = p_bone_id - 1; // This is correct even if p_link_id is 0 + armature->set_bone(this); + if (get_link_id() == -1) + is_root = true; + + update_joint_limits(); + update_joint_motor(); +} + +int BoneBullet::get_bone_id() const { + return get_link_id() + 1; +} + +int BoneBullet::get_link_id() const { + return bt_body->m_link; +} + +void BoneBullet::set_parent_bone_id(int p_bone_id) { + ERR_FAIL_COND(p_bone_id < 0); + parent_link_id = p_bone_id - 1; +} + +int BoneBullet::get_parent_bone_id() const { + return get_parent_link_id() + 1; +} + +int BoneBullet::get_parent_link_id() const { + return parent_link_id; +} + +void BoneBullet::set_joint_offset(const Transform &p_transform) { + G_TO_B(p_transform, joint_offset); + UNSCALE_BT_BASIS(joint_offset); +} + +Transform BoneBullet::get_joint_offset() const { + Transform t; + B_TO_G(joint_offset, t); + return t; +} + +const btTransform &BoneBullet::get_joint_offset__bullet() const { + return joint_offset; +} + +btTransform BoneBullet::get_joint_offset_scaled__bullet() const { + btTransform joint_offset_scaled; + G_TO_B(get_joint_offset().scaled(get_body_scale()), joint_offset_scaled); + return joint_offset_scaled; +} + +void BoneBullet::set_link_mass(real_t p_link_mass) { + ERR_FAIL_COND(p_link_mass < 0); + link_mass = p_link_mass; + if (armature) + if (get_link_id() != -1) + armature->update_link_mass_and_inertia(link_mass); +} + +real_t BoneBullet::get_link_mass() const { + return link_mass; +} + +void BoneBullet::set_param(PhysicsServer::BodyParameter p_param, real_t p_value) { + switch (p_param) { + case PhysicsServer::BODY_PARAM_BOUNCE: + bt_body->setRestitution(p_value); + break; + case PhysicsServer::BODY_PARAM_FRICTION: + bt_body->setFriction(p_value); + break; + case PhysicsServer::BODY_PARAM_MASS: + case PhysicsServer::BODY_PARAM_LINEAR_DAMP: + case PhysicsServer::BODY_PARAM_ANGULAR_DAMP: + case PhysicsServer::BODY_PARAM_GRAVITY_SCALE: + default: + WARN_PRINTS("Parameter " + itos(p_param) + " not supported by bullet. Value: " + itos(p_value)); + } +} + +real_t BoneBullet::get_param(PhysicsServer::BodyParameter p_param) const { + switch (p_param) { + case PhysicsServer::BODY_PARAM_BOUNCE: + return bt_body->getRestitution(); + case PhysicsServer::BODY_PARAM_FRICTION: + return bt_body->getFriction(); + case PhysicsServer::BODY_PARAM_MASS: + case PhysicsServer::BODY_PARAM_LINEAR_DAMP: + case PhysicsServer::BODY_PARAM_ANGULAR_DAMP: + case PhysicsServer::BODY_PARAM_GRAVITY_SCALE: + default: + WARN_PRINTS("Parameter " + itos(p_param) + " not supported by bullet"); + return 0; + } +} + +void BoneBullet::set_disable_parent_collision(bool p_disable) { + disable_parent_collision = p_disable; + + if (armature) { + if (get_link_id() >= 0) { + if (disable_parent_collision) { + armature->get_bt_body()->getLink(get_link_id()).m_flags |= BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION; + } else { + armature->get_bt_body()->getLink(get_link_id()).m_flags &= ~BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION; + } + } + } +} + +bool BoneBullet::get_disable_parent_collision() const { + return disable_parent_collision; +} + +void BoneBullet::set_limit_active(bool p_limit_active) { + is_limit_active = p_limit_active; + update_joint_limits(); +} + +bool BoneBullet::get_is_limit_active() const { + return is_limit_active; +} + +void BoneBullet::set_lower_limit(real_t p_lower_limit) { + lower_limit = p_lower_limit; + update_joint_limits(); +} + +real_t BoneBullet::get_lower_limit() const { + return lower_limit; +} + +void BoneBullet::set_upper_limit(real_t p_upper_limit) { + upper_limit = p_upper_limit; + update_joint_limits(); +} + +real_t BoneBullet::get_upper_limit() const { + return upper_limit; +} + +void BoneBullet::set_motor_enabled(bool p_v) { + is_motor_enabled = p_v; + update_joint_motor(); +} +bool BoneBullet::get_motor_enabled() const { + return is_motor_enabled; +} + +void BoneBullet::set_velocity_target(const Vector3 &p_v) { + G_TO_B(p_v, velocity_target); + update_joint_motor_params(); +} +Vector3 BoneBullet::get_velocity_target() const { + Vector3 r; + B_TO_G(velocity_target, r); + return r; +} + +void BoneBullet::set_position_target(real_t p_v) { + position_target = p_v; + update_joint_motor_params(); +} +real_t BoneBullet::get_position_target() const { + return position_target; +} + +void BoneBullet::set_rotation_target(const Basis &p_v) { + btMatrix3x3 m; + G_TO_B(p_v, m); + m.getRotation(rotation_target); + update_joint_motor_params(); +} +Basis BoneBullet::get_rotation_target() const { + Basis r; + B_TO_G(btMatrix3x3(rotation_target), r); + return r; +} + +void BoneBullet::set_max_motor_impulse(real_t p_v) { + max_motor_impulse = p_v; + update_joint_motor(); +} +real_t BoneBullet::get_max_motor_impulse() const { + return max_motor_impulse; +} + +void BoneBullet::set_error_reduction_parameter(real_t p_v) { + error_reduction_parameter = p_v; + update_joint_motor_params(); +} +real_t BoneBullet::get_error_reduction_parameter() const { + return error_reduction_parameter; +} + +void BoneBullet::set_spring_constant(real_t p_v) { + spring_constant = p_v; + update_joint_motor_params(); +} +real_t BoneBullet::get_spring_constant() const { + return spring_constant; +} + +void BoneBullet::set_damping_constant(real_t p_v) { + damping_constant = p_v; + update_joint_motor_params(); +} +real_t BoneBullet::get_damping_constant() const { + return damping_constant; +} + +void BoneBullet::set_maximum_error(real_t p_v) { + maximum_error = p_v; + update_joint_motor_params(); +} +real_t BoneBullet::get_maximum_error() const { + return maximum_error; +} + +Vector3 BoneBullet::get_joint_force() const { + + if (get_link_id() == -1) + return Vector3(); + + Vector3 ret; + B_TO_G(armature->get_bt_body()->getLink(get_link_id()).m_appliedConstraintForce, ret); + return ret; +} + +Vector3 BoneBullet::get_joint_torque() const { + + if (get_link_id() == -1) + return Vector3(); + + Vector3 ret; + B_TO_G(armature->get_bt_body()->getLink(get_link_id()).m_appliedConstraintTorque, ret); + return ret; +} + +void BoneBullet::setup_joint_fixed() { + + if (get_link_id() == -1) + return; + + ERR_FAIL_COND(armature->get_bone(get_parent_link_id()) == NULL); + + const btTransform joint_offset_scaled = get_joint_offset_scaled__bullet(); + const btTransform parent_transform = armature->get_bone(get_parent_link_id())->get_transform__bullet(); + const btTransform bone_transform = get_transform__bullet(); + const btTransform parent_to_this = parent_transform.inverse() * bone_transform; + const btTransform parent_to_joint = parent_to_this * joint_offset_scaled; + + link_half_size = 0; + + // 0 Inertia for the fixed joints + btVector3 inertia(0, 0, 0); + + btQuaternion q; + (parent_to_this.getBasis() * joint_offset_scaled.getBasis()).getRotation(q); + + armature->get_bt_body()->setupFixed( + get_link_id(), + link_mass, + inertia, + get_parent_link_id(), + + parent_to_this.getRotation(), + parent_to_joint.getOrigin(), + joint_offset_scaled.getOrigin() * -1); + armature->get_bt_body()->finalizeMultiDof(); + + update_joint_limits(); + update_joint_motor(); +} + +void BoneBullet::setup_joint_prismatic() { + + if (get_link_id() == -1) + return; + + ERR_FAIL_COND(armature->get_bone(get_parent_link_id()) == NULL); + + const btTransform joint_offset_scaled = get_joint_offset_scaled__bullet(); + const btTransform parent_transform = armature->get_bone(get_parent_link_id())->get_transform__bullet(); + const btTransform bone_transform = get_transform__bullet(); + const btTransform parent_to_this = parent_transform.inverse() * bone_transform; + const btTransform parent_to_joint = parent_to_this * joint_offset_scaled; + + link_half_size = parent_to_this.getOrigin().length() * 0.5; + + // Calculates inertia along X + btVector3 inertia(0, 0, 0); + calc_link_inertia(btMultibodyLink::ePrismatic, link_mass, link_half_size, inertia); + + armature->get_bt_body()->setupPrismatic( + get_link_id(), + link_mass, + inertia, + get_parent_link_id(), + + parent_to_this.getRotation(), + parent_to_joint.getBasis() * btVector3(1, 0, 0), // Slide along X + parent_to_joint.getOrigin(), + joint_offset_scaled.getOrigin() * -1, + disable_parent_collision); + armature->get_bt_body()->finalizeMultiDof(); + + update_joint_limits(); + update_joint_motor(); +} + +void BoneBullet::setup_joint_revolute() { + + if (get_link_id() == -1) + return; + + ERR_FAIL_COND(armature->get_bone(get_parent_link_id()) == NULL); + + const btTransform joint_offset_scaled = get_joint_offset_scaled__bullet(); + const btTransform parent_transform = armature->get_bone(get_parent_link_id())->get_transform__bullet(); + const btTransform bone_transform = get_transform__bullet(); + const btTransform parent_to_this = parent_transform.inverse() * bone_transform; + const btTransform parent_to_joint = parent_to_this * joint_offset_scaled; + + link_half_size = parent_to_this.getOrigin().length() * 0.5; + + // Calculates inertia along YZ + btVector3 inertia(0, 0, 0); + calc_link_inertia(btMultibodyLink::eRevolute, link_mass, link_half_size, inertia); + + armature->get_bt_body()->setupRevolute( + get_link_id(), + link_mass, + inertia, + get_parent_link_id(), + + parent_to_this.getRotation(), + parent_to_joint.getBasis() * btVector3(0, 0, 1), // Rotate along Z + parent_to_joint.getOrigin(), + joint_offset_scaled.getOrigin() * -1, + disable_parent_collision); + + armature->get_bt_body()->finalizeMultiDof(); + + update_joint_limits(); + update_joint_motor(); +} + +void BoneBullet::setup_joint_spherical() { + + if (get_link_id() == -1) + return; + + ERR_FAIL_COND(armature->get_bone(get_parent_link_id()) == NULL); + + const btTransform joint_offset_scaled = get_joint_offset_scaled__bullet(); + const btTransform parent_transform = armature->get_bone(get_parent_link_id())->get_transform__bullet(); + const btTransform bone_transform = get_transform__bullet(); + const btTransform parent_to_this = parent_transform.inverse() * bone_transform; + const btTransform parent_to_joint = parent_to_this * joint_offset_scaled; + + link_half_size = parent_to_this.getOrigin().length() * 0.5; + + // Calculates spherical inertia + btVector3 inertia(0, 0, 0); + calc_link_inertia(btMultibodyLink::eSpherical, link_mass, link_half_size, inertia); + + armature->get_bt_body()->setupSpherical( + get_link_id(), + link_mass, + inertia, + get_parent_link_id(), + + parent_to_this.getRotation(), + parent_to_joint.getOrigin(), + joint_offset_scaled.getOrigin() * -1, + disable_parent_collision); + armature->get_bt_body()->finalizeMultiDof(); + + update_joint_limits(); + update_joint_motor(); +} + +void BoneBullet::setup_joint_planar() { + + if (get_link_id() == -1) + return; + + ERR_FAIL_COND(armature->get_bone(get_parent_link_id()) == NULL); + + const btTransform joint_offset_scaled = get_joint_offset_scaled__bullet(); + const btTransform parent_transform = armature->get_bone(get_parent_link_id())->get_transform__bullet(); + const btTransform bone_transform = get_transform__bullet(); + const btTransform parent_to_this = parent_transform.inverse() * bone_transform; + const btTransform parent_to_joint = parent_to_this * joint_offset_scaled; + + link_half_size = parent_to_this.getOrigin().length() * 0.5; + + // Calculates inertia along XZ + btVector3 inertia(0, 0, 0); + calc_link_inertia(btMultibodyLink::ePlanar, link_mass, link_half_size, inertia); + + armature->get_bt_body()->setupPlanar( + get_link_id(), + link_mass, + inertia, + get_parent_link_id(), + + parent_to_this.getRotation(), + parent_to_joint.getBasis() * btVector3(0, 1, 0), // Allow rotation along Y so the plain is XZ + parent_to_this.getOrigin(), + disable_parent_collision); + + armature->get_bt_body()->finalizeMultiDof(); + + update_joint_limits(); + update_joint_motor(); +} + +void BoneBullet::update_joint_limits() { + + if (space) + if (bt_joint_limiter) + space->remove_bone_joint_limit(this); + + bulletdelete(bt_joint_limiter); + bt_joint_limiter = NULL; + + if (!is_limit_active) + return; + + if (get_link_id() == -1) + return; + + if (!space) + return; + + real_t ll = lower_limit; + real_t ul = upper_limit; + + switch (armature->get_bt_body()->getLink(get_link_id()).m_jointType) { + case btMultibodyLink::eRevolute: + ll = lower_limit * Math_PI / 180.f; + ul = upper_limit * Math_PI / 180.f; + break; + case btMultibodyLink::ePrismatic: + case btMultibodyLink::eSpherical: + case btMultibodyLink::ePlanar: + case btMultibodyLink::eFixed: + case btMultibodyLink::eInvalid: + break; + } + + bt_joint_limiter = bulletnew(btMultiBodyJointLimitConstraint( + armature->get_bt_body(), + get_link_id(), + ll, + ul)); + + space->add_bone_joint_limit(this); +} + +void BoneBullet::update_joint_motor() { + + if (space) + if (bt_joint_motor) + space->remove_bone_joint_motor(this); + + bulletdelete(bt_joint_motor); + bt_joint_motor = NULL; + + if (!is_motor_enabled) + return; + + if (get_link_id() == -1) + return; + + if (!space) + return; + + switch (armature->get_bt_body()->getLink(get_link_id()).m_jointType) { + case btMultibodyLink::eRevolute: + case btMultibodyLink::ePrismatic: + bt_joint_motor = bulletnew(btMultiBodyJointMotor( + armature->get_bt_body(), + get_link_id(), + velocity_target.getX(), + max_motor_impulse)); + + break; + case btMultibodyLink::eSpherical: + + bt_joint_motor = bulletnew(btMultiBodySphericalJointMotor( + armature->get_bt_body(), + get_link_id(), + max_motor_impulse)); + + break; + case btMultibodyLink::ePlanar: + case btMultibodyLink::eFixed: + case btMultibodyLink::eInvalid: + return; // Stop here + } + + update_joint_motor_params(); + space->add_bone_joint_motor(this); +} + +void BoneBullet::update_joint_motor_params() { + + if (!bt_joint_motor) + return; + + if (!is_motor_enabled) + return; + + if (get_link_id() == -1) + return; + + if (!space) + return; + + switch (armature->get_bt_body()->getLink(get_link_id()).m_jointType) { + case btMultibodyLink::eRevolute: { + + btMultiBodyJointMotor *j = static_cast(bt_joint_motor); + j->setVelocityTarget(velocity_target.getX() * Math_PI / 180.f, damping_constant); + j->setPositionTarget(position_target * Math_PI / 180.f, spring_constant); + j->setErp(error_reduction_parameter); + j->setRhsClamp(maximum_error); + + } break; + case btMultibodyLink::ePrismatic: { + + btMultiBodyJointMotor *j = static_cast(bt_joint_motor); + j->setVelocityTarget(velocity_target.getX(), damping_constant); + j->setPositionTarget(position_target, spring_constant); + j->setErp(error_reduction_parameter); + j->setRhsClamp(maximum_error); + + } break; + case btMultibodyLink::eSpherical: { + + btMultiBodySphericalJointMotor *j = static_cast(bt_joint_motor); + j->setVelocityTarget(velocity_target * Math_PI / 180.f, damping_constant); + j->setPositionTarget(rotation_target, spring_constant); + j->setErp(error_reduction_parameter); + j->setRhsClamp(maximum_error); + + } break; + case btMultibodyLink::ePlanar: + case btMultibodyLink::eFixed: + case btMultibodyLink::eInvalid: + return; // Stop here + } +} + +void BoneBullet::calc_link_inertia( + btMultibodyLink::eFeatherstoneJointType p_joint_type, + real_t p_link_half_size, + real_t p_link_mass, + btVector3 &r_inertia) { + + r_inertia = btVector3(0, 0, 0); + + switch (p_joint_type) { + case btMultibodyLink::eRevolute: + + btBoxShape( + btVector3(0.1, p_link_half_size, p_link_half_size)) + .calculateLocalInertia(p_link_mass, r_inertia); + + break; + case btMultibodyLink::ePrismatic: + + btBoxShape( + btVector3(p_link_half_size, 0.1, 0.1)) + .calculateLocalInertia(p_link_mass, r_inertia); + + break; + case btMultibodyLink::eSpherical: + + btSphereShape(p_link_half_size) + .calculateLocalInertia(p_link_mass, r_inertia); + + break; + case btMultibodyLink::ePlanar: + + btBoxShape( + btVector3(p_link_half_size, 0.1, p_link_half_size)) + .calculateLocalInertia(p_link_mass, r_inertia); + + break; + case btMultibodyLink::eFixed: + case btMultibodyLink::eInvalid: + break; + } +} diff --git a/modules/bullet/armature_bullet.h b/modules/bullet/armature_bullet.h new file mode 100644 index 000000000000..84766ef7c888 --- /dev/null +++ b/modules/bullet/armature_bullet.h @@ -0,0 +1,349 @@ +/*************************************************************************/ +/* bullet_physics_server.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef ARMATURE_BULLET_H +#define ARMATURE_BULLET_H + +/** + @author AndreaCatania +*/ + +#include "collision_object_bullet.h" +#include "space_bullet.h" +#include + +class btMultiBody; +class btMultiBodyLinkCollider; +class btMultiBodyConstraint; +class JointBullet; + +class ArmatureBullet : public RIDBullet { + + struct ForceIntegrationCallback { + ObjectID id; + StringName method; + Variant udata; + }; + + SpaceBullet *space; + btMultiBody *bt_body; + bool active; + btTransform transform; + + ForceIntegrationCallback *force_integration_callback; + + /** + * @brief The list of joints between two multibody, or between a rigid body + * So this is not the list of internal joints + */ + Vector ext_joints; + +public: + ArmatureBullet(); + ~ArmatureBullet(); + + btMultiBody *get_bt_body() const; + + void set_bone_count(int p_count); + int get_bone_count() const; + + void set_space(SpaceBullet *p_space); + SpaceBullet *get_space() const; + + void set_active(bool p_active); + bool is_active() const { return active; } + + void set_transform(const Transform &p_global_transform); + Transform get_transform() const; + void set_transform__bullet(const btTransform &p_global_transform); + const btTransform &get_transform__bullet() const; + + void set_force_integration_callback( + ObjectID p_id, + const StringName &p_method, + const Variant &p_udata = Variant()); + + void set_bone(BoneBullet *p_bone); + BoneBullet *get_bone(int p_link_id) const; + void remove_bone(int p_link_id); + + void update_base_inertia(); + void update_link_mass_and_inertia(int p_link_id); + + void set_param(PhysicsServer::ArmatureParameter p_param, real_t p_value); + real_t get_param(PhysicsServer::ArmatureParameter p_param) const; + + void register_ext_joint(JointBullet *p_joint); + void erase_ext_joint(JointBullet *p_joint); + +private: + void clear_links(); + + void update_activation(); + void update_ext_joints(); +}; + +class BoneBullet; + +class BoneBulletPhysicsDirectBodyState : public PhysicsDirectBodyState { + GDCLASS(BoneBulletPhysicsDirectBodyState, PhysicsDirectBodyState) + + static BoneBulletPhysicsDirectBodyState *singleton; + +public: + /// This class avoid the creation of more object of this class + static void initSingleton() { + if (!singleton) { + singleton = memnew(BoneBulletPhysicsDirectBodyState); + } + } + + static void destroySingleton() { + memdelete(singleton); + singleton = NULL; + } + + static void singleton_setDeltaTime(real_t p_deltaTime) { + singleton->deltaTime = p_deltaTime; + } + + static BoneBulletPhysicsDirectBodyState *get_singleton(BoneBullet *p_body) { + singleton->bone = p_body; + return singleton; + } + +public: + BoneBullet *bone; + real_t deltaTime; + +private: + BoneBulletPhysicsDirectBodyState() {} + +public: + virtual Vector3 get_total_gravity() const; + virtual float get_total_angular_damp() const; + virtual float get_total_linear_damp() const; + + virtual Vector3 get_center_of_mass() const; + virtual Basis get_principal_inertia_axes() const; + // get the mass + virtual float get_inverse_mass() const; + // get density of this body space + virtual Vector3 get_inverse_inertia() const; + // get density of this body space + virtual Basis get_inverse_inertia_tensor() const; + + virtual void set_linear_velocity(const Vector3 &p_velocity); + virtual Vector3 get_linear_velocity() const; + + virtual void set_angular_velocity(const Vector3 &p_velocity); + virtual Vector3 get_angular_velocity() const; + + virtual void set_transform(const Transform &p_transform); + virtual Transform get_transform() const; + + virtual void add_central_force(const Vector3 &p_force); + virtual void add_force(const Vector3 &p_force, const Vector3 &p_pos); + virtual void add_torque(const Vector3 &p_torque); + virtual void apply_central_impulse(const Vector3 &p_impulse); + virtual void apply_impulse(const Vector3 &p_pos, const Vector3 &p_j); + virtual void apply_torque_impulse(const Vector3 &p_j); + + virtual void set_sleep_state(bool p_enable); + virtual bool is_sleeping() const; + + virtual int get_contact_count() const; + + virtual Vector3 get_contact_local_position(int p_contact_idx) const; + virtual Vector3 get_contact_local_normal(int p_contact_idx) const; + virtual float get_contact_impulse(int p_contact_idx) const; + virtual int get_contact_local_shape(int p_contact_idx) const; + + virtual RID get_contact_collider(int p_contact_idx) const; + virtual Vector3 get_contact_collider_position(int p_contact_idx) const; + virtual ObjectID get_contact_collider_id(int p_contact_idx) const; + virtual int get_contact_collider_shape(int p_contact_idx) const; + virtual Vector3 get_contact_collider_velocity_at_position(int p_contact_idx) const; + + virtual real_t get_step() const { return deltaTime; } + virtual void integrate_forces() { + // Skip the execution of this function + } + + virtual PhysicsDirectSpaceState *get_space_state(); +}; + +class BoneBullet : public RigidCollisionObjectBullet { + + friend class ArmatureBullet; + friend class BoneBulletPhysicsDirectBodyState; + + struct ForceIntegrationCallback { + ObjectID id; + StringName method; + Variant udata; + }; + + btMultiBodyLinkCollider *bt_body; + btMultiBodyConstraint *bt_joint_limiter; + btMultiBodyConstraint *bt_joint_motor; + ArmatureBullet *armature; + ForceIntegrationCallback *force_integration_callback; + real_t link_mass; + real_t link_half_size; + int parent_link_id; // Set -1 if no parent + btTransform joint_offset; + bool disable_parent_collision; + + bool is_limit_active; + real_t lower_limit; // In m if slider, in deg if hinge + real_t upper_limit; // In m if slider, in deg if hinge + + // Check this http://www.ode.org/ode-latest-userguide.html#sec_3_7_0 + // For information about these parameters + bool is_motor_enabled; + btVector3 velocity_target; // Used for 1D and 3D motor + real_t position_target; // Used for 1D + btQuaternion rotation_target; // Used for 3D motor + real_t max_motor_impulse; + real_t error_reduction_parameter; // From 0 to 1 + real_t spring_constant; + real_t damping_constant; + real_t maximum_error; + + bool is_root; + +public: + BoneBullet(); + virtual ~BoneBullet(); + + virtual void set_space(SpaceBullet *p_space); + virtual void on_collision_filters_change(); + virtual void on_collision_checker_end(); + virtual void dispatch_callbacks(); + virtual void on_enter_area(AreaBullet *p_area); + + virtual void main_shape_changed(); + virtual void reload_body(); + + virtual void set_transform__bullet(const btTransform &p_global_transform); + virtual const btTransform &get_transform__bullet() const; + + btMultiBodyLinkCollider *get_bt_body() const; + btMultiBodyConstraint *get_bt_joint_limiter() const; + btMultiBodyConstraint *get_bt_joint_motor() const; + + void set_force_integration_callback( + ObjectID p_id, + const StringName &p_method, + const Variant &p_udata = Variant()); + + void set_armature(ArmatureBullet *p_armature); + ArmatureBullet *get_armature() const; + + void set_bone_id(int p_link_id); + int get_bone_id() const; + int get_link_id() const; + + void set_parent_bone_id(int p_bone_id); + int get_parent_bone_id() const; + int get_parent_link_id() const; + + void set_joint_offset(const Transform &p_transform); + Transform get_joint_offset() const; + const btTransform &get_joint_offset__bullet() const; + btTransform get_joint_offset_scaled__bullet() const; + + void set_link_mass(real_t p_link_mass); + real_t get_link_mass() const; + + void set_param(PhysicsServer::BodyParameter p_param, real_t p_value); + real_t get_param(PhysicsServer::BodyParameter p_param) const; + + void set_disable_parent_collision(bool p_disable); + bool get_disable_parent_collision() const; + + void set_limit_active(bool p_limit_active); + bool get_is_limit_active() const; + + void set_lower_limit(real_t p_lower_limit); + real_t get_lower_limit() const; + + void set_upper_limit(real_t p_upper_limit); + real_t get_upper_limit() const; + + void set_motor_enabled(bool p_v); + bool get_motor_enabled() const; + + void set_velocity_target(const Vector3 &p_v); + Vector3 get_velocity_target() const; + + void set_position_target(real_t p_v); + real_t get_position_target() const; + + void set_rotation_target(const Basis &p_v); + Basis get_rotation_target() const; + + void set_max_motor_impulse(real_t p_v); + real_t get_max_motor_impulse() const; + + void set_error_reduction_parameter(real_t p_v); + real_t get_error_reduction_parameter() const; + + void set_spring_constant(real_t p_v); + real_t get_spring_constant() const; + + void set_damping_constant(real_t p_v); + real_t get_damping_constant() const; + + void set_maximum_error(real_t p_v); + real_t get_maximum_error() const; + + Vector3 get_joint_force() const; + Vector3 get_joint_torque() const; + + void setup_joint_fixed(); + void setup_joint_prismatic(); + void setup_joint_revolute(); + void setup_joint_spherical(); + void setup_joint_planar(); + + void update_joint_limits(); + void update_joint_motor(); + void update_joint_motor_params(); + + void calc_link_inertia( + btMultibodyLink::eFeatherstoneJointType p_joint_type, + real_t p_link_mass, + real_t p_link_half_length, + btVector3 &r_inertia); +}; + +#endif // ARMATURE_BULLET_H diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp index 038001996d83..50f9400950ba 100644 --- a/modules/bullet/bullet_physics_server.cpp +++ b/modules/bullet/bullet_physics_server.cpp @@ -70,7 +70,8 @@ return RID(); \ } -#define AddJointToSpace(body, joint) \ +#define AddJointToSpace(body, joint) \ + joint->set_space(body->get_space()); \ body->get_space()->add_constraint(joint, joint->is_disabled_collisions_between_bodies()); // <--------------- Joint creation asserts @@ -780,7 +781,7 @@ void BulletPhysicsServer::body_add_collision_exception(RID p_body, RID p_body_b) RigidBodyBullet *body = rigid_body_owner.get(p_body); ERR_FAIL_COND(!body); - RigidBodyBullet *other_body = rigid_body_owner.get(p_body_b); + CollisionObjectBullet *other_body = get_collisin_object(p_body_b); ERR_FAIL_COND(!other_body); body->add_collision_exception(other_body); @@ -790,7 +791,7 @@ void BulletPhysicsServer::body_remove_collision_exception(RID p_body, RID p_body RigidBodyBullet *body = rigid_body_owner.get(p_body); ERR_FAIL_COND(!body); - RigidBodyBullet *other_body = rigid_body_owner.get(p_body_b); + CollisionObjectBullet *other_body = get_collisin_object(p_body_b); ERR_FAIL_COND(!other_body); body->remove_collision_exception(other_body); @@ -881,6 +882,572 @@ int BulletPhysicsServer::body_test_ray_separation(RID p_body, const Transform &p return body->get_space()->test_ray_separation(body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin); } +RID BulletPhysicsServer::armature_create() { + ArmatureBullet *body = bulletnew(ArmatureBullet); + CreateThenReturnRID(armature_owner, body); +} + +void BulletPhysicsServer::armature_set_bone_count(RID p_armature, int p_count) { + ArmatureBullet *body = armature_owner.get(p_armature); + ERR_FAIL_COND(!body); + + body->set_bone_count(p_count); +} + +int BulletPhysicsServer::armature_get_bone_count(RID p_armature) const { + ArmatureBullet *body = armature_owner.get(p_armature); + ERR_FAIL_COND_V(!body, 0); + + return body->get_bone_count(); +} + +void BulletPhysicsServer::armature_set_force_integration_callback( + RID p_body, + Object *p_receiver, + const StringName &p_method, + const Variant &p_udata) { + + ArmatureBullet *body = armature_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_force_integration_callback( + p_receiver ? p_receiver->get_instance_id() : ObjectID(0), + p_method, + p_udata); +} + +void BulletPhysicsServer::armature_set_space(RID p_body, RID p_space) { + ArmatureBullet *body = armature_owner.get(p_body); + ERR_FAIL_COND(!body); + + SpaceBullet *space = NULL; + + if (p_space.is_valid()) { + space = space_owner.get(p_space); + ERR_FAIL_COND(!space); + } + + body->set_space(space); +} + +RID BulletPhysicsServer::armature_get_space(RID p_body) const { + ArmatureBullet *body = armature_owner.get(p_body); + ERR_FAIL_COND_V(!body, RID()); + + SpaceBullet *space = body->get_space(); + if (!space) + return RID(); + + return space->get_self(); +} + +void BulletPhysicsServer::armature_set_active(RID p_body, bool p_active) { + ArmatureBullet *body = armature_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_active(p_active); +} + +void BulletPhysicsServer::armature_set_param(RID p_body, ArmatureParameter p_param, float p_value) { + ArmatureBullet *body = armature_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_param(p_param, p_value); +} + +float BulletPhysicsServer::armature_get_param(RID p_body, ArmatureParameter p_param) const { + ArmatureBullet *body = armature_owner.get(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_param(p_param); +} + +RID BulletPhysicsServer::bone_create() { + BoneBullet *body = bulletnew(BoneBullet); + body->set_collision_layer(1); + body->set_collision_mask(1); + CreateThenReturnRID(bone_owner, body); +} + +void BulletPhysicsServer::bone_set_force_integration_callback( + RID p_body, + Object *p_receiver, + const StringName &p_method, + const Variant &p_udata) { + + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_force_integration_callback( + p_receiver ? p_receiver->get_instance_id() : ObjectID(0), + p_method, + p_udata); +} + +void BulletPhysicsServer::bone_set_armature(RID p_body, RID p_armature) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + ArmatureBullet *parent = NULL; + + if (p_armature.is_valid()) { + parent = armature_owner.get(p_armature); + ERR_FAIL_COND(!parent); + } + + body->set_armature(parent); +} + +RID BulletPhysicsServer::bone_get_armature(RID p_body) const { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, RID()); + + ArmatureBullet *armature = body->get_armature(); + if (!armature) + return RID(); + return armature->get_self(); +} + +void BulletPhysicsServer::bone_set_max_contacts_reported(RID p_body, int p_contacts) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_max_collisions_detection(p_contacts); +} + +int BulletPhysicsServer::bone_get_max_contacts_reported(RID p_body) const { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_max_collisions_detection(); +} + +void BulletPhysicsServer::bone_set_id(RID p_body, int p_link_id) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_bone_id(p_link_id); +} + +int BulletPhysicsServer::bone_get_id(RID p_body) const { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, -1); + + return body->get_bone_id(); +} + +void BulletPhysicsServer::bone_set_parent_id(RID p_body, int p_id) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_parent_bone_id(p_id); +} + +int BulletPhysicsServer::bone_get_parent_id(RID p_body) const { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, -1); + + return body->get_parent_bone_id(); +} + +void BulletPhysicsServer::bone_set_transform(RID p_body, const Transform &p_transform) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_transform(p_transform); +} + +Transform BulletPhysicsServer::bone_get_transform(RID p_body) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, Transform()); + + return body->get_transform(); +} + +void BulletPhysicsServer::bone_set_joint_transform(RID p_body, const Transform &p_transform) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_joint_offset(p_transform); +} + +Transform BulletPhysicsServer::bone_get_joint_transform(RID p_body) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, Transform()); + + return body->get_joint_offset(); +} + +void BulletPhysicsServer::bone_add_shape(RID p_body, RID p_shape, const Transform &p_transform, bool p_disabled) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + ShapeBullet *shape = shape_owner.get(p_shape); + ERR_FAIL_COND(!shape); + + body->add_shape(shape, p_transform, p_disabled); +} + +void BulletPhysicsServer::bone_set_shape(RID p_body, int p_shape_idx, RID p_shape) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + ShapeBullet *shape = shape_owner.get(p_shape); + ERR_FAIL_COND(!shape); + + body->set_shape(p_shape_idx, shape); +} + +void BulletPhysicsServer::bone_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_shape_transform(p_shape_idx, p_transform); +} + +int BulletPhysicsServer::bone_get_shape_count(RID p_body) const { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, 0); + return body->get_shape_count(); +} + +RID BulletPhysicsServer::bone_get_shape(RID p_body, int p_shape_idx) const { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, RID()); + + ShapeBullet *shape = body->get_shape(p_shape_idx); + ERR_FAIL_COND_V(!shape, RID()); + + return shape->get_self(); +} + +Transform BulletPhysicsServer::bone_get_shape_transform(RID p_body, int p_shape_idx) const { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, Transform()); + return body->get_shape_transform(p_shape_idx); +} + +void BulletPhysicsServer::bone_remove_shape(RID p_body, int p_shape_idx) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->remove_shape_full(p_shape_idx); +} + +void BulletPhysicsServer::bone_clear_shapes(RID p_body) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->remove_all_shapes(); +} + +void BulletPhysicsServer::bone_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_shape_disabled(p_shape_idx, p_disabled); +} + +void BulletPhysicsServer::bone_attach_object_instance_id(RID p_body, uint32_t p_ID) { + CollisionObjectBullet *body = get_collisin_object(p_body); + ERR_FAIL_COND(!body); + + body->set_instance_id(p_ID); +} + +uint32_t BulletPhysicsServer::bone_get_object_instance_id(RID p_body) const { + CollisionObjectBullet *body = get_collisin_object(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_instance_id(); +} + +void BulletPhysicsServer::bone_set_disable_parent_collision(RID p_body, bool p_disable) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_disable_parent_collision(p_disable); +} + +bool BulletPhysicsServer::bone_get_disable_parent_collision(RID p_body) const { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, false); + + return body->get_disable_parent_collision(); +} + +void BulletPhysicsServer::bone_set_joint_limit_active(RID p_body, bool p_active) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_limit_active(p_active); +} + +void BulletPhysicsServer::bone_set_joint_lower_limit(RID p_body, real_t p_lower_limits) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_lower_limit(p_lower_limits); +} + +void BulletPhysicsServer::bone_set_joint_upper_limit(RID p_body, real_t p_upper_limits) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_upper_limit(p_upper_limits); +} + +void BulletPhysicsServer::bone_set_collision_layer(RID p_body, uint32_t p_layer) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_collision_layer(p_layer); +} + +uint32_t BulletPhysicsServer::bone_get_collision_layer(RID p_body) const { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_collision_layer(); +} + +void BulletPhysicsServer::bone_set_collision_mask(RID p_body, uint32_t p_mask) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_collision_mask(p_mask); +} + +uint32_t BulletPhysicsServer::bone_get_collision_mask(RID p_body) const { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_collision_mask(); +} + +void BulletPhysicsServer::bone_set_link_mass(RID p_body, float p_value) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_link_mass(p_value); +} + +float BulletPhysicsServer::bone_get_link_mass(RID p_body) const { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_link_mass(); +} + +void BulletPhysicsServer::bone_set_param(RID p_body, BodyParameter p_param, float p_value) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_param(p_param, p_value); +} + +float BulletPhysicsServer::bone_get_param(RID p_body, BodyParameter p_param) const { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_param(p_param); +} + +void BulletPhysicsServer::bone_joint_fixed_setup(RID p_body) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->setup_joint_fixed(); +} + +void BulletPhysicsServer::bone_joint_slider_setup(RID p_body) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->setup_joint_prismatic(); +} + +void BulletPhysicsServer::bone_joint_hinge_setup(RID p_body) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->setup_joint_revolute(); +} + +void BulletPhysicsServer::bone_joint_spherical_setup(RID p_body) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->setup_joint_spherical(); +} + +void BulletPhysicsServer::bone_joint_planar_setup(RID p_body) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->setup_joint_planar(); +} + +void BulletPhysicsServer::bone_set_motor_enabled(RID p_body, bool p_v) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_motor_enabled(p_v); +} +bool BulletPhysicsServer::bone_get_motor_enabled(RID p_body) const { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, false); + + return body->get_motor_enabled(); +} + +void BulletPhysicsServer::bone_set_velocity_target(RID p_body, const Vector3 &p_v) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_velocity_target(p_v); +} +Vector3 BulletPhysicsServer::bone_get_velocity_target(RID p_body) const { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, Vector3()); + + return body->get_velocity_target(); +} + +void BulletPhysicsServer::bone_set_position_target(RID p_body, real_t p_v) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_position_target(p_v); +} +real_t BulletPhysicsServer::bone_get_position_target(RID p_body) const { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_position_target(); +} + +void BulletPhysicsServer::bone_set_rotation_target(RID p_body, const Basis &p_v) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_rotation_target(p_v); +} +Basis BulletPhysicsServer::bone_get_rotation_target(RID p_body) const { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, Basis()); + + return body->get_rotation_target(); +} + +void BulletPhysicsServer::bone_set_max_motor_impulse(RID p_body, real_t p_v) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_max_motor_impulse(p_v); +} +real_t BulletPhysicsServer::bone_get_max_motor_impulse(RID p_body) const { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_max_motor_impulse(); +} + +void BulletPhysicsServer::bone_set_error_reduction_parameter(RID p_body, real_t p_v) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_error_reduction_parameter(p_v); +} +real_t BulletPhysicsServer::bone_get_error_reduction_parameter(RID p_body) const { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_error_reduction_parameter(); +} + +void BulletPhysicsServer::bone_set_spring_constant(RID p_body, real_t p_v) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_spring_constant(p_v); +} +real_t BulletPhysicsServer::bone_get_spring_constant(RID p_body) const { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_spring_constant(); +} + +void BulletPhysicsServer::bone_set_damping_constant(RID p_body, real_t p_v) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_damping_constant(p_v); +} +real_t BulletPhysicsServer::bone_get_damping_constant(RID p_body) const { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_damping_constant(); +} + +void BulletPhysicsServer::bone_set_maximum_error(RID p_body, real_t p_v) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_maximum_error(p_v); +} +real_t BulletPhysicsServer::bone_get_maximum_error(RID p_body) const { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_maximum_error(); +} + +void BulletPhysicsServer::bone_add_collision_exception(RID p_body, RID p_body_b) { + + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + CollisionObjectBullet *other_body = get_collisin_object(p_body_b); + ERR_FAIL_COND(!other_body); + + body->add_collision_exception(other_body); +} + +void BulletPhysicsServer::bone_remove_collision_exception(RID p_body, RID p_body_b) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + + CollisionObjectBullet *other_body = get_collisin_object(p_body_b); + ERR_FAIL_COND(!other_body); + + body->remove_collision_exception(other_body); +} + +void BulletPhysicsServer::bone_get_collision_exceptions(RID p_body, List *p_exceptions) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND(!body); + for (int i = 0; i < body->get_exceptions().size(); i++) { + p_exceptions->push_back(body->get_exceptions()[i]); + } +} + +Vector3 BulletPhysicsServer::bone_joint_get_force(RID p_body) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, Vector3()); + + return body->get_joint_force(); +} + +Vector3 BulletPhysicsServer::bone_joint_get_torque(RID p_body) { + BoneBullet *body = bone_owner.get(p_body); + ERR_FAIL_COND_V(!body, Vector3()); + + return body->get_joint_torque(); +} + RID BulletPhysicsServer::soft_body_create(bool p_init_sleeping) { SoftBodyBullet *body = bulletnew(SoftBodyBullet); body->set_collision_layer(1); @@ -1209,22 +1776,40 @@ bool BulletPhysicsServer::joint_is_disabled_collisions_between_bodies(RID p_join } RID BulletPhysicsServer::joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) { - RigidBodyBullet *body_A = rigid_body_owner.get(p_body_A); - ERR_FAIL_COND_V(!body_A, RID()); + JointBullet *joint(NULL); - JointAssertSpace(body_A, "A", RID()); + RigidBodyBullet *body_B = rigid_body_owner.get(p_body_B); - RigidBodyBullet *body_B = NULL; - if (p_body_B.is_valid()) { - body_B = rigid_body_owner.get(p_body_B); + if (rigid_body_owner.owns(p_body_A)) { + + RigidBodyBullet *body_A = rigid_body_owner.get(p_body_A); + JointAssertSpace(body_A, "A", RID()); + + if (p_body_B.is_valid()) { + + ERR_FAIL_COND_V(!body_B, RID()); + JointAssertSpace(body_B, "B", RID()); + ERR_FAIL_COND_V(body_A == body_B, RID()); + JointAssertSameSpace(body_A, body_B, RID()); + } + + joint = bulletnew(PinJointBullet(body_A, p_local_A, body_B, p_local_B)); + AddJointToSpace(body_A, joint); + + } else { + + ERR_FAIL_COND_V(!body_B, RID()); JointAssertSpace(body_B, "B", RID()); - JointAssertSameSpace(body_A, body_B, RID()); - } - ERR_FAIL_COND_V(body_A == body_B, RID()); + BoneBullet *bone_body_A = bone_owner.get(p_body_A); + ERR_FAIL_COND_V(!bone_body_A, RID()); + JointAssertSpace(bone_body_A, "A", RID()); - JointBullet *joint = bulletnew(PinJointBullet(body_A, p_local_A, body_B, p_local_B)); - AddJointToSpace(body_A, joint); + JointAssertSameSpace(bone_body_A, body_B, RID()); + + joint = bulletnew(PinJointBullet(bone_body_A, p_local_A, body_B, p_local_B)); + AddJointToSpace(bone_body_A, joint); + } CreateThenReturnRID(joint_owner, joint); } @@ -1510,6 +2095,24 @@ void BulletPhysicsServer::free(RID p_rid) { rigid_body_owner.free(p_rid); bulletdelete(body); + } else if (armature_owner.owns(p_rid)) { + + ArmatureBullet *body = armature_owner.get(p_rid); + + body->set_space(NULL); + + armature_owner.free(p_rid); + bulletdelete(body); + + } else if (bone_owner.owns(p_rid)) { + + BoneBullet *body = bone_owner.get(p_rid); + + body->set_armature(NULL); + + bone_owner.free(p_rid); + bulletdelete(body); + } else if (soft_body_owner.owns(p_rid)) { SoftBodyBullet *body = soft_body_owner.get(p_rid); @@ -1533,7 +2136,6 @@ void BulletPhysicsServer::free(RID p_rid) { } else if (joint_owner.owns(p_rid)) { JointBullet *joint = joint_owner.get(p_rid); - joint->destroy_internal_constraint(); joint_owner.free(p_rid); bulletdelete(joint); @@ -1555,6 +2157,7 @@ void BulletPhysicsServer::free(RID p_rid) { void BulletPhysicsServer::init() { BulletPhysicsDirectBodyState::initSingleton(); + BoneBulletPhysicsDirectBodyState::initSingleton(); } void BulletPhysicsServer::step(float p_deltaTime) { @@ -1562,6 +2165,7 @@ void BulletPhysicsServer::step(float p_deltaTime) { return; BulletPhysicsDirectBodyState::singleton_setDeltaTime(p_deltaTime); + BoneBulletPhysicsDirectBodyState::singleton_setDeltaTime(p_deltaTime); for (int i = 0; i < active_spaces_count; ++i) { @@ -1577,6 +2181,7 @@ void BulletPhysicsServer::flush_queries() { void BulletPhysicsServer::finish() { BulletPhysicsDirectBodyState::destroySingleton(); + BoneBulletPhysicsDirectBodyState::destroySingleton(); } int BulletPhysicsServer::get_process_info(ProcessInfo p_info) { @@ -1587,6 +2192,9 @@ CollisionObjectBullet *BulletPhysicsServer::get_collisin_object(RID p_object) co if (rigid_body_owner.owns(p_object)) { return rigid_body_owner.getornull(p_object); } + if (bone_owner.owns(p_object)) { + return bone_owner.getornull(p_object); + } if (area_owner.owns(p_object)) { return area_owner.getornull(p_object); } @@ -1600,6 +2208,9 @@ RigidCollisionObjectBullet *BulletPhysicsServer::get_rigid_collisin_object(RID p if (rigid_body_owner.owns(p_object)) { return rigid_body_owner.getornull(p_object); } + if (bone_owner.owns(p_object)) { + return bone_owner.getornull(p_object); + } if (area_owner.owns(p_object)) { return area_owner.getornull(p_object); } diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h index 4c598c84f281..e6ef60b9a653 100644 --- a/modules/bullet/bullet_physics_server.h +++ b/modules/bullet/bullet_physics_server.h @@ -32,6 +32,7 @@ #define BULLET_PHYSICS_SERVER_H #include "area_bullet.h" +#include "armature_bullet.h" #include "core/rid.h" #include "joint_bullet.h" #include "rigid_body_bullet.h" @@ -57,6 +58,8 @@ class BulletPhysicsServer : public PhysicsServer { mutable RID_Owner shape_owner; mutable RID_Owner area_owner; mutable RID_Owner rigid_body_owner; + mutable RID_Owner armature_owner; + mutable RID_Owner bone_owner; mutable RID_Owner soft_body_owner; mutable RID_Owner joint_owner; @@ -79,6 +82,9 @@ class BulletPhysicsServer : public PhysicsServer { _FORCE_INLINE_ RID_Owner *get_rigid_body_owner() { return &rigid_body_owner; } + _FORCE_INLINE_ RID_Owner *get_multibody_owner() { + return &armature_owner; + } _FORCE_INLINE_ RID_Owner *get_soft_body_owner() { return &soft_body_owner; } @@ -257,6 +263,122 @@ class BulletPhysicsServer : public PhysicsServer { virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true); virtual int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001); + /* ARMATURE API */ + + virtual RID armature_create(); + + virtual void armature_set_bone_count(RID p_armature, int p_count); + virtual int armature_get_bone_count(RID p_armature) const; + + virtual void armature_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()); + + virtual void armature_set_space(RID p_body, RID p_space); + virtual RID armature_get_space(RID p_body) const; + + virtual void armature_set_active(RID p_body, bool p_active); + + virtual void armature_set_param(RID p_body, ArmatureParameter p_param, float p_value); + virtual float armature_get_param(RID p_body, ArmatureParameter p_param) const; + + /* BONE API*/ + + virtual RID bone_create(); + + virtual void bone_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()); + + virtual void bone_set_armature(RID p_body, RID p_parent); + virtual RID bone_get_armature(RID p_body) const; + + virtual void bone_set_max_contacts_reported(RID p_body, int p_contacts); + virtual int bone_get_max_contacts_reported(RID p_body) const; + + virtual void bone_set_id(RID p_body, int p_link_id); + virtual int bone_get_id(RID p_body) const; + + virtual void bone_set_parent_id(RID p_body, int p_id); + virtual int bone_get_parent_id(RID p_body) const; + + virtual void bone_set_transform(RID p_body, const Transform &p_transform); + virtual Transform bone_get_transform(RID p_body); + + virtual void bone_set_joint_transform(RID p_body, const Transform &p_transform); + virtual Transform bone_get_joint_transform(RID p_body); + + virtual void bone_add_shape(RID p_body, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false); + virtual void bone_set_shape(RID p_body, int p_shape_idx, RID p_shape); + virtual void bone_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform); + + virtual int bone_get_shape_count(RID p_body) const; + virtual RID bone_get_shape(RID p_body, int p_shape_idx) const; + virtual Transform bone_get_shape_transform(RID p_body, int p_shape_idx) const; + + virtual void bone_remove_shape(RID p_body, int p_shape_idx); + virtual void bone_clear_shapes(RID p_body); + + virtual void bone_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled); + + virtual void bone_attach_object_instance_id(RID p_body, uint32_t p_ID); + virtual uint32_t bone_get_object_instance_id(RID p_body) const; + + virtual void bone_set_disable_parent_collision(RID p_body, bool p_disable); + virtual bool bone_get_disable_parent_collision(RID p_body) const; + + virtual void bone_set_joint_limit_active(RID p_body, bool p_active); + virtual void bone_set_joint_lower_limit(RID p_body, real_t p_lower_limits); + virtual void bone_set_joint_upper_limit(RID p_body, real_t p_upper_limits); + + virtual void bone_set_collision_layer(RID p_body, uint32_t p_layer); + virtual uint32_t bone_get_collision_layer(RID p_body) const; + + virtual void bone_set_collision_mask(RID p_body, uint32_t p_mask); + virtual uint32_t bone_get_collision_mask(RID p_body) const; + + virtual void bone_set_link_mass(RID p_body, float p_value); + virtual float bone_get_link_mass(RID p_body) const; + + virtual void bone_set_param(RID p_body, BodyParameter p_param, float p_value); + virtual float bone_get_param(RID p_body, BodyParameter p_param) const; + + virtual void bone_joint_fixed_setup(RID p_body); + virtual void bone_joint_slider_setup(RID p_body); + virtual void bone_joint_hinge_setup(RID p_body); + virtual void bone_joint_spherical_setup(RID p_body); + virtual void bone_joint_planar_setup(RID p_body); + + virtual void bone_set_motor_enabled(RID p_body, bool p_v); + virtual bool bone_get_motor_enabled(RID p_body) const; + + virtual void bone_set_velocity_target(RID p_body, const Vector3 &p_v); + virtual Vector3 bone_get_velocity_target(RID p_body) const; + + virtual void bone_set_position_target(RID p_body, real_t p_v); + virtual real_t bone_get_position_target(RID p_body) const; + + virtual void bone_set_rotation_target(RID p_body, const Basis &p_v); + virtual Basis bone_get_rotation_target(RID p_body) const; + + virtual void bone_set_max_motor_impulse(RID p_body, real_t p_v); + virtual real_t bone_get_max_motor_impulse(RID p_body) const; + + virtual void bone_set_error_reduction_parameter(RID p_body, real_t p_v); + virtual real_t bone_get_error_reduction_parameter(RID p_body) const; + + virtual void bone_set_spring_constant(RID p_body, real_t p_v); + virtual real_t bone_get_spring_constant(RID p_body) const; + + virtual void bone_set_damping_constant(RID p_body, real_t p_v); + virtual real_t bone_get_damping_constant(RID p_body) const; + + virtual void bone_set_maximum_error(RID p_body, real_t p_v); + virtual real_t bone_get_maximum_error(RID p_body) const; + + virtual void bone_add_collision_exception(RID p_body, RID p_body_b); + virtual void bone_remove_collision_exception(RID p_body, RID p_body_b); + virtual void bone_get_collision_exceptions(RID p_body, List *p_exceptions); + + virtual Vector3 bone_joint_get_force(RID p_body); + virtual Vector3 bone_joint_get_torque(RID p_body); + /* SOFT BODY API */ virtual RID soft_body_create(bool p_init_sleeping = false); diff --git a/modules/bullet/collision_object_bullet.cpp b/modules/bullet/collision_object_bullet.cpp index e1800fd3eb6e..31c428f325e2 100644 --- a/modules/bullet/collision_object_bullet.cpp +++ b/modules/bullet/collision_object_bullet.cpp @@ -37,8 +37,6 @@ #include "shape_bullet.h" #include "space_bullet.h" -#include - /** @author AndreaCatania */ @@ -227,7 +225,13 @@ void CollisionObjectBullet::notify_transform_changed() { RigidCollisionObjectBullet::RigidCollisionObjectBullet(Type p_type) : CollisionObjectBullet(p_type), - mainShape(NULL) { + mainShape(NULL), + maxCollisionsDetection(0), + collisionsCount(0), + prev_collision_count(0) { + + prev_collision_traces = &collision_traces_1; + curr_collision_traces = &collision_traces_2; } RigidCollisionObjectBullet::~RigidCollisionObjectBullet() { @@ -394,6 +398,50 @@ void RigidCollisionObjectBullet::body_scale_changed() { reload_shapes(); } +void RigidCollisionObjectBullet::on_collision_checker_start() { + + prev_collision_count = collisionsCount; + collisionsCount = 0; + + // Swap array + Vector *s = prev_collision_traces; + prev_collision_traces = curr_collision_traces; + curr_collision_traces = s; +} + +void RigidCollisionObjectBullet::on_collision_checker_end() { + isTransformChanged = false; // Override for different behaviour +} + +bool RigidCollisionObjectBullet::add_collision_object(RigidCollisionObjectBullet *p_otherObject, const Vector3 &p_hitWorldLocation, const Vector3 &p_hitLocalLocation, const Vector3 &p_hitNormal, const float &p_appliedImpulse, int p_other_shape_index, int p_local_shape_index) { + + if (collisionsCount >= maxCollisionsDetection) { + return false; + } + + CollisionData &cd = collisions.write[collisionsCount]; + cd.hitLocalLocation = p_hitLocalLocation; + cd.otherObject = p_otherObject; + cd.hitWorldLocation = p_hitWorldLocation; + cd.hitNormal = p_hitNormal; + cd.appliedImpulse = p_appliedImpulse; + cd.other_object_shape = p_other_shape_index; + cd.local_shape = p_local_shape_index; + + curr_collision_traces->write[collisionsCount] = p_otherObject; + + ++collisionsCount; + return true; +} + +bool RigidCollisionObjectBullet::was_colliding(RigidCollisionObjectBullet *p_other_object) { + for (int i = prev_collision_count - 1; 0 <= i; --i) { + if ((*prev_collision_traces)[i] == p_other_object) + return true; + } + return false; +} + void RigidCollisionObjectBullet::internal_shape_destroy(int p_index, bool p_permanentlyFromThisBody) { ShapeWrapper &shp = shapes.write[p_index]; shp.shape->remove_owner(this, p_permanentlyFromThisBody); diff --git a/modules/bullet/collision_object_bullet.h b/modules/bullet/collision_object_bullet.h index c9430bec1857..d0cb51030cdc 100644 --- a/modules/bullet/collision_object_bullet.h +++ b/modules/bullet/collision_object_bullet.h @@ -64,6 +64,7 @@ class CollisionObjectBullet : public RIDBullet { enum Type { TYPE_AREA = 0, TYPE_RIGID_BODY, + TYPE_BONE_BODY, TYPE_SOFT_BODY, TYPE_KINEMATIC_GHOST_BODY }; @@ -213,10 +214,32 @@ class CollisionObjectBullet : public RIDBullet { }; class RigidCollisionObjectBullet : public CollisionObjectBullet, public ShapeOwnerBullet { +public: + struct CollisionData { + RigidCollisionObjectBullet *otherObject; + int other_object_shape; + int local_shape; + Vector3 hitLocalLocation; + Vector3 hitWorldLocation; + Vector3 hitNormal; + float appliedImpulse; + }; + protected: btCollisionShape *mainShape; Vector shapes; + Vector collisions; + Vector collision_traces_1; + Vector collision_traces_2; + Vector *prev_collision_traces; + Vector *curr_collision_traces; + + // these parameters are used to avoid vector resize + int maxCollisionsDetection; + int collisionsCount; + int prev_collision_count; + public: RigidCollisionObjectBullet(Type p_type); ~RigidCollisionObjectBullet(); @@ -252,6 +275,31 @@ class RigidCollisionObjectBullet : public CollisionObjectBullet, public ShapeOwn virtual void main_shape_changed() = 0; virtual void body_scale_changed(); + void set_max_collisions_detection(int p_maxCollisionsDetection) { + + ERR_FAIL_COND(0 > p_maxCollisionsDetection); + + maxCollisionsDetection = p_maxCollisionsDetection; + + collisions.resize(p_maxCollisionsDetection); + collision_traces_1.resize(p_maxCollisionsDetection); + collision_traces_2.resize(p_maxCollisionsDetection); + + collisionsCount = 0; + prev_collision_count = MIN(prev_collision_count, p_maxCollisionsDetection); + } + + int get_max_collisions_detection() { + return maxCollisionsDetection; + } + + virtual void on_collision_checker_start(); + virtual void on_collision_checker_end(); + + bool can_add_collision() { return collisionsCount < maxCollisionsDetection; } + bool add_collision_object(RigidCollisionObjectBullet *p_otherObject, const Vector3 &p_hitWorldLocation, const Vector3 &p_hitLocalLocation, const Vector3 &p_hitNormal, const float &p_appliedImpulse, int p_other_shape_index, int p_local_shape_index); + bool was_colliding(RigidCollisionObjectBullet *p_other_object); + private: void internal_shape_destroy(int p_index, bool p_permanentlyFromThisBody = false); }; diff --git a/modules/bullet/constraint_bullet.cpp b/modules/bullet/constraint_bullet.cpp deleted file mode 100644 index f3f3907ada58..000000000000 --- a/modules/bullet/constraint_bullet.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/*************************************************************************/ -/* constraint_bullet.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "constraint_bullet.h" - -#include "collision_object_bullet.h" -#include "space_bullet.h" - -/** - @author AndreaCatania -*/ - -ConstraintBullet::ConstraintBullet() : - space(NULL), - constraint(NULL), - disabled_collisions_between_bodies(true) {} - -void ConstraintBullet::setup(btTypedConstraint *p_constraint) { - constraint = p_constraint; - constraint->setUserConstraintPtr(this); -} - -void ConstraintBullet::set_space(SpaceBullet *p_space) { - space = p_space; -} - -void ConstraintBullet::destroy_internal_constraint() { - space->remove_constraint(this); -} - -void ConstraintBullet::disable_collisions_between_bodies(const bool p_disabled) { - disabled_collisions_between_bodies = p_disabled; - - if (space) { - space->remove_constraint(this); - space->add_constraint(this, disabled_collisions_between_bodies); - } -} diff --git a/modules/bullet/constraint_bullet.h b/modules/bullet/constraint_bullet.h deleted file mode 100644 index f6ac3e80c227..000000000000 --- a/modules/bullet/constraint_bullet.h +++ /dev/null @@ -1,72 +0,0 @@ -/*************************************************************************/ -/* constraint_bullet.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef CONSTRAINT_BULLET_H -#define CONSTRAINT_BULLET_H - -#include "bullet_utilities.h" -#include "rid_bullet.h" - -#include - -/** - @author AndreaCatania -*/ - -class RigidBodyBullet; -class SpaceBullet; -class btTypedConstraint; - -class ConstraintBullet : public RIDBullet { - -protected: - SpaceBullet *space; - btTypedConstraint *constraint; - bool disabled_collisions_between_bodies; - -public: - ConstraintBullet(); - - virtual void setup(btTypedConstraint *p_constraint); - virtual void set_space(SpaceBullet *p_space); - virtual void destroy_internal_constraint(); - - void disable_collisions_between_bodies(const bool p_disabled); - _FORCE_INLINE_ bool is_disabled_collisions_between_bodies() const { return disabled_collisions_between_bodies; } - -public: - virtual ~ConstraintBullet() { - bulletdelete(constraint); - constraint = NULL; - } - - _FORCE_INLINE_ btTypedConstraint *get_bt_constraint() { return constraint; } -}; -#endif diff --git a/modules/bullet/joint_bullet.cpp b/modules/bullet/joint_bullet.cpp index a52b05f5c416..f35dc2dd0428 100644 --- a/modules/bullet/joint_bullet.cpp +++ b/modules/bullet/joint_bullet.cpp @@ -30,6 +30,8 @@ #include "joint_bullet.h" +#include "armature_bullet.h" +#include "collision_object_bullet.h" #include "space_bullet.h" /** @@ -37,6 +39,68 @@ */ JointBullet::JointBullet() : - ConstraintBullet() {} + space(NULL), + body_a(NULL), + body_b(NULL), + constraint(NULL), + multibody_constraint(NULL), + disabled_collisions_between_bodies(true) {} -JointBullet::~JointBullet() {} +JointBullet::~JointBullet() { + clear_internal_joint(); +} + +void JointBullet::setup(btTypedConstraint *p_constraint) { + ERR_FAIL_COND(constraint != NULL); + ERR_FAIL_COND(multibody_constraint != NULL); + constraint = p_constraint; + constraint->setUserConstraintPtr(this); +} + +void JointBullet::setup(btMultiBodyConstraint *p_constraint, BoneBullet *p_body_a, BoneBullet *p_body_b) { + ERR_FAIL_COND(constraint != NULL); + ERR_FAIL_COND(multibody_constraint != NULL); + multibody_constraint = p_constraint; + + body_a = p_body_a; + body_b = p_body_b; + + body_a->get_armature()->register_ext_joint(this); + + if (body_b) + body_b->get_armature()->register_ext_joint(this); +} + +void JointBullet::set_space(SpaceBullet *p_space) { + space = p_space; +} + +void JointBullet::disable_collisions_between_bodies(const bool p_disabled) { + disabled_collisions_between_bodies = p_disabled; + + if (space) { + space->remove_constraint(this); + space->add_constraint(this, disabled_collisions_between_bodies); + } +} + +void JointBullet::clear_internal_joint() { + if (space) + space->remove_constraint(this); + + bulletdelete(constraint); + constraint = NULL; + bulletdelete(multibody_constraint); + multibody_constraint = NULL; + + if (body_a) + if (body_a->get_armature()) + body_a->get_armature()->erase_ext_joint(this); + + if (body_b) + if (body_b->get_armature()) + body_b->get_armature()->erase_ext_joint(this); + + body_a = NULL; + body_b = NULL; +} diff --git a/modules/bullet/joint_bullet.h b/modules/bullet/joint_bullet.h index d2c2796367e3..b2e024374ba8 100644 --- a/modules/bullet/joint_bullet.h +++ b/modules/bullet/joint_bullet.h @@ -31,8 +31,11 @@ #ifndef JOINT_BULLET_H #define JOINT_BULLET_H -#include "constraint_bullet.h" +#include "bullet_utilities.h" +#include "rid_bullet.h" #include "servers/physics_server.h" +#include +#include /** @author AndreaCatania @@ -40,13 +43,46 @@ class RigidBodyBullet; class btTypedConstraint; +class RigidBodyBullet; +class SpaceBullet; +class BoneBullet; + +class JointBullet : public RIDBullet { -class JointBullet : public ConstraintBullet { +protected: + SpaceBullet *space; + BoneBullet *body_a; + BoneBullet *body_b; + btTypedConstraint *constraint; + btMultiBodyConstraint *multibody_constraint; + bool disabled_collisions_between_bodies; public: JointBullet(); virtual ~JointBullet(); + BoneBullet *get_body_a() const { + return body_a; + } + + BoneBullet *get_body_b() const { + return body_b; + } + + virtual void reload_internal() {} virtual PhysicsServer::JointType get_type() const = 0; + + virtual void setup(btTypedConstraint *p_constraint); + virtual void setup(btMultiBodyConstraint *p_constraint, BoneBullet *p_body_a, BoneBullet *p_body_b); + virtual void set_space(SpaceBullet *p_space); + + void disable_collisions_between_bodies(const bool p_disabled); + _FORCE_INLINE_ bool is_disabled_collisions_between_bodies() const { return disabled_collisions_between_bodies; } + + _FORCE_INLINE_ bool is_multi_joint() { return constraint == NULL; } + _FORCE_INLINE_ btTypedConstraint *get_bt_constraint() { return constraint; } + _FORCE_INLINE_ btMultiBodyConstraint *get_bt_mb_constraint() { return multibody_constraint; } + + virtual void clear_internal_joint(); }; #endif diff --git a/modules/bullet/pin_joint_bullet.cpp b/modules/bullet/pin_joint_bullet.cpp index c9c4d1af7ea3..337f8876da7d 100644 --- a/modules/bullet/pin_joint_bullet.cpp +++ b/modules/bullet/pin_joint_bullet.cpp @@ -30,15 +30,83 @@ #include "pin_joint_bullet.h" +#include "armature_bullet.h" #include "bullet_types_converter.h" #include "rigid_body_bullet.h" #include +#include /** @author AndreaCatania */ +class GodotMultiBodyPoint2Point : public btMultiBodyPoint2Point { + +public: + GodotMultiBodyPoint2Point( + btMultiBody *body, + int link, + btRigidBody *bodyB, + const btVector3 &pivotInA, + const btVector3 &pivotInB) : + + btMultiBodyPoint2Point( + body, + link, + bodyB, + pivotInA, + pivotInB) {} + + void set_linkA(int p_link_id) { + m_linkA = p_link_id; + } + + btRigidBody *get_rigidBodyA() { + return m_rigidBodyA; + } + + btRigidBody *get_rigidBodyB() { + return m_rigidBodyB; + } + + void set_pivotInA(btVector3 &p_pivot) { + m_pivotInA = p_pivot; + } + + btVector3 &get_pivotInA() { + return m_pivotInA; + } + + btVector3 &get_pivotInB() { + return m_pivotInB; + } +}; + +PinJointBullet::PinJointBullet(BoneBullet *p_body_a, const Vector3 &p_pos_a, RigidBodyBullet *p_body_b, const Vector3 &p_pos_b) : + JointBullet() { + + ERR_FAIL_COND(!p_body_a); + ERR_FAIL_COND(!p_body_b); + + btVector3 btPivotA; + btVector3 btPivotB; + G_TO_B(p_pos_a * p_body_a->get_body_scale(), btPivotA); + G_TO_B(p_pos_b * p_body_b->get_body_scale(), btPivotB); + mb_p2pConstraint = bulletnew(GodotMultiBodyPoint2Point( + p_body_a->get_armature()->get_bt_body(), + p_body_a->get_link_id(), + p_body_b->get_bt_rigid_body(), + btPivotA, + btPivotB)); + + p2pConstraint = NULL; + setup( + mb_p2pConstraint, + p_body_a, + NULL); +} + PinJointBullet::PinJointBullet(RigidBodyBullet *p_body_a, const Vector3 &p_pos_a, RigidBodyBullet *p_body_b, const Vector3 &p_pos_b) : JointBullet() { if (p_body_b) { @@ -47,7 +115,8 @@ PinJointBullet::PinJointBullet(RigidBodyBullet *p_body_a, const Vector3 &p_pos_a btVector3 btPivotB; G_TO_B(p_pos_a * p_body_a->get_body_scale(), btPivotA); G_TO_B(p_pos_b * p_body_b->get_body_scale(), btPivotB); - p2pConstraint = bulletnew(btPoint2PointConstraint(*p_body_a->get_bt_rigid_body(), + p2pConstraint = bulletnew(btPoint2PointConstraint( + *p_body_a->get_bt_rigid_body(), *p_body_b->get_bt_rigid_body(), btPivotA, btPivotB)); @@ -57,62 +126,113 @@ PinJointBullet::PinJointBullet(RigidBodyBullet *p_body_a, const Vector3 &p_pos_a p2pConstraint = bulletnew(btPoint2PointConstraint(*p_body_a->get_bt_rigid_body(), btPivotA)); } + mb_p2pConstraint = NULL; setup(p2pConstraint); } PinJointBullet::~PinJointBullet() {} -void PinJointBullet::set_param(PhysicsServer::PinJointParam p_param, real_t p_value) { - switch (p_param) { - case PhysicsServer::PIN_JOINT_BIAS: - p2pConstraint->m_setting.m_tau = p_value; - break; - case PhysicsServer::PIN_JOINT_DAMPING: - p2pConstraint->m_setting.m_damping = p_value; - break; - case PhysicsServer::PIN_JOINT_IMPULSE_CLAMP: - p2pConstraint->m_setting.m_impulseClamp = p_value; - break; +void PinJointBullet::reload_internal() { + if (mb_p2pConstraint) { + mb_p2pConstraint->set_linkA(body_a->get_link_id()); } } +void PinJointBullet::set_param(PhysicsServer::PinJointParam p_param, real_t p_value) { + if (p2pConstraint) + switch (p_param) { + case PhysicsServer::PIN_JOINT_BIAS: + p2pConstraint->m_setting.m_tau = p_value; + break; + case PhysicsServer::PIN_JOINT_DAMPING: + p2pConstraint->m_setting.m_damping = p_value; + break; + case PhysicsServer::PIN_JOINT_IMPULSE_CLAMP: + p2pConstraint->m_setting.m_impulseClamp = p_value; + break; + } + + if (mb_p2pConstraint) + switch (p_param) { + case PhysicsServer::PIN_JOINT_BIAS: + break; + case PhysicsServer::PIN_JOINT_DAMPING: + break; + case PhysicsServer::PIN_JOINT_IMPULSE_CLAMP: + break; + } +} + real_t PinJointBullet::get_param(PhysicsServer::PinJointParam p_param) const { - switch (p_param) { - case PhysicsServer::PIN_JOINT_BIAS: - return p2pConstraint->m_setting.m_tau; - case PhysicsServer::PIN_JOINT_DAMPING: - return p2pConstraint->m_setting.m_damping; - case PhysicsServer::PIN_JOINT_IMPULSE_CLAMP: - return p2pConstraint->m_setting.m_impulseClamp; - default: - ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated"); - WARN_DEPRECATED; - return 0; - } + + if (p2pConstraint) + switch (p_param) { + case PhysicsServer::PIN_JOINT_BIAS: + return p2pConstraint->m_setting.m_tau; + case PhysicsServer::PIN_JOINT_DAMPING: + return p2pConstraint->m_setting.m_damping; + case PhysicsServer::PIN_JOINT_IMPULSE_CLAMP: + return p2pConstraint->m_setting.m_impulseClamp; + default: + ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated"); + WARN_DEPRECATED + return 0; + } + + if (mb_p2pConstraint) + return 0; + + return 0; } void PinJointBullet::setPivotInA(const Vector3 &p_pos) { btVector3 btVec; G_TO_B(p_pos, btVec); - p2pConstraint->setPivotA(btVec); + + if (p2pConstraint) + p2pConstraint->setPivotA(btVec); + else + mb_p2pConstraint->set_pivotInA(btVec); } void PinJointBullet::setPivotInB(const Vector3 &p_pos) { btVector3 btVec; G_TO_B(p_pos, btVec); - p2pConstraint->setPivotB(btVec); + + if (p2pConstraint) + p2pConstraint->setPivotB(btVec); + else + mb_p2pConstraint->setPivotInB(btVec); } Vector3 PinJointBullet::getPivotInA() { - btVector3 vec = p2pConstraint->getPivotInA(); + btVector3 vec; + + if (p2pConstraint) + vec = p2pConstraint->getPivotInA(); + else + vec = mb_p2pConstraint->get_pivotInA(); + Vector3 gVec; B_TO_G(vec, gVec); return gVec; } Vector3 PinJointBullet::getPivotInB() { - btVector3 vec = p2pConstraint->getPivotInB(); + btVector3 vec; + + if (p2pConstraint) + vec = p2pConstraint->getPivotInB(); + else + vec = mb_p2pConstraint->getPivotInB(); + Vector3 gVec; B_TO_G(vec, gVec); return gVec; } + +void PinJointBullet::clear_internal_joint() { + JointBullet::clear_internal_joint(); + p2pConstraint = NULL; + mb_p2pConstraint = NULL; +} diff --git a/modules/bullet/pin_joint_bullet.h b/modules/bullet/pin_joint_bullet.h index 7c0c5be329f0..92181ec0d365 100644 --- a/modules/bullet/pin_joint_bullet.h +++ b/modules/bullet/pin_joint_bullet.h @@ -38,14 +38,18 @@ */ class RigidBodyBullet; +class BoneBullet; class PinJointBullet : public JointBullet { class btPoint2PointConstraint *p2pConstraint; + class GodotMultiBodyPoint2Point *mb_p2pConstraint; public: PinJointBullet(RigidBodyBullet *p_body_a, const Vector3 &p_pos_a, RigidBodyBullet *p_body_b, const Vector3 &p_pos_b); + PinJointBullet(BoneBullet *p_body_a, const Vector3 &p_pos_a, RigidBodyBullet *p_body_b, const Vector3 &p_pos_b); ~PinJointBullet(); + virtual void reload_internal(); virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_PIN; } void set_param(PhysicsServer::PinJointParam p_param, real_t p_value); @@ -56,5 +60,7 @@ class PinJointBullet : public JointBullet { Vector3 getPivotInA(); Vector3 getPivotInB(); + + virtual void clear_internal_joint(); }; #endif diff --git a/modules/bullet/register_types.cpp b/modules/bullet/register_types.cpp index 03fb75cc82a6..3d16006c9f7b 100644 --- a/modules/bullet/register_types.cpp +++ b/modules/bullet/register_types.cpp @@ -49,8 +49,23 @@ void register_bullet_types() { PhysicsServerManager::register_server("Bullet", &_createBulletPhysicsCallback); PhysicsServerManager::set_default_server("Bullet", 1); - GLOBAL_DEF("physics/3d/active_soft_world", true); - ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/active_soft_world", PropertyInfo(Variant::BOOL, "physics/3d/active_soft_world")); + GLOBAL_DEF("physics/3d/world_type", 1); + ProjectSettings::get_singleton()->set_custom_property_info( + "physics/3d/world_type", + PropertyInfo( + Variant::INT, + "physics/3d/world_type", + PROPERTY_HINT_ENUM, + "Plain,Soft,Multi body")); + + GLOBAL_DEF("physics/3d/multibody_constraint_solver", 0); + ProjectSettings::get_singleton()->set_custom_property_info( + "physics/3d/multibody_constraint_solver", + PropertyInfo( + Variant::INT, + "physics/3d/multibody_constraint_solver", + PROPERTY_HINT_ENUM, + "Default constraint,Projected Gauss Seidel,Dantzig,Lemke")); #endif } diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp index 085cce9733b2..ed39ea9e90c3 100644 --- a/modules/bullet/rigid_body_bullet.cpp +++ b/modules/bullet/rigid_body_bullet.cpp @@ -40,7 +40,6 @@ #include #include #include -#include #include @@ -188,8 +187,12 @@ Vector3 BulletPhysicsDirectBodyState::get_contact_collider_velocity_at_position( btVector3 hitLocation; G_TO_B(colDat.hitLocalLocation, hitLocation); + btCollisionObject *co = colDat.otherObject->get_bt_collision_object(); + btRigidBody *rb = btRigidBody::upcast(co); + Vector3 velocityAtPoint; - B_TO_G(colDat.otherObject->get_bt_rigid_body()->getVelocityInLocalPoint(hitLocation), velocityAtPoint); + if (rb) + B_TO_G(rb->getVelocityInLocalPoint(hitLocation), velocityAtPoint); return velocityAtPoint; } @@ -266,9 +269,6 @@ RigidBodyBullet::RigidBodyBullet() : can_sleep(true), omit_forces_integration(false), can_integrate_forces(false), - maxCollisionsDetection(0), - collisionsCount(0), - prev_collision_count(0), maxAreasWhereIam(10), areaWhereIamCount(0), countGravityPointSpaces(0), @@ -294,9 +294,6 @@ RigidBodyBullet::RigidBodyBullet() : areasWhereIam.write[i] = NULL; } btBody->setSleepingThresholds(0.2, 0.2); - - prev_collision_traces = &collision_traces_1; - curr_collision_traces = &collision_traces_2; } RigidBodyBullet::~RigidBodyBullet() { @@ -413,51 +410,11 @@ void RigidBodyBullet::on_collision_filters_change() { } } -void RigidBodyBullet::on_collision_checker_start() { - - prev_collision_count = collisionsCount; - collisionsCount = 0; - - // Swap array - Vector *s = prev_collision_traces; - prev_collision_traces = curr_collision_traces; - curr_collision_traces = s; -} - void RigidBodyBullet::on_collision_checker_end() { // Always true if active and not a static or kinematic body isTransformChanged = btBody->isActive() && !btBody->isStaticOrKinematicObject(); } -bool RigidBodyBullet::add_collision_object(RigidBodyBullet *p_otherObject, const Vector3 &p_hitWorldLocation, const Vector3 &p_hitLocalLocation, const Vector3 &p_hitNormal, const float &p_appliedImpulse, int p_other_shape_index, int p_local_shape_index) { - - if (collisionsCount >= maxCollisionsDetection) { - return false; - } - - CollisionData &cd = collisions.write[collisionsCount]; - cd.hitLocalLocation = p_hitLocalLocation; - cd.otherObject = p_otherObject; - cd.hitWorldLocation = p_hitWorldLocation; - cd.hitNormal = p_hitNormal; - cd.appliedImpulse = p_appliedImpulse; - cd.other_object_shape = p_other_shape_index; - cd.local_shape = p_local_shape_index; - - curr_collision_traces->write[collisionsCount] = p_otherObject; - - ++collisionsCount; - return true; -} - -bool RigidBodyBullet::was_colliding(RigidBodyBullet *p_other_object) { - for (int i = prev_collision_count - 1; 0 <= i; --i) { - if ((*prev_collision_traces)[i] == p_other_object) - return true; - } - return false; -} - void RigidBodyBullet::assert_no_constraints() { if (btBody->getNumConstraintRefs()) { WARN_PRINT("A body with a joints is destroyed. Please check the implementation in order to destroy the joint before the body."); diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h index 2c9bdb8b0bb3..5a13db8f7336 100644 --- a/modules/bullet/rigid_body_bullet.h +++ b/modules/bullet/rigid_body_bullet.h @@ -77,11 +77,19 @@ class BulletPhysicsDirectBodyState : public PhysicsDirectBodyState { static BulletPhysicsDirectBodyState *get_singleton(RigidBodyBullet *p_body) { singleton->body = p_body; + singleton->bone = NULL; + return singleton; + } + + static BulletPhysicsDirectBodyState *get_singleton(BoneBullet *p_body) { + singleton->body = NULL; + singleton->bone = p_body; return singleton; } public: RigidBodyBullet *body; + BoneBullet *bone; real_t deltaTime; private: @@ -144,16 +152,6 @@ class BulletPhysicsDirectBodyState : public PhysicsDirectBodyState { class RigidBodyBullet : public RigidCollisionObjectBullet { public: - struct CollisionData { - RigidBodyBullet *otherObject; - int other_object_shape; - int local_shape; - Vector3 hitLocalLocation; - Vector3 hitWorldLocation; - Vector3 hitNormal; - float appliedImpulse; - }; - struct ForceIntegrationCallback { ObjectID id; StringName method; @@ -204,17 +202,6 @@ class RigidBodyBullet : public RigidCollisionObjectBullet { bool omit_forces_integration; bool can_integrate_forces; - Vector collisions; - Vector collision_traces_1; - Vector collision_traces_2; - Vector *prev_collision_traces; - Vector *curr_collision_traces; - - // these parameters are used to avoid vector resize - int maxCollisionsDetection; - int collisionsCount; - int prev_collision_count; - Vector areasWhereIam; // these parameters are used to avoid vector resize int maxAreasWhereIam; @@ -246,30 +233,8 @@ class RigidBodyBullet : public RigidCollisionObjectBullet { void scratch_space_override_modificator(); virtual void on_collision_filters_change(); - virtual void on_collision_checker_start(); virtual void on_collision_checker_end(); - void set_max_collisions_detection(int p_maxCollisionsDetection) { - - ERR_FAIL_COND(0 > p_maxCollisionsDetection); - - maxCollisionsDetection = p_maxCollisionsDetection; - - collisions.resize(p_maxCollisionsDetection); - collision_traces_1.resize(p_maxCollisionsDetection); - collision_traces_2.resize(p_maxCollisionsDetection); - - collisionsCount = 0; - prev_collision_count = MIN(prev_collision_count, p_maxCollisionsDetection); - } - int get_max_collisions_detection() { - return maxCollisionsDetection; - } - - bool can_add_collision() { return collisionsCount < maxCollisionsDetection; } - bool add_collision_object(RigidBodyBullet *p_otherObject, const Vector3 &p_hitWorldLocation, const Vector3 &p_hitLocalLocation, const Vector3 &p_hitNormal, const float &p_appliedImpulse, int p_other_shape_index, int p_local_shape_index); - bool was_colliding(RigidBodyBullet *p_other_object); - void assert_no_constraints(); void set_activation_state(bool p_active); diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp index f15bcec914b8..d193a0f3b419 100644 --- a/modules/bullet/shape_bullet.cpp +++ b/modules/bullet/shape_bullet.cpp @@ -40,7 +40,6 @@ #include #include #include -#include /** @author AndreaCatania diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index 738b415d162f..4ed37f25e993 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -33,7 +33,6 @@ #include "bullet_physics_server.h" #include "bullet_types_converter.h" #include "bullet_utilities.h" -#include "constraint_bullet.h" #include "core/project_settings.h" #include "core/ustring.h" #include "godot_collision_configuration.h" @@ -47,6 +46,13 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -331,9 +337,11 @@ Vector3 BulletPhysicsDirectSpaceState::get_closest_point_to_object_volume(RID p_ } SpaceBullet::SpaceBullet() : + world_type(-1), broadphase(NULL), collisionConfiguration(NULL), dispatcher(NULL), + mlcp_solver_interfance(NULL), solver(NULL), dynamicsWorld(NULL), soft_body_world_info(NULL), @@ -344,7 +352,9 @@ SpaceBullet::SpaceBullet() : contactDebugCount(0), delta_time(0.) { - create_empty_world(GLOBAL_DEF("physics/3d/active_soft_world", true)); + create_empty_world( + GLOBAL_DEF("physics/3d/world_type", 1), + GLOBAL_DEF("physics/3d/multibody_constraint_solver", 0)); direct_access = memnew(BulletPhysicsDirectSpaceState(this)); } @@ -469,7 +479,7 @@ void SpaceBullet::add_rigid_body(RigidBodyBullet *p_body) { dynamicsWorld->addCollisionObject(p_body->get_bt_rigid_body(), p_body->get_collision_layer(), p_body->get_collision_mask()); } else { dynamicsWorld->addRigidBody(p_body->get_bt_rigid_body(), p_body->get_collision_layer(), p_body->get_collision_mask()); - p_body->scratch_space_override_modificator(); + p_body->reload_space_override_modificator(); // Update gravity here to use rigid body custom gravity } } @@ -487,6 +497,109 @@ void SpaceBullet::reload_collision_filters(RigidBodyBullet *p_body) { add_rigid_body(p_body); } +void SpaceBullet::add_armature(ArmatureBullet *p_body) { + if (is_using_multibody_world()) { + + static_cast(dynamicsWorld)->addMultiBody(p_body->get_bt_body(), + // Not used + 0, 0); + } else { + + ERR_PRINT("This multi body can't be added to non multi body world"); + } +} + +void SpaceBullet::remove_armature(ArmatureBullet *p_body) { + if (is_using_multibody_world()) { + + static_cast(dynamicsWorld)->removeMultiBody(p_body->get_bt_body()); + } else { + + ERR_PRINT("This multi body can't be removed from non multi body world"); + } +} + +void SpaceBullet::reload_collision_filters(ArmatureBullet *p_body) { + remove_armature(p_body); + add_armature(p_body); +} + +void SpaceBullet::add_bone(BoneBullet *p_body) { + if (is_using_multibody_world()) { + + if (p_body->get_armature()->is_active()) { + dynamicsWorld->addCollisionObject( + p_body->get_bt_body(), + p_body->get_collision_layer(), + p_body->get_collision_mask()); + } else { + dynamicsWorld->addCollisionObject( + p_body->get_bt_body(), + 0, + 0); + } + + } else { + + ERR_PRINT("This multi body can't be added to non multi body world"); + } +} + +void SpaceBullet::remove_bone(BoneBullet *p_body) { + if (is_using_multibody_world()) { + + dynamicsWorld->removeCollisionObject(p_body->get_bt_body()); + } else { + + ERR_PRINT("This multi body can't be removed from non multi body world"); + } +} + +void SpaceBullet::reload_collision_filters(BoneBullet *p_body) { + remove_bone(p_body); + add_bone(p_body); +} + +void SpaceBullet::add_bone_joint_limit(BoneBullet *p_body) { + if (is_using_multibody_world()) { + + static_cast(dynamicsWorld)->addMultiBodyConstraint(p_body->get_bt_joint_limiter()); + } else { + + ERR_PRINT("This joint limiter can't be added to non multi body world"); + } +} + +void SpaceBullet::remove_bone_joint_limit(BoneBullet *p_body) { + if (is_using_multibody_world()) { + + static_cast(dynamicsWorld)->removeMultiBodyConstraint(p_body->get_bt_joint_limiter()); + } else { + + ERR_PRINT("This joint limiter can't be removed from non multi body world"); + } +} + +void SpaceBullet::add_bone_joint_motor(BoneBullet *p_body) { + if (is_using_multibody_world()) { + + static_cast(dynamicsWorld)->addMultiBodyConstraint(p_body->get_bt_joint_motor()); + } else { + + ERR_PRINT("This joint limiter can't be added to non multi body world"); + } +} + +void SpaceBullet::remove_bone_joint_motor(BoneBullet *p_body) { + if (is_using_multibody_world()) { + + static_cast(dynamicsWorld)->removeMultiBodyConstraint(p_body->get_bt_joint_motor()); + } else { + + ERR_PRINT("This joint limiter can't be removed from non multi body world"); + } +} + void SpaceBullet::add_soft_body(SoftBodyBullet *p_body) { if (is_using_soft_world()) { if (p_body->get_bt_soft_body()) { @@ -513,13 +626,43 @@ void SpaceBullet::reload_collision_filters(SoftBodyBullet *p_body) { add_soft_body(p_body); } -void SpaceBullet::add_constraint(ConstraintBullet *p_constraint, bool disableCollisionsBetweenLinkedBodies) { - p_constraint->set_space(this); - dynamicsWorld->addConstraint(p_constraint->get_bt_constraint(), disableCollisionsBetweenLinkedBodies); +void SpaceBullet::add_constraint(JointBullet *p_constraint, bool disableCollisionsBetweenLinkedBodies) { + + if (p_constraint->is_multi_joint()) { + + if (is_using_multibody_world()) { + + static_cast(dynamicsWorld)->addMultiBodyConstraint(p_constraint->get_bt_mb_constraint()); + + } else { + + ERR_PRINT("This constraint can't be added from non multi body world"); + } + } else { + + dynamicsWorld->addConstraint( + p_constraint->get_bt_constraint(), + disableCollisionsBetweenLinkedBodies); + } } -void SpaceBullet::remove_constraint(ConstraintBullet *p_constraint) { - dynamicsWorld->removeConstraint(p_constraint->get_bt_constraint()); +void SpaceBullet::remove_constraint(JointBullet *p_constraint) { + + if (p_constraint->is_multi_joint()) { + + if (is_using_multibody_world()) { + + static_cast(dynamicsWorld)->removeMultiBodyConstraint(p_constraint->get_bt_mb_constraint()); + + } else { + + ERR_PRINT("This constraint can't be removed from non multi body world"); + } + + } else { + + dynamicsWorld->removeConstraint(p_constraint->get_bt_constraint()); + } } int SpaceBullet::get_num_collision_objects() const { @@ -570,33 +713,81 @@ btScalar calculateGodotCombinedFriction(const btCollisionObject *body0, const bt return ABS(MIN(body0->getFriction(), body1->getFriction())); } -void SpaceBullet::create_empty_world(bool p_create_soft_world) { +void SpaceBullet::create_empty_world( + int p_world_type, + int p_multibody_constraint_solver_type) { + + world_type = p_world_type; gjk_epa_pen_solver = bulletnew(btGjkEpaPenetrationDepthSolver); gjk_simplex_solver = bulletnew(btVoronoiSimplexSolver); void *world_mem; - if (p_create_soft_world) { - world_mem = malloc(sizeof(btSoftRigidDynamicsWorld)); - } else { + if (p_world_type == 0) { + world_mem = malloc(sizeof(btDiscreteDynamicsWorld)); - } + collisionConfiguration = bulletnew(GodotCollisionConfiguration(static_cast(world_mem))); + solver = bulletnew(btSequentialImpulseConstraintSolver); - if (p_create_soft_world) { + } else if (p_world_type == 1) { + + world_mem = malloc(sizeof(btSoftRigidDynamicsWorld)); collisionConfiguration = bulletnew(GodotSoftCollisionConfiguration(static_cast(world_mem))); - } else { + solver = bulletnew(btSequentialImpulseConstraintSolver); + + } else if (p_world_type == 2) { + + world_mem = malloc(sizeof(btMultiBodyDynamicsWorld)); collisionConfiguration = bulletnew(GodotCollisionConfiguration(static_cast(world_mem))); + solver = bulletnew(btMultiBodyConstraintSolver); + + switch (p_multibody_constraint_solver_type) { + case 0: + solver = new btMultiBodyConstraintSolver; + break; + case 1: + mlcp_solver_interfance = new btSolveProjectedGaussSeidel(); + solver = new btMultiBodyMLCPConstraintSolver(mlcp_solver_interfance); + break; + case 2: + mlcp_solver_interfance = new btDantzigSolver(); + solver = new btMultiBodyMLCPConstraintSolver(mlcp_solver_interfance); + break; + default: + mlcp_solver_interfance = new btLemkeSolver(); + solver = new btMultiBodyMLCPConstraintSolver(mlcp_solver_interfance); + break; + } + + } else { + CRASH_NOW(); } dispatcher = bulletnew(GodotCollisionDispatcher(collisionConfiguration)); broadphase = bulletnew(btDbvtBroadphase); - solver = bulletnew(btSequentialImpulseConstraintSolver); - if (p_create_soft_world) { + if (p_world_type == 0) { + + dynamicsWorld = new (world_mem) btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration); + dynamicsWorld->getSolverInfo().m_globalCfm = btScalar(1e-6); + + } else if (p_world_type == 1) { + dynamicsWorld = new (world_mem) btSoftRigidDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration); soft_body_world_info = bulletnew(btSoftBodyWorldInfo); + dynamicsWorld->getSolverInfo().m_globalCfm = btScalar(1e-6); + + } else if (p_world_type == 2) { + + dynamicsWorld = new (world_mem) btMultiBodyDynamicsWorld( + dispatcher, + broadphase, + static_cast(solver), + collisionConfiguration); + dynamicsWorld->getSolverInfo().m_globalCfm = btScalar(1e-3); + } else { - dynamicsWorld = new (world_mem) btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration); + CRASH_NOW(); } ghostPairCallback = bulletnew(btGhostPairCallback); @@ -637,6 +828,7 @@ void SpaceBullet::destroy_world() { dynamicsWorld = NULL; bulletdelete(solver); + bulletdelete(mlcp_solver_interfance); bulletdelete(broadphase); bulletdelete(dispatcher); bulletdelete(collisionConfiguration); @@ -693,7 +885,7 @@ void SpaceBullet::check_ghost_overlaps() { if (overlapped_bt_co->getUserIndex() == CollisionObjectBullet::TYPE_AREA) { if (!static_cast(overlapped_bt_co->getUserPointer())->is_monitorable()) continue; - } else if (overlapped_bt_co->getUserIndex() != CollisionObjectBullet::TYPE_RIGID_BODY) + } else if (overlapped_bt_co->getUserIndex() != CollisionObjectBullet::TYPE_RIGID_BODY && overlapped_bt_co->getUserIndex() != CollisionObjectBullet::TYPE_BONE_BODY) continue; // For each area shape @@ -800,56 +992,60 @@ void SpaceBullet::check_body_collision() { // I know this static cast is a bit risky. But I'm checking its type just after it. // This allow me to avoid a lot of other cast and checks - RigidBodyBullet *bodyA = static_cast(contactManifold->getBody0()->getUserPointer()); - RigidBodyBullet *bodyB = static_cast(contactManifold->getBody1()->getUserPointer()); + RigidCollisionObjectBullet *bodyA = static_cast(contactManifold->getBody0()->getUserPointer()); + RigidCollisionObjectBullet *bodyB = static_cast(contactManifold->getBody1()->getUserPointer()); - if (CollisionObjectBullet::TYPE_RIGID_BODY == bodyA->getType() && CollisionObjectBullet::TYPE_RIGID_BODY == bodyB->getType()) { - if (!bodyA->can_add_collision() && !bodyB->can_add_collision()) { - continue; - } + if (CollisionObjectBullet::TYPE_RIGID_BODY != bodyA->getType() && CollisionObjectBullet::TYPE_BONE_BODY != bodyA->getType()) { + continue; + } + if (CollisionObjectBullet::TYPE_RIGID_BODY != bodyB->getType() && CollisionObjectBullet::TYPE_BONE_BODY != bodyB->getType()) { + continue; + } + if (!bodyA->can_add_collision() && !bodyB->can_add_collision()) { + continue; + } - const int numContacts = contactManifold->getNumContacts(); + const int numContacts = contactManifold->getNumContacts(); - /// Since I don't need report all contacts for these objects, - /// So report only the first + /// Since I don't need report all contacts for these objects, + /// So report only the first #define REPORT_ALL_CONTACTS 0 #if REPORT_ALL_CONTACTS - for (int j = 0; j < numContacts; j++) { - btManifoldPoint &pt = contactManifold->getContactPoint(j); + for (int j = 0; j < numContacts; j++) { + btManifoldPoint &pt = contactManifold->getContactPoint(j); #else - if (numContacts) { - btManifoldPoint &pt = contactManifold->getContactPoint(0); + if (numContacts) { + btManifoldPoint &pt = contactManifold->getContactPoint(0); #endif - if ( - pt.getDistance() <= 0.0 || - bodyA->was_colliding(bodyB) || - bodyB->was_colliding(bodyA)) { - - Vector3 collisionWorldPosition; - Vector3 collisionLocalPosition; - Vector3 normalOnB; - float appliedImpulse = pt.m_appliedImpulse; - B_TO_G(pt.m_normalWorldOnB, normalOnB); - - if (bodyA->can_add_collision()) { - B_TO_G(pt.getPositionWorldOnB(), collisionWorldPosition); - /// pt.m_localPointB Doesn't report the exact point in local space - B_TO_G(pt.getPositionWorldOnB() - contactManifold->getBody1()->getWorldTransform().getOrigin(), collisionLocalPosition); - bodyA->add_collision_object(bodyB, collisionWorldPosition, collisionLocalPosition, normalOnB, appliedImpulse, pt.m_index1, pt.m_index0); - } - if (bodyB->can_add_collision()) { - B_TO_G(pt.getPositionWorldOnA(), collisionWorldPosition); - /// pt.m_localPointA Doesn't report the exact point in local space - B_TO_G(pt.getPositionWorldOnA() - contactManifold->getBody0()->getWorldTransform().getOrigin(), collisionLocalPosition); - bodyB->add_collision_object(bodyA, collisionWorldPosition, collisionLocalPosition, normalOnB * -1, appliedImpulse * -1, pt.m_index0, pt.m_index1); - } + if ( + pt.getDistance() <= 0.0 || + bodyA->was_colliding(bodyB) || + bodyB->was_colliding(bodyA)) { + + Vector3 collisionWorldPosition; + Vector3 collisionLocalPosition; + Vector3 normalOnB; + float appliedImpulse = pt.m_appliedImpulse; + B_TO_G(pt.m_normalWorldOnB, normalOnB); + + if (bodyA->can_add_collision()) { + B_TO_G(pt.getPositionWorldOnB(), collisionWorldPosition); + /// pt.m_localPointB Doesn't report the exact point in local space + B_TO_G(pt.getPositionWorldOnB() - contactManifold->getBody1()->getWorldTransform().getOrigin(), collisionLocalPosition); + bodyA->add_collision_object(bodyB, collisionWorldPosition, collisionLocalPosition, normalOnB, appliedImpulse, pt.m_index1, pt.m_index0); + } + if (bodyB->can_add_collision()) { + B_TO_G(pt.getPositionWorldOnA(), collisionWorldPosition); + /// pt.m_localPointA Doesn't report the exact point in local space + B_TO_G(pt.getPositionWorldOnA() - contactManifold->getBody0()->getWorldTransform().getOrigin(), collisionLocalPosition); + bodyB->add_collision_object(bodyA, collisionWorldPosition, collisionLocalPosition, normalOnB * -1, appliedImpulse * -1, pt.m_index0, pt.m_index1); + } #ifdef DEBUG_ENABLED - if (is_debugging_contacts()) { - add_debug_contact(collisionWorldPosition); - } -#endif + if (is_debugging_contacts()) { + add_debug_contact(collisionWorldPosition); } +#endif } } } @@ -858,8 +1054,7 @@ void SpaceBullet::check_body_collision() { void SpaceBullet::update_gravity() { btVector3 btGravity; G_TO_B(gravityDirection * gravityMagnitude, btGravity); - //dynamicsWorld->setGravity(btGravity); - dynamicsWorld->setGravity(btVector3(0, 0, 0)); + dynamicsWorld->setGravity(btGravity); if (soft_body_world_info) { soft_body_world_info->m_gravity = btGravity; } diff --git a/modules/bullet/space_bullet.h b/modules/bullet/space_bullet.h index eb4a065e54c9..a1b21cb62a8f 100644 --- a/modules/bullet/space_bullet.h +++ b/modules/bullet/space_bullet.h @@ -50,6 +50,7 @@ class AreaBullet; class btBroadphaseInterface; class btCollisionDispatcher; +class btMLCPSolverInterface; class btConstraintSolver; class btDefaultCollisionConfiguration; class btDynamicsWorld; @@ -58,10 +59,12 @@ class btEmptyShape; class btGhostPairCallback; class btSoftRigidDynamicsWorld; struct btSoftBodyWorldInfo; -class ConstraintBullet; +class JointBullet; class CollisionObjectBullet; class RigidBodyBullet; class SpaceBullet; +class ArmatureBullet; +class BoneBullet; class SoftBodyBullet; class btGjkEpaPenetrationDepthSolver; @@ -92,9 +95,12 @@ class SpaceBullet : public RIDBullet { friend void onBulletTickCallback(btDynamicsWorld *world, btScalar timeStep); friend class BulletPhysicsDirectSpaceState; + int world_type; + btBroadphaseInterface *broadphase; btDefaultCollisionConfiguration *collisionConfiguration; btCollisionDispatcher *dispatcher; + btMLCPSolverInterface *mlcp_solver_interfance; btConstraintSolver *solver; btDiscreteDynamicsWorld *dynamicsWorld; btSoftBodyWorldInfo *soft_body_world_info; @@ -125,7 +131,8 @@ class SpaceBullet : public RIDBullet { _FORCE_INLINE_ btBroadphaseInterface *get_broadphase() { return broadphase; } _FORCE_INLINE_ btCollisionDispatcher *get_dispatcher() { return dispatcher; } _FORCE_INLINE_ btSoftBodyWorldInfo *get_soft_body_world_info() { return soft_body_world_info; } - _FORCE_INLINE_ bool is_using_soft_world() { return soft_body_world_info; } + _FORCE_INLINE_ bool is_using_soft_world() { return world_type == 1; } + _FORCE_INLINE_ bool is_using_multibody_world() { return world_type == 2; } /// Used to set some parameters to Bullet world /// @param p_param: @@ -149,12 +156,26 @@ class SpaceBullet : public RIDBullet { void remove_rigid_body(RigidBodyBullet *p_body); void reload_collision_filters(RigidBodyBullet *p_body); + void add_armature(ArmatureBullet *p_body); + void remove_armature(ArmatureBullet *p_body); + void reload_collision_filters(ArmatureBullet *p_body); + + void add_bone(BoneBullet *p_body); + void remove_bone(BoneBullet *p_body); + void reload_collision_filters(BoneBullet *p_body); + + void add_bone_joint_limit(BoneBullet *p_body); + void remove_bone_joint_limit(BoneBullet *p_body); + + void add_bone_joint_motor(BoneBullet *p_body); + void remove_bone_joint_motor(BoneBullet *p_body); + void add_soft_body(SoftBodyBullet *p_body); void remove_soft_body(SoftBodyBullet *p_body); void reload_collision_filters(SoftBodyBullet *p_body); - void add_constraint(ConstraintBullet *p_constraint, bool disableCollisionsBetweenLinkedBodies = false); - void remove_constraint(ConstraintBullet *p_constraint); + void add_constraint(JointBullet *p_constraint, bool disableCollisionsBetweenLinkedBodies = false); + void remove_constraint(JointBullet *p_constraint); int get_num_collision_objects() const; void remove_all_collision_objects(); @@ -181,7 +202,16 @@ class SpaceBullet : public RIDBullet { int test_ray_separation(RigidBodyBullet *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer::SeparationResult *r_results, int p_result_max, float p_margin); private: - void create_empty_world(bool p_create_soft_world); + /** + * @brief create_empty_world + * @param p_world_type 0 plain, 1 Soft, 2 Multi body + * @param p_multibody_constraint_solver_type + * 0 btMultiBodyConstraintSolver + * 1 btSolveProjectedGaussSeidel + * 2 btDantzigSolver + * D btLemkeSolver + */ + void create_empty_world(int p_world_type, int p_multibody_constraint_solver_type); void destroy_world(); void check_ghost_overlaps(); void check_body_collision(); diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp index 4247266e3d45..b1b9a5dc337d 100644 --- a/scene/3d/area.cpp +++ b/scene/3d/area.cpp @@ -494,56 +494,6 @@ bool Area::overlaps_body(Node *p_body) const { return false; return E->get().in_tree; } -void Area::set_collision_mask(uint32_t p_mask) { - - collision_mask = p_mask; - PhysicsServer::get_singleton()->area_set_collision_mask(get_rid(), p_mask); -} - -uint32_t Area::get_collision_mask() const { - - return collision_mask; -} -void Area::set_collision_layer(uint32_t p_layer) { - - collision_layer = p_layer; - PhysicsServer::get_singleton()->area_set_collision_layer(get_rid(), p_layer); -} - -uint32_t Area::get_collision_layer() const { - - return collision_layer; -} - -void Area::set_collision_mask_bit(int p_bit, bool p_value) { - - uint32_t mask = get_collision_mask(); - if (p_value) - mask |= 1 << p_bit; - else - mask &= ~(1 << p_bit); - set_collision_mask(mask); -} - -bool Area::get_collision_mask_bit(int p_bit) const { - - return get_collision_mask() & (1 << p_bit); -} - -void Area::set_collision_layer_bit(int p_bit, bool p_value) { - - uint32_t layer = get_collision_layer(); - if (p_value) - layer |= 1 << p_bit; - else - layer &= ~(1 << p_bit); - set_collision_layer(layer); -} - -bool Area::get_collision_layer_bit(int p_bit) const { - - return get_collision_layer() & (1 << p_bit); -} void Area::set_audio_bus_override(bool p_override) { @@ -658,18 +608,6 @@ void Area::_bind_methods() { ClassDB::bind_method(D_METHOD("set_priority", "priority"), &Area::set_priority); ClassDB::bind_method(D_METHOD("get_priority"), &Area::get_priority); - ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &Area::set_collision_mask); - ClassDB::bind_method(D_METHOD("get_collision_mask"), &Area::get_collision_mask); - - ClassDB::bind_method(D_METHOD("set_collision_layer", "collision_layer"), &Area::set_collision_layer); - ClassDB::bind_method(D_METHOD("get_collision_layer"), &Area::get_collision_layer); - - ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &Area::set_collision_mask_bit); - ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &Area::get_collision_mask_bit); - - ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &Area::set_collision_layer_bit); - ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &Area::get_collision_layer_bit); - ClassDB::bind_method(D_METHOD("set_monitorable", "enable"), &Area::set_monitorable); ClassDB::bind_method(D_METHOD("is_monitorable"), &Area::is_monitorable); @@ -723,9 +661,6 @@ void Area::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "priority", PROPERTY_HINT_RANGE, "0,128,1"), "set_priority", "get_priority"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "monitoring"), "set_monitoring", "is_monitoring"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "monitorable"), "set_monitorable", "is_monitorable"); - ADD_GROUP("Collision", "collision_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); ADD_GROUP("Audio Bus", "audio_bus_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_bus_override"), "set_audio_bus_override", "is_overriding_audio_bus"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "audio_bus_name", PROPERTY_HINT_ENUM, ""), "set_audio_bus", "get_audio_bus"); @@ -743,7 +678,7 @@ void Area::_bind_methods() { } Area::Area() : - CollisionObject(PhysicsServer::get_singleton()->area_create(), true) { + CollisionObject(PhysicsServer::get_singleton()->area_create(), COLLISION_OBJECT_TYPE_AREA) { space_override = SPACE_OVERRIDE_DISABLED; set_gravity(9.8); @@ -756,8 +691,6 @@ Area::Area() : priority = 0; monitoring = false; monitorable = false; - collision_mask = 1; - collision_layer = 1; set_monitoring(true); set_monitorable(true); diff --git a/scene/3d/area.h b/scene/3d/area.h index 043d651e04e8..6804f2dd0080 100644 --- a/scene/3d/area.h +++ b/scene/3d/area.h @@ -55,8 +55,6 @@ class Area : public CollisionObject { real_t gravity_distance_scale; real_t angular_damp; real_t linear_damp; - uint32_t collision_mask; - uint32_t collision_layer; int priority; bool monitoring; bool monitorable; @@ -172,18 +170,6 @@ class Area : public CollisionObject { void set_monitorable(bool p_enable); bool is_monitorable() const; - void set_collision_mask(uint32_t p_mask); - uint32_t get_collision_mask() const; - - void set_collision_layer(uint32_t p_layer); - uint32_t get_collision_layer() const; - - void set_collision_mask_bit(int p_bit, bool p_value); - bool get_collision_mask_bit(int p_bit) const; - - void set_collision_layer_bit(int p_bit, bool p_value); - bool get_collision_layer_bit(int p_bit) const; - Array get_overlapping_bodies() const; Array get_overlapping_areas() const; //function for script diff --git a/scene/3d/collision_object.cpp b/scene/3d/collision_object.cpp index fc46cf5bdb6e..3412c0b6dcda 100644 --- a/scene/3d/collision_object.cpp +++ b/scene/3d/collision_object.cpp @@ -39,27 +39,36 @@ void CollisionObject::_notification(int p_what) { case NOTIFICATION_ENTER_WORLD: { - if (area) - PhysicsServer::get_singleton()->area_set_transform(rid, get_global_transform()); - else - PhysicsServer::get_singleton()->body_set_state(rid, PhysicsServer::BODY_STATE_TRANSFORM, get_global_transform()); - RID space = get_world()->get_space(); - if (area) { - PhysicsServer::get_singleton()->area_set_space(rid, space); - } else - PhysicsServer::get_singleton()->body_set_space(rid, space); + switch (type) { + case COLLISION_OBJECT_TYPE_AREA: + PhysicsServer::get_singleton()->area_set_transform(rid, get_global_transform()); + PhysicsServer::get_singleton()->area_set_space(rid, space); + break; + case COLLISION_OBJECT_TYPE_BODY: + PhysicsServer::get_singleton()->body_set_state(rid, PhysicsServer::BODY_STATE_TRANSFORM, get_global_transform()); + PhysicsServer::get_singleton()->body_set_space(rid, space); + break; + case COLLISION_OBJECT_TYPE_BONE: + PhysicsServer::get_singleton()->bone_set_transform(rid, get_global_transform()); + break; + } _update_pickable(); - //get space } break; - case NOTIFICATION_TRANSFORM_CHANGED: { - if (area) - PhysicsServer::get_singleton()->area_set_transform(rid, get_global_transform()); - else - PhysicsServer::get_singleton()->body_set_state(rid, PhysicsServer::BODY_STATE_TRANSFORM, get_global_transform()); + switch (type) { + case COLLISION_OBJECT_TYPE_AREA: + PhysicsServer::get_singleton()->area_set_transform(rid, get_global_transform()); + break; + case COLLISION_OBJECT_TYPE_BODY: + PhysicsServer::get_singleton()->body_set_state(rid, PhysicsServer::BODY_STATE_TRANSFORM, get_global_transform()); + break; + case COLLISION_OBJECT_TYPE_BONE: + PhysicsServer::get_singleton()->bone_set_transform(rid, get_global_transform()); + break; + } } break; case NOTIFICATION_VISIBILITY_CHANGED: { @@ -69,10 +78,17 @@ void CollisionObject::_notification(int p_what) { } break; case NOTIFICATION_EXIT_WORLD: { - if (area) { - PhysicsServer::get_singleton()->area_set_space(rid, RID()); - } else - PhysicsServer::get_singleton()->body_set_space(rid, RID()); + switch (type) { + case COLLISION_OBJECT_TYPE_AREA: + PhysicsServer::get_singleton()->area_set_space(rid, RID()); + break; + case COLLISION_OBJECT_TYPE_BODY: + PhysicsServer::get_singleton()->body_set_space(rid, RID()); + break; + case COLLISION_OBJECT_TYPE_BONE: + + break; + } } break; } @@ -106,10 +122,18 @@ void CollisionObject::_update_pickable() { if (!is_inside_tree()) return; bool pickable = ray_pickable && is_inside_tree() && is_visible_in_tree(); - if (area) - PhysicsServer::get_singleton()->area_set_ray_pickable(rid, pickable); - else - PhysicsServer::get_singleton()->body_set_ray_pickable(rid, pickable); + + switch (type) { + case COLLISION_OBJECT_TYPE_AREA: + PhysicsServer::get_singleton()->area_set_ray_pickable(rid, pickable); + break; + case COLLISION_OBJECT_TYPE_BODY: + PhysicsServer::get_singleton()->body_set_ray_pickable(rid, pickable); + break; + case COLLISION_OBJECT_TYPE_BONE: + + break; + } } void CollisionObject::set_ray_pickable(bool p_ray_pickable) { @@ -146,6 +170,21 @@ void CollisionObject::_bind_methods() { ClassDB::bind_method(D_METHOD("shape_owner_clear_shapes", "owner_id"), &CollisionObject::shape_owner_clear_shapes); ClassDB::bind_method(D_METHOD("shape_find_owner", "shape_index"), &CollisionObject::shape_find_owner); + ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &CollisionObject::set_collision_layer); + ClassDB::bind_method(D_METHOD("get_collision_layer"), &CollisionObject::get_collision_layer); + + ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &CollisionObject::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &CollisionObject::get_collision_mask); + + ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &CollisionObject::set_collision_mask_bit); + ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &CollisionObject::get_collision_mask_bit); + + ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &CollisionObject::set_collision_layer_bit); + ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &CollisionObject::get_collision_layer_bit); + + ClassDB::bind_method(D_METHOD("_set_layers", "mask"), &CollisionObject::_set_layers); + ClassDB::bind_method(D_METHOD("_get_layers"), &CollisionObject::_get_layers); + BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx"))); ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx"))); @@ -154,6 +193,10 @@ void CollisionObject::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "input_ray_pickable"), "set_ray_pickable", "is_ray_pickable"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "input_capture_on_drag"), "set_capture_input_on_drag", "get_capture_input_on_drag"); + + ADD_GROUP("Collision", "collision_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); } uint32_t CollisionObject::create_shape_owner(Object *p_owner) { @@ -188,12 +231,23 @@ void CollisionObject::shape_owner_set_disabled(uint32_t p_owner, bool p_disabled ShapeData &sd = shapes[p_owner]; sd.disabled = p_disabled; - for (int i = 0; i < sd.shapes.size(); i++) { - if (area) { - PhysicsServer::get_singleton()->area_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); - } else { - PhysicsServer::get_singleton()->body_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); - } + + switch (type) { + case COLLISION_OBJECT_TYPE_AREA: + for (int i = 0; i < sd.shapes.size(); i++) { + PhysicsServer::get_singleton()->area_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); + } + break; + case COLLISION_OBJECT_TYPE_BODY: + for (int i = 0; i < sd.shapes.size(); i++) { + PhysicsServer::get_singleton()->body_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); + } + break; + case COLLISION_OBJECT_TYPE_BONE: + for (int i = 0; i < sd.shapes.size(); i++) { + PhysicsServer::get_singleton()->bone_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); + } + break; } } @@ -227,12 +281,23 @@ void CollisionObject::shape_owner_set_transform(uint32_t p_owner, const Transfor ShapeData &sd = shapes[p_owner]; sd.xform = p_transform; - for (int i = 0; i < sd.shapes.size(); i++) { - if (area) { - PhysicsServer::get_singleton()->area_set_shape_transform(rid, sd.shapes[i].index, p_transform); - } else { - PhysicsServer::get_singleton()->body_set_shape_transform(rid, sd.shapes[i].index, p_transform); - } + + switch (type) { + case COLLISION_OBJECT_TYPE_AREA: + for (int i = 0; i < sd.shapes.size(); i++) { + PhysicsServer::get_singleton()->area_set_shape_transform(rid, sd.shapes[i].index, p_transform); + } + break; + case COLLISION_OBJECT_TYPE_BODY: + for (int i = 0; i < sd.shapes.size(); i++) { + PhysicsServer::get_singleton()->body_set_shape_transform(rid, sd.shapes[i].index, p_transform); + } + break; + case COLLISION_OBJECT_TYPE_BONE: + for (int i = 0; i < sd.shapes.size(); i++) { + PhysicsServer::get_singleton()->bone_set_shape_transform(rid, sd.shapes[i].index, p_transform); + } + break; } } Transform CollisionObject::shape_owner_get_transform(uint32_t p_owner) const { @@ -258,11 +323,19 @@ void CollisionObject::shape_owner_add_shape(uint32_t p_owner, const Ref & ShapeData::ShapeBase s; s.index = total_subshapes; s.shape = p_shape; - if (area) { - PhysicsServer::get_singleton()->area_add_shape(rid, p_shape->get_rid(), sd.xform, sd.disabled); - } else { - PhysicsServer::get_singleton()->body_add_shape(rid, p_shape->get_rid(), sd.xform, sd.disabled); + + switch (type) { + case COLLISION_OBJECT_TYPE_AREA: + PhysicsServer::get_singleton()->area_add_shape(rid, p_shape->get_rid(), sd.xform, sd.disabled); + break; + case COLLISION_OBJECT_TYPE_BODY: + PhysicsServer::get_singleton()->body_add_shape(rid, p_shape->get_rid(), sd.xform, sd.disabled); + break; + case COLLISION_OBJECT_TYPE_BONE: + PhysicsServer::get_singleton()->bone_add_shape(rid, p_shape->get_rid(), sd.xform, sd.disabled); + break; } + sd.shapes.push_back(s); total_subshapes++; @@ -294,10 +367,16 @@ void CollisionObject::shape_owner_remove_shape(uint32_t p_owner, int p_shape) { ERR_FAIL_INDEX(p_shape, shapes[p_owner].shapes.size()); int index_to_remove = shapes[p_owner].shapes[p_shape].index; - if (area) { - PhysicsServer::get_singleton()->area_remove_shape(rid, index_to_remove); - } else { - PhysicsServer::get_singleton()->body_remove_shape(rid, index_to_remove); + switch (type) { + case COLLISION_OBJECT_TYPE_AREA: + PhysicsServer::get_singleton()->area_remove_shape(rid, index_to_remove); + break; + case COLLISION_OBJECT_TYPE_BODY: + PhysicsServer::get_singleton()->body_remove_shape(rid, index_to_remove); + break; + case COLLISION_OBJECT_TYPE_BONE: + PhysicsServer::get_singleton()->bone_remove_shape(rid, index_to_remove); + break; } shapes[p_owner].shapes.remove(p_shape); @@ -338,19 +417,177 @@ uint32_t CollisionObject::shape_find_owner(int p_shape_index) const { return 0; } -CollisionObject::CollisionObject(RID p_rid, bool p_area) { +void CollisionObject::set_collision_layer(uint32_t p_layer) { + + collision_layer = p_layer; + switch (type) { + case COLLISION_OBJECT_TYPE_AREA: + PhysicsServer::get_singleton()->area_set_collision_layer(get_rid(), collision_layer); + break; + case COLLISION_OBJECT_TYPE_BODY: + PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), collision_layer); + break; + case COLLISION_OBJECT_TYPE_BONE: + PhysicsServer::get_singleton()->bone_set_collision_layer(get_rid(), collision_layer); + break; + } +} + +uint32_t CollisionObject::get_collision_layer() const { + + return collision_layer; +} + +void CollisionObject::set_collision_mask(uint32_t p_mask) { + + collision_mask = p_mask; + switch (type) { + case COLLISION_OBJECT_TYPE_AREA: + PhysicsServer::get_singleton()->area_set_collision_mask(get_rid(), collision_mask); + break; + case COLLISION_OBJECT_TYPE_BODY: + PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), collision_mask); + break; + case COLLISION_OBJECT_TYPE_BONE: + PhysicsServer::get_singleton()->bone_set_collision_mask(get_rid(), collision_mask); + break; + } +} + +uint32_t CollisionObject::get_collision_mask() const { + + return collision_mask; +} + +void CollisionObject::set_collision_mask_bit(int p_bit, bool p_value) { + + uint32_t mask = get_collision_mask(); + if (p_value) + mask |= 1 << p_bit; + else + mask &= ~(1 << p_bit); + set_collision_mask(mask); +} + +bool CollisionObject::get_collision_mask_bit(int p_bit) const { + + return get_collision_mask() & (1 << p_bit); +} + +void CollisionObject::set_collision_layer_bit(int p_bit, bool p_value) { + + uint32_t mask = get_collision_layer(); + if (p_value) + mask |= 1 << p_bit; + else + mask &= ~(1 << p_bit); + set_collision_layer(mask); +} + +bool CollisionObject::get_collision_layer_bit(int p_bit) const { + + return get_collision_layer() & (1 << p_bit); +} + +Array CollisionObject::get_collision_exceptions() { + List exceptions; + + switch (type) { + case COLLISION_OBJECT_TYPE_AREA: + break; + case COLLISION_OBJECT_TYPE_BODY: + PhysicsServer::get_singleton()->body_get_collision_exceptions(get_rid(), &exceptions); + break; + case COLLISION_OBJECT_TYPE_BONE: + PhysicsServer::get_singleton()->bone_get_collision_exceptions(get_rid(), &exceptions); + break; + } + + Array ret; + for (List::Element *E = exceptions.front(); E; E = E->next()) { + RID body = E->get(); + ObjectID instance_id = PhysicsServer::get_singleton()->body_get_object_instance_id(body); + Object *obj = ObjectDB::get_instance(instance_id); + CollisionObject *physics_body = Object::cast_to(obj); + ret.append(physics_body); + } + return ret; +} + +void CollisionObject::add_collision_exception_with(Node *p_node) { + + ERR_FAIL_NULL(p_node); + CollisionObject *collision_object = Object::cast_to(p_node); + if (!collision_object) { + ERR_EXPLAIN("Collision exception only works between two CollisionObject"); + } + ERR_FAIL_COND(!collision_object); + + switch (type) { + case COLLISION_OBJECT_TYPE_AREA: + break; + case COLLISION_OBJECT_TYPE_BODY: + PhysicsServer::get_singleton()->body_add_collision_exception(get_rid(), collision_object->get_rid()); + break; + case COLLISION_OBJECT_TYPE_BONE: + PhysicsServer::get_singleton()->bone_add_collision_exception(get_rid(), collision_object->get_rid()); + break; + } +} + +void CollisionObject::remove_collision_exception_with(Node *p_node) { + + ERR_FAIL_NULL(p_node); + CollisionObject *collision_object = Object::cast_to(p_node); + if (!collision_object) { + ERR_EXPLAIN("Collision exception only works between two CollisionObject"); + } + ERR_FAIL_COND(!collision_object); + + switch (type) { + case COLLISION_OBJECT_TYPE_AREA: + break; + case COLLISION_OBJECT_TYPE_BODY: + PhysicsServer::get_singleton()->body_remove_collision_exception(get_rid(), collision_object->get_rid()); + break; + case COLLISION_OBJECT_TYPE_BONE: + PhysicsServer::get_singleton()->bone_remove_collision_exception(get_rid(), collision_object->get_rid()); + break; + } +} + +void CollisionObject::_set_layers(uint32_t p_mask) { + set_collision_layer(p_mask); + set_collision_mask(p_mask); +} + +uint32_t CollisionObject::_get_layers() const { + + return get_collision_layer(); +} + +CollisionObject::CollisionObject(RID p_rid, CollisionObjectType p_type) { rid = p_rid; - area = p_area; + type = p_type; capture_input_on_drag = false; ray_pickable = true; set_notify_transform(true); total_subshapes = 0; - if (p_area) { - PhysicsServer::get_singleton()->area_attach_object_instance_id(rid, get_instance_id()); - } else { - PhysicsServer::get_singleton()->body_attach_object_instance_id(rid, get_instance_id()); + collision_layer = 1; + collision_mask = 1; + + switch (p_type) { + case COLLISION_OBJECT_TYPE_AREA: + PhysicsServer::get_singleton()->area_attach_object_instance_id(rid, get_instance_id()); + break; + case COLLISION_OBJECT_TYPE_BODY: + PhysicsServer::get_singleton()->body_attach_object_instance_id(rid, get_instance_id()); + break; + case COLLISION_OBJECT_TYPE_BONE: + PhysicsServer::get_singleton()->bone_attach_object_instance_id(rid, get_instance_id()); + break; } //set_transform_notify(true); } diff --git a/scene/3d/collision_object.h b/scene/3d/collision_object.h index 90f370b6d44f..dbfc4889b882 100644 --- a/scene/3d/collision_object.h +++ b/scene/3d/collision_object.h @@ -38,7 +38,15 @@ class CollisionObject : public Spatial { GDCLASS(CollisionObject, Spatial); - bool area; +public: + enum CollisionObjectType { + COLLISION_OBJECT_TYPE_AREA, + COLLISION_OBJECT_TYPE_BODY, + COLLISION_OBJECT_TYPE_BONE, + }; + +private: + CollisionObjectType type; RID rid; @@ -64,13 +72,19 @@ class CollisionObject : public Spatial { Map shapes; + uint32_t collision_layer; + uint32_t collision_mask; + + void _set_layers(uint32_t p_mask); + uint32_t _get_layers() const; + bool capture_input_on_drag; bool ray_pickable; void _update_pickable(); protected: - CollisionObject(RID p_rid, bool p_area); + CollisionObject(RID p_rid, CollisionObjectType p_type); void _notification(int p_what); static void _bind_methods(); @@ -102,6 +116,22 @@ class CollisionObject : public Spatial { uint32_t shape_find_owner(int p_shape_index) const; + void set_collision_layer(uint32_t p_layer); + uint32_t get_collision_layer() const; + + void set_collision_mask(uint32_t p_mask); + uint32_t get_collision_mask() const; + + void set_collision_layer_bit(int p_bit, bool p_value); + bool get_collision_layer_bit(int p_bit) const; + + void set_collision_mask_bit(int p_bit, bool p_value); + bool get_collision_mask_bit(int p_bit) const; + + Array get_collision_exceptions(); + void add_collision_exception_with(Node *p_node); // Must be collision object + void remove_collision_exception_with(Node *p_node); + void set_ray_pickable(bool p_ray_pickable); bool is_ray_pickable() const; diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index d3aad7000ddd..82622e3c5bc7 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -59,130 +59,11 @@ float PhysicsBody::get_inverse_mass() const { return 0; } -void PhysicsBody::set_collision_layer(uint32_t p_layer) { - - collision_layer = p_layer; - PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), p_layer); -} - -uint32_t PhysicsBody::get_collision_layer() const { - - return collision_layer; -} - -void PhysicsBody::set_collision_mask(uint32_t p_mask) { - - collision_mask = p_mask; - PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), p_mask); -} - -uint32_t PhysicsBody::get_collision_mask() const { - - return collision_mask; -} - -void PhysicsBody::set_collision_mask_bit(int p_bit, bool p_value) { - - uint32_t mask = get_collision_mask(); - if (p_value) - mask |= 1 << p_bit; - else - mask &= ~(1 << p_bit); - set_collision_mask(mask); -} - -bool PhysicsBody::get_collision_mask_bit(int p_bit) const { - - return get_collision_mask() & (1 << p_bit); -} - -void PhysicsBody::set_collision_layer_bit(int p_bit, bool p_value) { - - uint32_t mask = get_collision_layer(); - if (p_value) - mask |= 1 << p_bit; - else - mask &= ~(1 << p_bit); - set_collision_layer(mask); -} - -bool PhysicsBody::get_collision_layer_bit(int p_bit) const { - - return get_collision_layer() & (1 << p_bit); -} - -Array PhysicsBody::get_collision_exceptions() { - List exceptions; - PhysicsServer::get_singleton()->body_get_collision_exceptions(get_rid(), &exceptions); - Array ret; - for (List::Element *E = exceptions.front(); E; E = E->next()) { - RID body = E->get(); - ObjectID instance_id = PhysicsServer::get_singleton()->body_get_object_instance_id(body); - Object *obj = ObjectDB::get_instance(instance_id); - PhysicsBody *physics_body = Object::cast_to(obj); - ret.append(physics_body); - } - return ret; -} - -void PhysicsBody::add_collision_exception_with(Node *p_node) { - - ERR_FAIL_NULL(p_node); - CollisionObject *collision_object = Object::cast_to(p_node); - if (!collision_object) { - ERR_EXPLAIN("Collision exception only works between two CollisionObject"); - } - ERR_FAIL_COND(!collision_object); - PhysicsServer::get_singleton()->body_add_collision_exception(get_rid(), collision_object->get_rid()); -} - -void PhysicsBody::remove_collision_exception_with(Node *p_node) { - - ERR_FAIL_NULL(p_node); - CollisionObject *collision_object = Object::cast_to(p_node); - if (!collision_object) { - ERR_EXPLAIN("Collision exception only works between two CollisionObject"); - } - ERR_FAIL_COND(!collision_object); - PhysicsServer::get_singleton()->body_remove_collision_exception(get_rid(), collision_object->get_rid()); -} - -void PhysicsBody::_set_layers(uint32_t p_mask) { - set_collision_layer(p_mask); - set_collision_mask(p_mask); -} - -uint32_t PhysicsBody::_get_layers() const { - - return get_collision_layer(); -} - void PhysicsBody::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &PhysicsBody::set_collision_layer); - ClassDB::bind_method(D_METHOD("get_collision_layer"), &PhysicsBody::get_collision_layer); - - ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &PhysicsBody::set_collision_mask); - ClassDB::bind_method(D_METHOD("get_collision_mask"), &PhysicsBody::get_collision_mask); - - ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &PhysicsBody::set_collision_mask_bit); - ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &PhysicsBody::get_collision_mask_bit); - - ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &PhysicsBody::set_collision_layer_bit); - ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &PhysicsBody::get_collision_layer_bit); - - ClassDB::bind_method(D_METHOD("_set_layers", "mask"), &PhysicsBody::_set_layers); - ClassDB::bind_method(D_METHOD("_get_layers"), &PhysicsBody::_get_layers); - - ADD_GROUP("Collision", "collision_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); } PhysicsBody::PhysicsBody(PhysicsServer::BodyMode p_mode) : - CollisionObject(PhysicsServer::get_singleton()->body_create(p_mode), false) { - - collision_layer = 1; - collision_mask = 1; + CollisionObject(PhysicsServer::get_singleton()->body_create(p_mode), COLLISION_OBJECT_TYPE_BODY) { } #ifndef DISABLE_DEPRECATED @@ -1549,100 +1430,66 @@ KinematicCollision::KinematicCollision() { /////////////////////////////////////// -bool PhysicalBone::JointData::_set(const StringName &p_name, const Variant &p_value, RID j) { +bool PhysicalBone::JointData::_set(const StringName &p_name, const Variant &p_value) { + return false; } bool PhysicalBone::JointData::_get(const StringName &p_name, Variant &r_ret) const { + return false; } void PhysicalBone::JointData::_get_property_list(List *p_list) const { } -bool PhysicalBone::PinJointData::_set(const StringName &p_name, const Variant &p_value, RID j) { - if (JointData::_set(p_name, p_value, j)) { +bool PhysicalBone::FixedJointData::_set(const StringName &p_name, const Variant &p_value) { + if (JointData::_set(p_name, p_value)) { return true; } - if ("joint_constraints/bias" == p_name) { - bias = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->pin_joint_set_param(j, PhysicsServer::PIN_JOINT_BIAS, bias); - - } else if ("joint_constraints/damping" == p_name) { - damping = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->pin_joint_set_param(j, PhysicsServer::PIN_JOINT_DAMPING, damping); - - } else if ("joint_constraints/impulse_clamp" == p_name) { - impulse_clamp = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->pin_joint_set_param(j, PhysicsServer::PIN_JOINT_IMPULSE_CLAMP, impulse_clamp); - - } else { - return false; - } - - return true; + return false; } -bool PhysicalBone::PinJointData::_get(const StringName &p_name, Variant &r_ret) const { +bool PhysicalBone::FixedJointData::_get(const StringName &p_name, Variant &r_ret) const { if (JointData::_get(p_name, r_ret)) { return true; } - if ("joint_constraints/bias" == p_name) { - r_ret = bias; - } else if ("joint_constraints/damping" == p_name) { - r_ret = damping; - } else if ("joint_constraints/impulse_clamp" == p_name) { - r_ret = impulse_clamp; - } else { - return false; - } - - return true; + return false; } -void PhysicalBone::PinJointData::_get_property_list(List *p_list) const { +void PhysicalBone::FixedJointData::_get_property_list(List *p_list) const { JointData::_get_property_list(p_list); - - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/bias", PROPERTY_HINT_RANGE, "0.01,0.99,0.01")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/damping", PROPERTY_HINT_RANGE, "0.01,8.0,0.01")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/impulse_clamp", PROPERTY_HINT_RANGE, "0.0,64.0,0.01")); } -bool PhysicalBone::ConeJointData::_set(const StringName &p_name, const Variant &p_value, RID j) { - if (JointData::_set(p_name, p_value, j)) { +bool PhysicalBone::SliderJointData::_set(const StringName &p_name, const Variant &p_value) { + if (JointData::_set(p_name, p_value)) { return true; } - if ("joint_constraints/swing_span" == p_name) { - swing_span = Math::deg2rad(real_t(p_value)); - if (j.is_valid()) - PhysicsServer::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer::CONE_TWIST_JOINT_SWING_SPAN, swing_span); - - } else if ("joint_constraints/twist_span" == p_name) { - twist_span = Math::deg2rad(real_t(p_value)); - if (j.is_valid()) - PhysicsServer::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer::CONE_TWIST_JOINT_TWIST_SPAN, twist_span); - - } else if ("joint_constraints/bias" == p_name) { - bias = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer::CONE_TWIST_JOINT_BIAS, bias); - - } else if ("joint_constraints/softness" == p_name) { - softness = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer::CONE_TWIST_JOINT_SOFTNESS, softness); - - } else if ("joint_constraints/relaxation" == p_name) { - relaxation = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer::CONE_TWIST_JOINT_RELAXATION, relaxation); - + if ("slider_joint/limit_active" == p_name) { + limit_active = p_value; + } else if ("slider_joint/lower_limit" == p_name) { + lower_limit = p_value; + } else if ("slider_joint/upper_limit" == p_name) { + upper_limit = p_value; + } else if ("slider_joint/motor_is_enabled" == p_name) { + motor_is_enabled = p_value; + } else if ("slider_joint/motor_velocity_target" == p_name) { + motor_velocity_target = p_value; + } else if ("slider_joint/motor_position_target" == p_name) { + motor_position_target = p_value; + } else if ("slider_joint/motor_max_impulse" == p_name) { + motor_max_impulse = p_value; + } else if ("slider_joint/motor_error_reduction_parameter" == p_name) { + motor_error_reduction_parameter = p_value; + } else if ("slider_joint/motor_spring_constant" == p_name) { + motor_spring_constant = p_value; + } else if ("slider_joint/motor_damping_constant" == p_name) { + motor_damping_constant = p_value; + } else if ("slider_joint/motor_maximum_error" == p_name) { + motor_maximum_error = p_value; } else { return false; } @@ -1650,76 +1497,84 @@ bool PhysicalBone::ConeJointData::_set(const StringName &p_name, const Variant & return true; } -bool PhysicalBone::ConeJointData::_get(const StringName &p_name, Variant &r_ret) const { +bool PhysicalBone::SliderJointData::_get(const StringName &p_name, Variant &r_ret) const { if (JointData::_get(p_name, r_ret)) { return true; } - if ("joint_constraints/swing_span" == p_name) { - r_ret = Math::rad2deg(swing_span); - } else if ("joint_constraints/twist_span" == p_name) { - r_ret = Math::rad2deg(twist_span); - } else if ("joint_constraints/bias" == p_name) { - r_ret = bias; - } else if ("joint_constraints/softness" == p_name) { - r_ret = softness; - } else if ("joint_constraints/relaxation" == p_name) { - r_ret = relaxation; - } else { + if ("slider_joint/limit_active" == p_name) { + r_ret = limit_active; + } else if ("slider_joint/lower_limit" == p_name) { + r_ret = lower_limit; + } else if ("slider_joint/upper_limit" == p_name) { + r_ret = upper_limit; + } else if ("slider_joint/motor_is_enabled" == p_name) { + r_ret = motor_is_enabled; + } else if ("slider_joint/motor_velocity_target" == p_name) { + r_ret = motor_velocity_target; + } else if ("slider_joint/motor_position_target" == p_name) { + r_ret = motor_position_target; + } else if ("slider_joint/motor_max_impulse" == p_name) { + r_ret = motor_max_impulse; + } else if ("slider_joint/motor_error_reduction_parameter" == p_name) { + r_ret = motor_error_reduction_parameter; + } else if ("slider_joint/motor_spring_constant" == p_name) { + r_ret = motor_spring_constant; + } else if ("slider_joint/motor_damping_constant" == p_name) { + r_ret = motor_damping_constant; + } else if ("slider_joint/motor_maximum_error" == p_name) { + r_ret = motor_maximum_error; + } else return false; - } return true; } -void PhysicalBone::ConeJointData::_get_property_list(List *p_list) const { +void PhysicalBone::SliderJointData::_get_property_list(List *p_list) const { JointData::_get_property_list(p_list); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/swing_span", PROPERTY_HINT_RANGE, "-180,180,0.01")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/twist_span", PROPERTY_HINT_RANGE, "-40000,40000,0.1,or_lesser,or_greater")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/bias", PROPERTY_HINT_RANGE, "0.01,16.0,0.01")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/relaxation", PROPERTY_HINT_RANGE, "0.01,16.0,0.01")); -} - -bool PhysicalBone::HingeJointData::_set(const StringName &p_name, const Variant &p_value, RID j) { - if (JointData::_set(p_name, p_value, j)) { + p_list->push_back(PropertyInfo(Variant::BOOL, "slider_joint/limit_active")); + p_list->push_back(PropertyInfo(Variant::REAL, "slider_joint/lower_limit")); + p_list->push_back(PropertyInfo(Variant::REAL, "slider_joint/upper_limit")); + p_list->push_back(PropertyInfo(Variant::BOOL, "slider_joint/motor_is_enabled")); + p_list->push_back(PropertyInfo(Variant::REAL, "slider_joint/motor_velocity_target")); + p_list->push_back(PropertyInfo(Variant::REAL, "slider_joint/motor_position_target")); + p_list->push_back(PropertyInfo(Variant::REAL, "slider_joint/motor_max_impulse")); + p_list->push_back(PropertyInfo(Variant::REAL, "slider_joint/motor_error_reduction_parameter")); + p_list->push_back(PropertyInfo(Variant::REAL, "slider_joint/motor_spring_constant")); + p_list->push_back(PropertyInfo(Variant::REAL, "slider_joint/motor_damping_constant")); + p_list->push_back(PropertyInfo(Variant::REAL, "slider_joint/motor_maximum_error")); +} + +bool PhysicalBone::HingeJointData::_set(const StringName &p_name, const Variant &p_value) { + if (JointData::_set(p_name, p_value)) { return true; } - if ("joint_constraints/angular_limit_enabled" == p_name) { - angular_limit_enabled = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->hinge_joint_set_flag(j, PhysicsServer::HINGE_JOINT_FLAG_USE_LIMIT, angular_limit_enabled); - - } else if ("joint_constraints/angular_limit_upper" == p_name) { - angular_limit_upper = Math::deg2rad(real_t(p_value)); - if (j.is_valid()) - PhysicsServer::get_singleton()->hinge_joint_set_param(j, PhysicsServer::HINGE_JOINT_LIMIT_UPPER, angular_limit_upper); - - } else if ("joint_constraints/angular_limit_lower" == p_name) { - angular_limit_lower = Math::deg2rad(real_t(p_value)); - if (j.is_valid()) - PhysicsServer::get_singleton()->hinge_joint_set_param(j, PhysicsServer::HINGE_JOINT_LIMIT_LOWER, angular_limit_lower); - - } else if ("joint_constraints/angular_limit_bias" == p_name) { - angular_limit_bias = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->hinge_joint_set_param(j, PhysicsServer::HINGE_JOINT_LIMIT_BIAS, angular_limit_bias); - - } else if ("joint_constraints/angular_limit_softness" == p_name) { - angular_limit_softness = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->hinge_joint_set_param(j, PhysicsServer::HINGE_JOINT_LIMIT_SOFTNESS, angular_limit_softness); - - } else if ("joint_constraints/angular_limit_relaxation" == p_name) { - angular_limit_relaxation = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->hinge_joint_set_param(j, PhysicsServer::HINGE_JOINT_LIMIT_RELAXATION, angular_limit_relaxation); - - } else { + if ("hinge_joint/limit_active" == p_name) { + limit_active = p_value; + } else if ("hinge_joint/lower_limit" == p_name) { + lower_limit = p_value; + } else if ("hinge_joint/upper_limit" == p_name) { + upper_limit = p_value; + } else if ("hinge_joint/motor_is_enabled" == p_name) { + motor_is_enabled = p_value; + } else if ("hinge_joint/motor_velocity_target" == p_name) { + motor_velocity_target = p_value; + } else if ("hinge_joint/motor_position_target" == p_name) { + motor_position_target = p_value; + } else if ("hinge_joint/motor_max_impulse" == p_name) { + motor_max_impulse = p_value; + } else if ("hinge_joint/motor_error_reduction_parameter" == p_name) { + motor_error_reduction_parameter = p_value; + } else if ("hinge_joint/motor_spring_constant" == p_name) { + motor_spring_constant = p_value; + } else if ("hinge_joint/motor_damping_constant" == p_name) { + motor_damping_constant = p_value; + } else if ("hinge_joint/motor_maximum_error" == p_name) { + motor_maximum_error = p_value; + } else return false; - } return true; } @@ -1729,21 +1584,30 @@ bool PhysicalBone::HingeJointData::_get(const StringName &p_name, Variant &r_ret return true; } - if ("joint_constraints/angular_limit_enabled" == p_name) { - r_ret = angular_limit_enabled; - } else if ("joint_constraints/angular_limit_upper" == p_name) { - r_ret = Math::rad2deg(angular_limit_upper); - } else if ("joint_constraints/angular_limit_lower" == p_name) { - r_ret = Math::rad2deg(angular_limit_lower); - } else if ("joint_constraints/angular_limit_bias" == p_name) { - r_ret = angular_limit_bias; - } else if ("joint_constraints/angular_limit_softness" == p_name) { - r_ret = angular_limit_softness; - } else if ("joint_constraints/angular_limit_relaxation" == p_name) { - r_ret = angular_limit_relaxation; - } else { + if ("hinge_joint/limit_active" == p_name) { + r_ret = limit_active; + } else if ("hinge_joint/lower_limit" == p_name) { + r_ret = lower_limit; + } else if ("hinge_joint/upper_limit" == p_name) { + r_ret = upper_limit; + } else if ("hinge_joint/motor_is_enabled" == p_name) { + r_ret = motor_is_enabled; + } else if ("hinge_joint/motor_velocity_target" == p_name) { + r_ret = motor_velocity_target; + } else if ("hinge_joint/motor_position_target" == p_name) { + r_ret = motor_position_target; + } else if ("hinge_joint/motor_max_impulse" == p_name) { + r_ret = motor_max_impulse; + } else if ("hinge_joint/motor_error_reduction_parameter" == p_name) { + r_ret = motor_error_reduction_parameter; + } else if ("hinge_joint/motor_spring_constant" == p_name) { + r_ret = motor_spring_constant; + } else if ("hinge_joint/motor_damping_constant" == p_name) { + r_ret = motor_damping_constant; + } else if ("hinge_joint/motor_maximum_error" == p_name) { + r_ret = motor_maximum_error; + } else return false; - } return true; } @@ -1751,69 +1615,40 @@ bool PhysicalBone::HingeJointData::_get(const StringName &p_name, Variant &r_ret void PhysicalBone::HingeJointData::_get_property_list(List *p_list) const { JointData::_get_property_list(p_list); - p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/angular_limit_enabled")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/angular_limit_upper", PROPERTY_HINT_RANGE, "-180,180,0.01")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/angular_limit_lower", PROPERTY_HINT_RANGE, "-180,180,0.01")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/angular_limit_bias", PROPERTY_HINT_RANGE, "0.01,0.99,0.01")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/angular_limit_softness", PROPERTY_HINT_RANGE, "0.01,16,0.01")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/angular_limit_relaxation", PROPERTY_HINT_RANGE, "0.01,16,0.01")); -} - -bool PhysicalBone::SliderJointData::_set(const StringName &p_name, const Variant &p_value, RID j) { - if (JointData::_set(p_name, p_value, j)) { + p_list->push_back(PropertyInfo(Variant::BOOL, "hinge_joint/limit_active")); + p_list->push_back(PropertyInfo(Variant::REAL, "hinge_joint/lower_limit")); + p_list->push_back(PropertyInfo(Variant::REAL, "hinge_joint/upper_limit")); + p_list->push_back(PropertyInfo(Variant::BOOL, "hinge_joint/motor_is_enabled")); + p_list->push_back(PropertyInfo(Variant::REAL, "hinge_joint/motor_velocity_target")); + p_list->push_back(PropertyInfo(Variant::REAL, "hinge_joint/motor_position_target")); + p_list->push_back(PropertyInfo(Variant::REAL, "hinge_joint/motor_max_impulse")); + p_list->push_back(PropertyInfo(Variant::REAL, "hinge_joint/motor_error_reduction_parameter")); + p_list->push_back(PropertyInfo(Variant::REAL, "hinge_joint/motor_spring_constant")); + p_list->push_back(PropertyInfo(Variant::REAL, "hinge_joint/motor_damping_constant")); + p_list->push_back(PropertyInfo(Variant::REAL, "hinge_joint/motor_maximum_error")); +} + +bool PhysicalBone::SphericalJointData::_set(const StringName &p_name, const Variant &p_value) { + if (JointData::_set(p_name, p_value)) { return true; } - if ("joint_constraints/linear_limit_upper" == p_name) { - linear_limit_upper = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER, linear_limit_upper); - - } else if ("joint_constraints/linear_limit_lower" == p_name) { - linear_limit_lower = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_LOWER, linear_limit_lower); - - } else if ("joint_constraints/linear_limit_softness" == p_name) { - linear_limit_softness = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS, linear_limit_softness); - - } else if ("joint_constraints/linear_limit_restitution" == p_name) { - linear_limit_restitution = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION, linear_limit_restitution); - - } else if ("joint_constraints/linear_limit_damping" == p_name) { - linear_limit_damping = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_DAMPING, linear_limit_restitution); - - } else if ("joint_constraints/angular_limit_upper" == p_name) { - angular_limit_upper = Math::deg2rad(real_t(p_value)); - if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_UPPER, angular_limit_upper); - - } else if ("joint_constraints/angular_limit_lower" == p_name) { - angular_limit_lower = Math::deg2rad(real_t(p_value)); - if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_LOWER, angular_limit_lower); - - } else if ("joint_constraints/angular_limit_softness" == p_name) { - angular_limit_softness = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, angular_limit_softness); - - } else if ("joint_constraints/angular_limit_restitution" == p_name) { - angular_limit_restitution = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, angular_limit_softness); - - } else if ("joint_constraints/angular_limit_damping" == p_name) { - angular_limit_damping = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING, angular_limit_damping); - + if ("spherical_joint/motor_is_enabled" == p_name) { + motor_is_enabled = p_value; + } else if ("spherical_joint/motor_velocity_target" == p_name) { + motor_velocity_target = p_value; + } else if ("spherical_joint/motor_rotation_target" == p_name) { + motor_rotation_target = p_value; + } else if ("spherical_joint/motor_max_impulse" == p_name) { + motor_max_impulse = p_value; + } else if ("spherical_joint/motor_error_reduction_parameter" == p_name) { + motor_error_reduction_parameter = p_value; + } else if ("spherical_joint/motor_spring_constant" == p_name) { + motor_spring_constant = p_value; + } else if ("spherical_joint/motor_damping_constant" == p_name) { + motor_damping_constant = p_value; + } else if ("spherical_joint/motor_maximum_error" == p_name) { + motor_maximum_error = p_value; } else { return false; } @@ -1821,286 +1656,63 @@ bool PhysicalBone::SliderJointData::_set(const StringName &p_name, const Variant return true; } -bool PhysicalBone::SliderJointData::_get(const StringName &p_name, Variant &r_ret) const { +bool PhysicalBone::SphericalJointData::_get(const StringName &p_name, Variant &r_ret) const { if (JointData::_get(p_name, r_ret)) { return true; } - if ("joint_constraints/linear_limit_upper" == p_name) { - r_ret = linear_limit_upper; - } else if ("joint_constraints/linear_limit_lower" == p_name) { - r_ret = linear_limit_lower; - } else if ("joint_constraints/linear_limit_softness" == p_name) { - r_ret = linear_limit_softness; - } else if ("joint_constraints/linear_limit_restitution" == p_name) { - r_ret = linear_limit_restitution; - } else if ("joint_constraints/linear_limit_damping" == p_name) { - r_ret = linear_limit_damping; - } else if ("joint_constraints/angular_limit_upper" == p_name) { - r_ret = Math::rad2deg(angular_limit_upper); - } else if ("joint_constraints/angular_limit_lower" == p_name) { - r_ret = Math::rad2deg(angular_limit_lower); - } else if ("joint_constraints/angular_limit_softness" == p_name) { - r_ret = angular_limit_softness; - } else if ("joint_constraints/angular_limit_restitution" == p_name) { - r_ret = angular_limit_restitution; - } else if ("joint_constraints/angular_limit_damping" == p_name) { - r_ret = angular_limit_damping; - } else { + if ("spherical_joint/motor_is_enabled" == p_name) { + r_ret = motor_is_enabled; + } else if ("spherical_joint/motor_velocity_target" == p_name) { + r_ret = motor_velocity_target; + } else if ("spherical_joint/motor_rotation_target" == p_name) { + r_ret = motor_rotation_target; + } else if ("spherical_joint/motor_max_impulse" == p_name) { + r_ret = motor_max_impulse; + } else if ("spherical_joint/motor_error_reduction_parameter" == p_name) { + r_ret = motor_error_reduction_parameter; + } else if ("spherical_joint/motor_spring_constant" == p_name) { + r_ret = motor_spring_constant; + } else if ("spherical_joint/motor_damping_constant" == p_name) { + r_ret = motor_damping_constant; + } else if ("spherical_joint/motor_maximum_error" == p_name) { + r_ret = motor_maximum_error; + } else return false; - } return true; } -void PhysicalBone::SliderJointData::_get_property_list(List *p_list) const { - JointData::_get_property_list(p_list); - - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/linear_limit_upper")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/linear_limit_lower")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/linear_limit_softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/linear_limit_restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/linear_limit_damping", PROPERTY_HINT_RANGE, "0,16.0,0.01")); +void PhysicalBone::SphericalJointData::_get_property_list(List *p_list) const { - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/angular_limit_upper", PROPERTY_HINT_RANGE, "-180,180,0.01")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/angular_limit_lower", PROPERTY_HINT_RANGE, "-180,180,0.01")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/angular_limit_softness", PROPERTY_HINT_RANGE, "0.01,16.0,0.01")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/angular_limit_restitution", PROPERTY_HINT_RANGE, "0.01,16.0,0.01")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/angular_limit_damping", PROPERTY_HINT_RANGE, "0,16.0,0.01")); + p_list->push_back(PropertyInfo(Variant::BOOL, "spherical_joint/motor_is_enabled")); + p_list->push_back(PropertyInfo(Variant::VECTOR3, "spherical_joint/motor_velocity_target")); + p_list->push_back(PropertyInfo(Variant::VECTOR3, "spherical_joint/motor_rotation_target")); + p_list->push_back(PropertyInfo(Variant::REAL, "spherical_joint/motor_max_impulse")); + p_list->push_back(PropertyInfo(Variant::REAL, "spherical_joint/motor_error_reduction_parameter")); + p_list->push_back(PropertyInfo(Variant::REAL, "spherical_joint/motor_spring_constant")); + p_list->push_back(PropertyInfo(Variant::REAL, "spherical_joint/motor_damping_constant")); + p_list->push_back(PropertyInfo(Variant::REAL, "spherical_joint/motor_maximum_error")); } -bool PhysicalBone::SixDOFJointData::_set(const StringName &p_name, const Variant &p_value, RID j) { - if (JointData::_set(p_name, p_value, j)) { +bool PhysicalBone::PlanarJointData::_set(const StringName &p_name, const Variant &p_value) { + if (JointData::_set(p_name, p_value)) { return true; } - String path = p_name; - - Vector3::Axis axis; - { - const String axis_s = path.get_slicec('/', 1); - if ("x" == axis_s) { - axis = Vector3::AXIS_X; - } else if ("y" == axis_s) { - axis = Vector3::AXIS_Y; - } else if ("z" == axis_s) { - axis = Vector3::AXIS_Z; - } else { - return false; - } - } - - String var_name = path.get_slicec('/', 2); - - if ("linear_limit_enabled" == var_name) { - axis_data[axis].linear_limit_enabled = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, axis_data[axis].linear_limit_enabled); - - } else if ("linear_limit_upper" == var_name) { - axis_data[axis].linear_limit_upper = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_UPPER_LIMIT, axis_data[axis].linear_limit_upper); - - } else if ("linear_limit_lower" == var_name) { - axis_data[axis].linear_limit_lower = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT, axis_data[axis].linear_limit_lower); - - } else if ("linear_limit_softness" == var_name) { - axis_data[axis].linear_limit_softness = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, axis_data[axis].linear_limit_softness); - - } else if ("linear_spring_enabled" == var_name) { - axis_data[axis].linear_spring_enabled = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, axis_data[axis].linear_spring_enabled); - - } else if ("linear_spring_stiffness" == var_name) { - axis_data[axis].linear_spring_stiffness = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, axis_data[axis].linear_spring_stiffness); - - } else if ("linear_spring_damping" == var_name) { - axis_data[axis].linear_spring_damping = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING, axis_data[axis].linear_spring_damping); - - } else if ("linear_equilibrium_point" == var_name) { - axis_data[axis].linear_equilibrium_point = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, axis_data[axis].linear_equilibrium_point); - - } else if ("linear_restitution" == var_name) { - axis_data[axis].linear_restitution = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_RESTITUTION, axis_data[axis].linear_restitution); - - } else if ("linear_damping" == var_name) { - axis_data[axis].linear_damping = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING, axis_data[axis].linear_damping); - - } else if ("angular_limit_enabled" == var_name) { - axis_data[axis].angular_limit_enabled = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, axis_data[axis].angular_limit_enabled); - - } else if ("angular_limit_upper" == var_name) { - axis_data[axis].angular_limit_upper = Math::deg2rad(real_t(p_value)); - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT, axis_data[axis].angular_limit_upper); - - } else if ("angular_limit_lower" == var_name) { - axis_data[axis].angular_limit_lower = Math::deg2rad(real_t(p_value)); - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT, axis_data[axis].angular_limit_lower); - - } else if ("angular_limit_softness" == var_name) { - axis_data[axis].angular_limit_softness = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS, axis_data[axis].angular_limit_softness); - - } else if ("angular_restitution" == var_name) { - axis_data[axis].angular_restitution = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION, axis_data[axis].angular_restitution); - - } else if ("angular_damping" == var_name) { - axis_data[axis].angular_damping = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_DAMPING, axis_data[axis].angular_damping); - - } else if ("erp" == var_name) { - axis_data[axis].erp = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_ERP, axis_data[axis].erp); - - } else if ("angular_spring_enabled" == var_name) { - axis_data[axis].angular_spring_enabled = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, axis_data[axis].angular_spring_enabled); - - } else if ("angular_spring_stiffness" == var_name) { - axis_data[axis].angular_spring_stiffness = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, axis_data[axis].angular_spring_stiffness); - - } else if ("angular_spring_damping" == var_name) { - axis_data[axis].angular_spring_damping = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, axis_data[axis].angular_spring_damping); - - } else if ("angular_equilibrium_point" == var_name) { - axis_data[axis].angular_equilibrium_point = p_value; - if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, axis_data[axis].angular_equilibrium_point); - - } else { - return false; - } - - return true; + return false; } -bool PhysicalBone::SixDOFJointData::_get(const StringName &p_name, Variant &r_ret) const { +bool PhysicalBone::PlanarJointData::_get(const StringName &p_name, Variant &r_ret) const { if (JointData::_get(p_name, r_ret)) { return true; } - String path = p_name; - - int axis; - { - const String axis_s = path.get_slicec('/', 1); - if ("x" == axis_s) { - axis = 0; - } else if ("y" == axis_s) { - axis = 1; - } else if ("z" == axis_s) { - axis = 2; - } else { - return false; - } - } - - String var_name = path.get_slicec('/', 2); - - if ("linear_limit_enabled" == var_name) { - r_ret = axis_data[axis].linear_limit_enabled; - } else if ("linear_limit_upper" == var_name) { - r_ret = axis_data[axis].linear_limit_upper; - } else if ("linear_limit_lower" == var_name) { - r_ret = axis_data[axis].linear_limit_lower; - } else if ("linear_limit_softness" == var_name) { - r_ret = axis_data[axis].linear_limit_softness; - } else if ("linear_spring_enabled" == var_name) { - r_ret = axis_data[axis].linear_spring_enabled; - } else if ("linear_spring_stiffness" == var_name) { - r_ret = axis_data[axis].linear_spring_stiffness; - } else if ("linear_spring_damping" == var_name) { - r_ret = axis_data[axis].linear_spring_damping; - } else if ("linear_equilibrium_point" == var_name) { - r_ret = axis_data[axis].linear_equilibrium_point; - } else if ("linear_restitution" == var_name) { - r_ret = axis_data[axis].linear_restitution; - } else if ("linear_damping" == var_name) { - r_ret = axis_data[axis].linear_damping; - } else if ("angular_limit_enabled" == var_name) { - r_ret = axis_data[axis].angular_limit_enabled; - } else if ("angular_limit_upper" == var_name) { - r_ret = Math::rad2deg(axis_data[axis].angular_limit_upper); - } else if ("angular_limit_lower" == var_name) { - r_ret = Math::rad2deg(axis_data[axis].angular_limit_lower); - } else if ("angular_limit_softness" == var_name) { - r_ret = axis_data[axis].angular_limit_softness; - } else if ("angular_restitution" == var_name) { - r_ret = axis_data[axis].angular_restitution; - } else if ("angular_damping" == var_name) { - r_ret = axis_data[axis].angular_damping; - } else if ("erp" == var_name) { - r_ret = axis_data[axis].erp; - } else if ("angular_spring_enabled" == var_name) { - r_ret = axis_data[axis].angular_spring_enabled; - } else if ("angular_spring_stiffness" == var_name) { - r_ret = axis_data[axis].angular_spring_stiffness; - } else if ("angular_spring_damping" == var_name) { - r_ret = axis_data[axis].angular_spring_damping; - } else if ("angular_equilibrium_point" == var_name) { - r_ret = axis_data[axis].angular_equilibrium_point; - } else { - return false; - } - - return true; + return false; } -void PhysicalBone::SixDOFJointData::_get_property_list(List *p_list) const { - const StringName axis_names[] = { "x", "y", "z" }; - for (int i = 0; i < 3; ++i) { - p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/linear_limit_enabled")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_limit_upper")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_limit_lower")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_limit_softness", PROPERTY_HINT_RANGE, "0.01,16,0.01")); - p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/linear_spring_enabled")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_spring_stiffness")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_spring_damping")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_equilibrium_point")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_damping", PROPERTY_HINT_RANGE, "0.01,16,0.01")); - p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/angular_limit_enabled")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_limit_upper", PROPERTY_HINT_RANGE, "-180,180,0.01")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_limit_lower", PROPERTY_HINT_RANGE, "-180,180,0.01")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_limit_softness", PROPERTY_HINT_RANGE, "0.01,16,0.01")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_damping", PROPERTY_HINT_RANGE, "0.01,16,0.01")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/erp")); - p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/angular_spring_enabled")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_spring_stiffness")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_spring_damping")); - p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_equilibrium_point")); - } +void PhysicalBone::PlanarJointData::_get_property_list(List *p_list) const { + JointData::_get_property_list(p_list); } bool PhysicalBone::_set(const StringName &p_name, const Variant &p_value) { @@ -2141,7 +1753,7 @@ void PhysicalBone::_get_property_list(List *p_list) const { if (parent) { - String names; + String names("--,"); for (int i = 0; i < parent->get_bone_count(); i++) { if (i > 0) names += ","; @@ -2162,46 +1774,42 @@ void PhysicalBone::_get_property_list(List *p_list) const { void PhysicalBone::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: + parent_skeleton = find_skeleton_parent(get_parent()); + update_bone_id(); reset_to_rest_position(); - _reset_physics_simulation_state(); + reset_physics_simulation_state(); + break; case NOTIFICATION_EXIT_TREE: + if (parent_skeleton) { - if (-1 != bone_id) { - parent_skeleton->unbind_physical_bone_from_bone(bone_id); - } + parent_skeleton->unbind_physical_bone_from_bone(bone_id); + parent_skeleton = NULL; + update_bone_id(); } - parent_skeleton = NULL; - update_bone_id(); + break; case NOTIFICATION_TRANSFORM_CHANGED: - if (Engine::get_singleton()->is_editor_hint()) { + if (Engine::get_singleton()->is_editor_hint()) { update_offset(); } + break; } } void PhysicalBone::_direct_state_changed(Object *p_state) { - if (!simulate_physics) { + if (!_internal_simulate_physics) { return; } /// Update bone transform - PhysicsDirectBodyState *state; - -#ifdef DEBUG_ENABLED - state = Object::cast_to(p_state); -#else - state = (PhysicsDirectBodyState *)p_state; //trust it -#endif - - Transform global_transform(state->get_transform()); + Transform global_transform(PhysicsServer::get_singleton()->bone_get_transform(get_rid())); set_ignore_transform_notification(true); set_global_transform(global_transform); @@ -2210,188 +1818,475 @@ void PhysicalBone::_direct_state_changed(Object *p_state) { // Update skeleton if (parent_skeleton) { if (-1 != bone_id) { - parent_skeleton->set_bone_global_pose(bone_id, parent_skeleton->get_global_transform().affine_inverse() * (global_transform * body_offset_inverse)); + + parent_skeleton->set_bone_global_pose( + bone_id, + parent_skeleton->get_global_transform().affine_inverse() * (global_transform * body_offset_inverse)); } } -} - -void PhysicalBone::_bind_methods() { - ClassDB::bind_method(D_METHOD("_direct_state_changed"), &PhysicalBone::_direct_state_changed); - - ClassDB::bind_method(D_METHOD("set_joint_type", "joint_type"), &PhysicalBone::set_joint_type); - ClassDB::bind_method(D_METHOD("get_joint_type"), &PhysicalBone::get_joint_type); - ClassDB::bind_method(D_METHOD("set_joint_offset", "offset"), &PhysicalBone::set_joint_offset); - ClassDB::bind_method(D_METHOD("get_joint_offset"), &PhysicalBone::get_joint_offset); +#ifdef DEBUG_ENABLED + PhysicsDirectBodyState *state = Object::cast_to(p_state); +#else + PhysicsDirectBodyState *state = (PhysicsDirectBodyState *)p_state; //trust it +#endif - ClassDB::bind_method(D_METHOD("set_body_offset", "offset"), &PhysicalBone::set_body_offset); - ClassDB::bind_method(D_METHOD("get_body_offset"), &PhysicalBone::get_body_offset); + if (contact_monitor) { - ClassDB::bind_method(D_METHOD("is_static_body"), &PhysicalBone::is_static_body); + contact_monitor->locked = true; - ClassDB::bind_method(D_METHOD("get_simulate_physics"), &PhysicalBone::get_simulate_physics); + //untag all + int rc = 0; + for (Map::Element *E = contact_monitor->body_map.front(); E; E = E->next()) { - ClassDB::bind_method(D_METHOD("is_simulating_physics"), &PhysicalBone::is_simulating_physics); + for (int i = 0; i < E->get().shapes.size(); i++) { - ClassDB::bind_method(D_METHOD("get_bone_id"), &PhysicalBone::get_bone_id); + E->get().shapes[i].tagged = false; + rc++; + } + } - ClassDB::bind_method(D_METHOD("set_mass", "mass"), &PhysicalBone::set_mass); - ClassDB::bind_method(D_METHOD("get_mass"), &PhysicalBone::get_mass); + _RigidBodyInOut *toadd = (_RigidBodyInOut *)alloca(state->get_contact_count() * sizeof(_RigidBodyInOut)); + int toadd_count = 0; //state->get_contact_count(); + RigidBody_RemoveAction *toremove = (RigidBody_RemoveAction *)alloca(rc * sizeof(RigidBody_RemoveAction)); + int toremove_count = 0; - ClassDB::bind_method(D_METHOD("set_weight", "weight"), &PhysicalBone::set_weight); - ClassDB::bind_method(D_METHOD("get_weight"), &PhysicalBone::get_weight); + //put the ones to add - ClassDB::bind_method(D_METHOD("set_friction", "friction"), &PhysicalBone::set_friction); - ClassDB::bind_method(D_METHOD("get_friction"), &PhysicalBone::get_friction); + for (int i = 0; i < state->get_contact_count(); i++) { - ClassDB::bind_method(D_METHOD("set_bounce", "bounce"), &PhysicalBone::set_bounce); - ClassDB::bind_method(D_METHOD("get_bounce"), &PhysicalBone::get_bounce); + ObjectID obj = state->get_contact_collider_id(i); + int local_shape = state->get_contact_local_shape(i); + int shape = state->get_contact_collider_shape(i); - ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &PhysicalBone::set_gravity_scale); - ClassDB::bind_method(D_METHOD("get_gravity_scale"), &PhysicalBone::get_gravity_scale); + //bool found=false; - ADD_GROUP("Joint", "joint_"); - 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::TRANSFORM, "joint_offset"), "set_joint_offset", "get_joint_offset"); + Map::Element *E = contact_monitor->body_map.find(obj); + if (!E) { + toadd[toadd_count].local_shape = local_shape; + toadd[toadd_count].id = obj; + toadd[toadd_count].shape = shape; + toadd_count++; + continue; + } - ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "body_offset"), "set_body_offset", "get_body_offset"); + ShapePair sp(shape, local_shape); + int idx = E->get().shapes.find(sp); + if (idx == -1) { - ADD_PROPERTY(PropertyInfo(Variant::REAL, "mass", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_mass", "get_mass"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "weight", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_weight", "get_weight"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_friction", "get_friction"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_bounce", "get_bounce"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "gravity_scale", PROPERTY_HINT_RANGE, "-10,10,0.01"), "set_gravity_scale", "get_gravity_scale"); + toadd[toadd_count].local_shape = local_shape; + toadd[toadd_count].id = obj; + toadd[toadd_count].shape = shape; + toadd_count++; + continue; + } - BIND_ENUM_CONSTANT(JOINT_TYPE_NONE); - BIND_ENUM_CONSTANT(JOINT_TYPE_PIN); - BIND_ENUM_CONSTANT(JOINT_TYPE_CONE); - BIND_ENUM_CONSTANT(JOINT_TYPE_HINGE); - BIND_ENUM_CONSTANT(JOINT_TYPE_SLIDER); - BIND_ENUM_CONSTANT(JOINT_TYPE_6DOF); -} + E->get().shapes[idx].tagged = true; + } -Skeleton *PhysicalBone::find_skeleton_parent(Node *p_parent) { - if (!p_parent) { - return NULL; - } - Skeleton *s = Object::cast_to(p_parent); - return s ? s : find_skeleton_parent(p_parent->get_parent()); -} + //put the ones to remove -void PhysicalBone::_fix_joint_offset() { - // Clamp joint origin to bone origin - if (parent_skeleton) { - joint_offset.origin = body_offset.affine_inverse().origin; - } -} + for (Map::Element *E = contact_monitor->body_map.front(); E; E = E->next()) { -void PhysicalBone::_reload_joint() { + for (int i = 0; i < E->get().shapes.size(); i++) { - if (joint.is_valid()) { - PhysicsServer::get_singleton()->free(joint); - joint = RID(); - } + if (!E->get().shapes[i].tagged) { - if (!parent_skeleton) { - return; - } + toremove[toremove_count].body_id = E->key(); + toremove[toremove_count].pair = E->get().shapes[i]; + toremove_count++; + } + } + } - PhysicalBone *body_a = parent_skeleton->get_physical_bone_parent(bone_id); - if (!body_a) { - return; - } + //process remotions - Transform joint_transf = get_global_transform() * joint_offset; - Transform local_a = body_a->get_global_transform().affine_inverse() * joint_transf; - local_a.orthonormalize(); + for (int i = 0; i < toremove_count; i++) { - switch (get_joint_type()) { - case JOINT_TYPE_PIN: { + _body_inout(0, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape); + } - joint = PhysicsServer::get_singleton()->joint_create_pin(body_a->get_rid(), local_a.origin, get_rid(), joint_offset.origin); - const PinJointData *pjd(static_cast(joint_data)); - PhysicsServer::get_singleton()->pin_joint_set_param(joint, PhysicsServer::PIN_JOINT_BIAS, pjd->bias); - PhysicsServer::get_singleton()->pin_joint_set_param(joint, PhysicsServer::PIN_JOINT_DAMPING, pjd->damping); - PhysicsServer::get_singleton()->pin_joint_set_param(joint, PhysicsServer::PIN_JOINT_IMPULSE_CLAMP, pjd->impulse_clamp); + //process aditions - } break; - case JOINT_TYPE_CONE: { + for (int i = 0; i < toadd_count; i++) { - joint = PhysicsServer::get_singleton()->joint_create_cone_twist(body_a->get_rid(), local_a, get_rid(), joint_offset); - const ConeJointData *cjd(static_cast(joint_data)); - PhysicsServer::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer::CONE_TWIST_JOINT_SWING_SPAN, cjd->swing_span); - PhysicsServer::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer::CONE_TWIST_JOINT_TWIST_SPAN, cjd->twist_span); - PhysicsServer::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer::CONE_TWIST_JOINT_BIAS, cjd->bias); - PhysicsServer::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer::CONE_TWIST_JOINT_SOFTNESS, cjd->softness); - PhysicsServer::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer::CONE_TWIST_JOINT_RELAXATION, cjd->relaxation); + _body_inout(1, toadd[i].id, toadd[i].shape, toadd[i].local_shape); + } - } break; - case JOINT_TYPE_HINGE: { + contact_monitor->locked = false; + } +} - joint = PhysicsServer::get_singleton()->joint_create_hinge(body_a->get_rid(), local_a, get_rid(), joint_offset); - const HingeJointData *hjd(static_cast(joint_data)); - PhysicsServer::get_singleton()->hinge_joint_set_flag(joint, PhysicsServer::HINGE_JOINT_FLAG_USE_LIMIT, hjd->angular_limit_enabled); - PhysicsServer::get_singleton()->hinge_joint_set_param(joint, PhysicsServer::HINGE_JOINT_LIMIT_UPPER, hjd->angular_limit_upper); - PhysicsServer::get_singleton()->hinge_joint_set_param(joint, PhysicsServer::HINGE_JOINT_LIMIT_LOWER, hjd->angular_limit_lower); - PhysicsServer::get_singleton()->hinge_joint_set_param(joint, PhysicsServer::HINGE_JOINT_LIMIT_BIAS, hjd->angular_limit_bias); - PhysicsServer::get_singleton()->hinge_joint_set_param(joint, PhysicsServer::HINGE_JOINT_LIMIT_SOFTNESS, hjd->angular_limit_softness); - PhysicsServer::get_singleton()->hinge_joint_set_param(joint, PhysicsServer::HINGE_JOINT_LIMIT_RELAXATION, hjd->angular_limit_relaxation); +void PhysicalBone::_body_enter_tree(ObjectID p_id) { + Object *obj = ObjectDB::get_instance(p_id); + Node *node = Object::cast_to(obj); + ERR_FAIL_COND(!node); + + ERR_FAIL_COND(!contact_monitor); + Map::Element *E = contact_monitor->body_map.find(p_id); + ERR_FAIL_COND(!E); + ERR_FAIL_COND(E->get().in_tree); + + E->get().in_tree = true; + + contact_monitor->locked = true; + + emit_signal(SceneStringNames::get_singleton()->body_entered, node); + + for (int i = 0; i < E->get().shapes.size(); i++) { + + emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape); + } + + contact_monitor->locked = false; +} + +void PhysicalBone::_body_exit_tree(ObjectID p_id) { + + Object *obj = ObjectDB::get_instance(p_id); + Node *node = Object::cast_to(obj); + ERR_FAIL_COND(!node); + ERR_FAIL_COND(!contact_monitor); + Map::Element *E = contact_monitor->body_map.find(p_id); + ERR_FAIL_COND(!E); + ERR_FAIL_COND(!E->get().in_tree); + E->get().in_tree = false; + + contact_monitor->locked = true; + + emit_signal(SceneStringNames::get_singleton()->body_exited, node); + + for (int i = 0; i < E->get().shapes.size(); i++) { + + emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape); + } + + contact_monitor->locked = false; +} + +void PhysicalBone::_body_inout(int p_status, ObjectID p_instance, int p_body_shape, int p_local_shape) { + + bool body_in = p_status == 1; + ObjectID objid = p_instance; + + Object *obj = ObjectDB::get_instance(objid); + Node *node = Object::cast_to(obj); + + ERR_FAIL_COND(!contact_monitor); + Map::Element *E = contact_monitor->body_map.find(objid); + + ERR_FAIL_COND(!body_in && !E); + + if (body_in) { + if (!E) { + + E = contact_monitor->body_map.insert(objid, BodyState()); + //E->get().rc=0; + E->get().in_tree = node && node->is_inside_tree(); + if (node) { + node->connect(SceneStringNames::get_singleton()->tree_entered, this, SceneStringNames::get_singleton()->_body_enter_tree, make_binds(objid)); + node->connect(SceneStringNames::get_singleton()->tree_exiting, this, SceneStringNames::get_singleton()->_body_exit_tree, make_binds(objid)); + if (E->get().in_tree) { + emit_signal(SceneStringNames::get_singleton()->body_entered, node); + } + } + } + //E->get().rc++; + if (node) + E->get().shapes.insert(ShapePair(p_body_shape, p_local_shape)); + + if (E->get().in_tree) { + emit_signal(SceneStringNames::get_singleton()->body_shape_entered, objid, node, p_body_shape, p_local_shape); + } + + } else { + + //E->get().rc--; + + if (node) + E->get().shapes.erase(ShapePair(p_body_shape, p_local_shape)); + + bool in_tree = E->get().in_tree; + + if (E->get().shapes.empty()) { + + if (node) { + node->disconnect(SceneStringNames::get_singleton()->tree_entered, this, SceneStringNames::get_singleton()->_body_enter_tree); + node->disconnect(SceneStringNames::get_singleton()->tree_exiting, this, SceneStringNames::get_singleton()->_body_exit_tree); + if (in_tree) + emit_signal(SceneStringNames::get_singleton()->body_exited, node); + } + + contact_monitor->body_map.erase(E); + } + if (node && in_tree) { + emit_signal(SceneStringNames::get_singleton()->body_shape_exited, objid, obj, p_body_shape, p_local_shape); + } + } +} + +void PhysicalBone::_bind_methods() { + ClassDB::bind_method(D_METHOD("_direct_state_changed"), &PhysicalBone::_direct_state_changed); + + ClassDB::bind_method(D_METHOD("_body_enter_tree"), &PhysicalBone::_body_enter_tree); + ClassDB::bind_method(D_METHOD("_body_exit_tree"), &PhysicalBone::_body_exit_tree); + + ClassDB::bind_method(D_METHOD("set_disable_parent_collision", "disable"), &PhysicalBone::set_disable_parent_collision); + ClassDB::bind_method(D_METHOD("get_disable_parent_collision"), &PhysicalBone::get_disable_parent_collision); + + ClassDB::bind_method(D_METHOD("set_joint_type", "joint_type"), &PhysicalBone::set_joint_type); + ClassDB::bind_method(D_METHOD("get_joint_type"), &PhysicalBone::get_joint_type); + + ClassDB::bind_method(D_METHOD("set_joint_offset", "offset"), &PhysicalBone::set_joint_offset); + ClassDB::bind_method(D_METHOD("get_joint_offset"), &PhysicalBone::get_joint_offset); + + ClassDB::bind_method(D_METHOD("set_body_offset", "offset"), &PhysicalBone::set_body_offset); + ClassDB::bind_method(D_METHOD("get_body_offset"), &PhysicalBone::get_body_offset); + + ClassDB::bind_method(D_METHOD("is_simulating_physics"), &PhysicalBone::is_simulating_physics); + + ClassDB::bind_method(D_METHOD("set_bone_name", "bone_id"), &PhysicalBone::set_bone_name); + ClassDB::bind_method(D_METHOD("get_bone_name"), &PhysicalBone::get_bone_name); + + ClassDB::bind_method(D_METHOD("set_bone_id", "bone_id"), &PhysicalBone::set_bone_id); + ClassDB::bind_method(D_METHOD("get_bone_id"), &PhysicalBone::get_bone_id); + + ClassDB::bind_method(D_METHOD("set_link_mass", "mass"), &PhysicalBone::set_link_mass); + ClassDB::bind_method(D_METHOD("get_link_mass"), &PhysicalBone::get_link_mass); + + ClassDB::bind_method(D_METHOD("set_weight", "weight"), &PhysicalBone::set_weight); + ClassDB::bind_method(D_METHOD("get_weight"), &PhysicalBone::get_weight); + + ClassDB::bind_method(D_METHOD("set_friction", "friction"), &PhysicalBone::set_friction); + ClassDB::bind_method(D_METHOD("get_friction"), &PhysicalBone::get_friction); + + ClassDB::bind_method(D_METHOD("set_bounce", "bounce"), &PhysicalBone::set_bounce); + ClassDB::bind_method(D_METHOD("get_bounce"), &PhysicalBone::get_bounce); + + ClassDB::bind_method(D_METHOD("set_contact_monitor", "enabled"), &PhysicalBone::set_contact_monitor); + ClassDB::bind_method(D_METHOD("is_contact_monitor_enabled"), &PhysicalBone::is_contact_monitor_enabled); + + ClassDB::bind_method(D_METHOD("set_max_contacts_reported", "amount"), &PhysicalBone::set_max_contacts_reported); + ClassDB::bind_method(D_METHOD("get_max_contacts_reported"), &PhysicalBone::get_max_contacts_reported); + + ClassDB::bind_method(D_METHOD("motor_set_active", "active"), &PhysicalBone::motor_set_active); + ClassDB::bind_method(D_METHOD("motor_set_position_target", "position"), &PhysicalBone::motor_set_position_target); + ClassDB::bind_method(D_METHOD("motor_set_rotation_target", "rotation"), &PhysicalBone::motor_set_rotation_target); + ClassDB::bind_method(D_METHOD("motor_set_rotation_target_basis", "rotation"), &PhysicalBone::motor_set_rotation_target_basis); + ClassDB::bind_method(D_METHOD("motor_set_velocity", "velocity"), &PhysicalBone::motor_set_velocity); + ClassDB::bind_method(D_METHOD("motor_set_max_impulse", "max_impulse"), &PhysicalBone::motor_set_max_impulse); + ClassDB::bind_method(D_METHOD("motor_set_error_reduction_parameter", "error_reduction_parameter"), &PhysicalBone::motor_set_error_reduction_parameter); + ClassDB::bind_method(D_METHOD("motor_set_spring_constant", "spring_constant"), &PhysicalBone::motor_set_spring_constant); + ClassDB::bind_method(D_METHOD("motor_set_damping_constant", "damping_constant"), &PhysicalBone::motor_set_damping_constant); + ClassDB::bind_method(D_METHOD("motor_set_maximum_error", "maximum_error"), &PhysicalBone::motor_set_maximum_error); + + ClassDB::bind_method(D_METHOD("get_joint_force"), &PhysicalBone::get_joint_force); + ClassDB::bind_method(D_METHOD("get_joint_torque"), &PhysicalBone::get_joint_torque); + + ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &PhysicalBone::get_colliding_bodies); + + ADD_GROUP("Joint", "joint_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "joint_type", PROPERTY_HINT_ENUM, "None,Fixed,Slider,Hinge,Spherical,Planar"), "set_joint_type", "get_joint_type"); + ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "joint_offset"), "set_joint_offset", "get_joint_offset"); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_parent_collision"), "set_disable_parent_collision", "get_disable_parent_collision"); + ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "body_offset"), "set_body_offset", "get_body_offset"); + + ADD_PROPERTY(PropertyInfo(Variant::REAL, "link_mass", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_link_mass", "get_link_mass"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "weight", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_weight", "get_weight"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_friction", "get_friction"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_bounce", "get_bounce"); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "contact_monitor"), "set_contact_monitor", "is_contact_monitor_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "contacts_reported"), "set_max_contacts_reported", "get_max_contacts_reported"); + + ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); + ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); + + BIND_ENUM_CONSTANT(JOINT_TYPE_NONE); + BIND_ENUM_CONSTANT(JOINT_TYPE_FIXED); + BIND_ENUM_CONSTANT(JOINT_TYPE_SLIDER); + BIND_ENUM_CONSTANT(JOINT_TYPE_HINGE); + BIND_ENUM_CONSTANT(JOINT_TYPE_SPHERICAL); + BIND_ENUM_CONSTANT(JOINT_TYPE_PLANAR); +} + +Skeleton *PhysicalBone::find_skeleton_parent(Node *p_parent) { + if (!p_parent) { + return NULL; + } + Skeleton *s = Object::cast_to(p_parent); + return s ? s : find_skeleton_parent(p_parent->get_parent()); +} + +void PhysicalBone::_reset_joint_offset_origin() { + // Clamp joint origin to bone origin + if (parent_skeleton) { + joint_offset.origin = body_offset_inverse.origin; + } +} + +void PhysicalBone::_setup_physical_bone() { + + if (!parent_skeleton) + return; + + if (parent_skeleton->get_skip_physics_tree_rebuild()) + return; + + /// Step 1 Reset bone position + + PhysicsServer::get_singleton()->bone_set_id( + get_rid(), + physical_bone_id); + + if (parent_physical_bone_id >= 0) + PhysicsServer::get_singleton()->bone_set_parent_id( + get_rid(), + parent_physical_bone_id); + + reset_to_rest_position(); + + PhysicsServer::get_singleton()->bone_set_joint_transform( + get_rid(), + get_joint_offset()); +} + +void PhysicalBone::_reload_joint() { + + if (!parent_skeleton) + return; + + if (parent_skeleton->get_skip_physics_tree_rebuild()) + return; + + /// Step 2 Set joint + + switch (get_joint_type()) { + case JOINT_TYPE_NONE: + case JOINT_TYPE_FIXED: { + PhysicsServer::get_singleton()->bone_joint_fixed_setup( + get_rid()); + + } break; + case JOINT_TYPE_SLIDER: { + PhysicsServer::get_singleton()->bone_joint_slider_setup( + get_rid()); + } break; + case JOINT_TYPE_HINGE: { + PhysicsServer::get_singleton()->bone_joint_hinge_setup( + get_rid()); + } break; + case JOINT_TYPE_SPHERICAL: { + PhysicsServer::get_singleton()->bone_joint_spherical_setup( + get_rid()); + } break; + case JOINT_TYPE_PLANAR: { + PhysicsServer::get_singleton()->bone_joint_planar_setup( + get_rid()); + } break; + } + + /// Step 3 Set joint limits and motors + + switch (get_joint_type()) { + case JOINT_TYPE_NONE: + return; // Stop here + case JOINT_TYPE_FIXED: { } break; case JOINT_TYPE_SLIDER: { - joint = PhysicsServer::get_singleton()->joint_create_slider(body_a->get_rid(), local_a, get_rid(), joint_offset); - const SliderJointData *sjd(static_cast(joint_data)); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER, sjd->linear_limit_upper); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_LOWER, sjd->linear_limit_lower); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS, sjd->linear_limit_softness); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION, sjd->linear_limit_restitution); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_DAMPING, sjd->linear_limit_restitution); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_UPPER, sjd->angular_limit_upper); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_LOWER, sjd->angular_limit_lower); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, sjd->angular_limit_softness); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, sjd->angular_limit_softness); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING, sjd->angular_limit_damping); + const PhysicalBone::HingeJointData *j = + static_cast( + get_joint_data()); + + PhysicsServer::get_singleton()->bone_set_joint_limit_active( + get_rid(), + j->limit_active); + + if (j->limit_active) { + PhysicsServer::get_singleton()->bone_set_joint_lower_limit( + get_rid(), + j->lower_limit); + + PhysicsServer::get_singleton()->bone_set_joint_upper_limit( + get_rid(), + j->upper_limit); + } + + PhysicsServer::get_singleton()->bone_set_motor_enabled(get_rid(), j->motor_is_enabled); + + if (j->motor_is_enabled) { + PhysicsServer::get_singleton()->bone_set_velocity_target(get_rid(), Vector3(j->motor_velocity_target, 0, 0)); + PhysicsServer::get_singleton()->bone_set_position_target(get_rid(), j->motor_position_target); + PhysicsServer::get_singleton()->bone_set_max_motor_impulse(get_rid(), j->motor_max_impulse); + PhysicsServer::get_singleton()->bone_set_error_reduction_parameter(get_rid(), j->motor_error_reduction_parameter); + PhysicsServer::get_singleton()->bone_set_spring_constant(get_rid(), j->motor_spring_constant); + PhysicsServer::get_singleton()->bone_set_damping_constant(get_rid(), j->motor_damping_constant); + PhysicsServer::get_singleton()->bone_set_maximum_error(get_rid(), j->motor_maximum_error); + } + + } break; + case JOINT_TYPE_HINGE: { + + const PhysicalBone::SliderJointData *j = + static_cast( + get_joint_data()); + + PhysicsServer::get_singleton()->bone_set_joint_limit_active( + get_rid(), + j->limit_active); + + if (j->limit_active) { + PhysicsServer::get_singleton()->bone_set_joint_lower_limit( + get_rid(), + j->lower_limit); + + PhysicsServer::get_singleton()->bone_set_joint_upper_limit( + get_rid(), + j->upper_limit); + } + + PhysicsServer::get_singleton()->bone_set_motor_enabled(get_rid(), j->motor_is_enabled); + + if (j->motor_is_enabled) { + PhysicsServer::get_singleton()->bone_set_velocity_target(get_rid(), Vector3(j->motor_velocity_target, 0, 0)); + PhysicsServer::get_singleton()->bone_set_position_target(get_rid(), j->motor_position_target); + PhysicsServer::get_singleton()->bone_set_max_motor_impulse(get_rid(), j->motor_max_impulse); + PhysicsServer::get_singleton()->bone_set_error_reduction_parameter(get_rid(), j->motor_error_reduction_parameter); + PhysicsServer::get_singleton()->bone_set_spring_constant(get_rid(), j->motor_spring_constant); + PhysicsServer::get_singleton()->bone_set_damping_constant(get_rid(), j->motor_damping_constant); + PhysicsServer::get_singleton()->bone_set_maximum_error(get_rid(), j->motor_maximum_error); + } } break; - case JOINT_TYPE_6DOF: { - - joint = PhysicsServer::get_singleton()->joint_create_generic_6dof(body_a->get_rid(), local_a, get_rid(), joint_offset); - const SixDOFJointData *g6dofjd(static_cast(joint_data)); - for (int axis = 0; axis < 3; ++axis) { - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, g6dofjd->axis_data[axis].linear_limit_enabled); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_UPPER_LIMIT, g6dofjd->axis_data[axis].linear_limit_upper); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT, g6dofjd->axis_data[axis].linear_limit_lower); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, g6dofjd->axis_data[axis].linear_limit_softness); - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, g6dofjd->axis_data[axis].linear_spring_enabled); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, g6dofjd->axis_data[axis].linear_spring_stiffness); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING, g6dofjd->axis_data[axis].linear_spring_damping); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, g6dofjd->axis_data[axis].linear_equilibrium_point); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_RESTITUTION, g6dofjd->axis_data[axis].linear_restitution); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING, g6dofjd->axis_data[axis].linear_damping); - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, g6dofjd->axis_data[axis].angular_limit_enabled); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT, g6dofjd->axis_data[axis].angular_limit_upper); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT, g6dofjd->axis_data[axis].angular_limit_lower); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS, g6dofjd->axis_data[axis].angular_limit_softness); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION, g6dofjd->axis_data[axis].angular_restitution); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_DAMPING, g6dofjd->axis_data[axis].angular_damping); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_ERP, g6dofjd->axis_data[axis].erp); - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, g6dofjd->axis_data[axis].angular_spring_enabled); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, g6dofjd->axis_data[axis].angular_spring_stiffness); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, g6dofjd->axis_data[axis].angular_spring_damping); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, g6dofjd->axis_data[axis].angular_equilibrium_point); + case JOINT_TYPE_SPHERICAL: { + + const PhysicalBone::SphericalJointData *j = + static_cast( + get_joint_data()); + + PhysicsServer::get_singleton()->bone_set_motor_enabled(get_rid(), j->motor_is_enabled); + + if (j->motor_is_enabled) { + PhysicsServer::get_singleton()->bone_set_velocity_target(get_rid(), j->motor_velocity_target); + PhysicsServer::get_singleton()->bone_set_rotation_target(get_rid(), Basis(j->motor_rotation_target * Math_PI / 180.)); + PhysicsServer::get_singleton()->bone_set_max_motor_impulse(get_rid(), j->motor_max_impulse); + PhysicsServer::get_singleton()->bone_set_error_reduction_parameter(get_rid(), j->motor_error_reduction_parameter); + PhysicsServer::get_singleton()->bone_set_spring_constant(get_rid(), j->motor_spring_constant); + PhysicsServer::get_singleton()->bone_set_damping_constant(get_rid(), j->motor_damping_constant); + PhysicsServer::get_singleton()->bone_set_maximum_error(get_rid(), j->motor_maximum_error); } } break; - case JOINT_TYPE_NONE: { + case JOINT_TYPE_PLANAR: { } break; } } -void PhysicalBone::_on_bone_parent_changed() { - _reload_joint(); -} - void PhysicalBone::_set_gizmo_move_joint(bool p_move_joint) { #ifdef TOOLS_ENABLED gizmo_move_joint = p_move_joint; @@ -2417,6 +2312,16 @@ Skeleton *PhysicalBone::find_skeleton_parent() { return find_skeleton_parent(this); } +void PhysicalBone::set_disable_parent_collision(bool p_col) { + disable_parent_collision = p_col; + + PhysicsServer::get_singleton()->bone_set_disable_parent_collision(get_rid(), disable_parent_collision); +} + +bool PhysicalBone::get_disable_parent_collision() const { + return disable_parent_collision; +} + void PhysicalBone::set_joint_type(JointType p_joint_type) { if (p_joint_type == get_joint_type()) @@ -2425,26 +2330,28 @@ void PhysicalBone::set_joint_type(JointType p_joint_type) { if (joint_data) memdelete(joint_data); joint_data = NULL; + switch (p_joint_type) { - case JOINT_TYPE_PIN: - joint_data = memnew(PinJointData); + case JOINT_TYPE_FIXED: + joint_data = memnew(FixedJointData); break; - case JOINT_TYPE_CONE: - joint_data = memnew(ConeJointData); + case JOINT_TYPE_SLIDER: + joint_data = memnew(SliderJointData); break; case JOINT_TYPE_HINGE: joint_data = memnew(HingeJointData); break; - case JOINT_TYPE_SLIDER: - joint_data = memnew(SliderJointData); + case JOINT_TYPE_SPHERICAL: + joint_data = memnew(SphericalJointData); break; - case JOINT_TYPE_6DOF: - joint_data = memnew(SixDOFJointData); + case JOINT_TYPE_PLANAR: + joint_data = memnew(PlanarJointData); break; case JOINT_TYPE_NONE: break; } + _setup_physical_bone(); _reload_joint(); #ifdef TOOLS_ENABLED @@ -2461,11 +2368,9 @@ PhysicalBone::JointType PhysicalBone::get_joint_type() const { void PhysicalBone::set_joint_offset(const Transform &p_offset) { joint_offset = p_offset; - _fix_joint_offset(); + _reset_joint_offset_origin(); - set_ignore_transform_notification(true); reset_to_rest_position(); - set_ignore_transform_notification(false); #ifdef TOOLS_ENABLED if (get_gizmo().is_valid()) @@ -2479,13 +2384,14 @@ const Transform &PhysicalBone::get_body_offset() const { void PhysicalBone::set_body_offset(const Transform &p_offset) { body_offset = p_offset; - body_offset_inverse = body_offset.affine_inverse(); - _fix_joint_offset(); + if (-1 != bone_id) + body_offset.basis = parent_skeleton->get_bone_global_pose(bone_id).basis; - set_ignore_transform_notification(true); + body_offset_inverse = body_offset.affine_inverse(); + + _reset_joint_offset_origin(); reset_to_rest_position(); - set_ignore_transform_notification(false); #ifdef TOOLS_ENABLED if (get_gizmo().is_valid()) @@ -2497,34 +2403,20 @@ const Transform &PhysicalBone::get_joint_offset() const { return joint_offset; } -void PhysicalBone::set_static_body(bool p_static) { - - static_body = p_static; - - set_as_toplevel(!static_body); - - _reset_physics_simulation_state(); -} - -bool PhysicalBone::is_static_body() { - return static_body; -} - -void PhysicalBone::set_simulate_physics(bool p_simulate) { - if (simulate_physics == p_simulate) { - return; +void PhysicalBone::reset_physics_simulation_state() { + if (parent_skeleton && parent_skeleton->get_active_physics()) { + _start_physics_simulation(); + } else { + _stop_physics_simulation(); } - - simulate_physics = p_simulate; - _reset_physics_simulation_state(); } -bool PhysicalBone::get_simulate_physics() { - return simulate_physics; +bool PhysicalBone::is_simulating_physics() { + return _internal_simulate_physics; } -bool PhysicalBone::is_simulating_physics() { - return _internal_simulate_physics && !_internal_static_body; +void PhysicalBone::set_bone_id(int p_bone_id) { + set_bone_name(parent_skeleton->get_bone_name(p_bone_id)); } void PhysicalBone::set_bone_name(const String &p_name) { @@ -2541,26 +2433,27 @@ const String &PhysicalBone::get_bone_name() const { return bone_name; } -void PhysicalBone::set_mass(real_t p_mass) { +void PhysicalBone::set_link_mass(real_t p_mass) { ERR_FAIL_COND(p_mass <= 0); - mass = p_mass; - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_MASS, mass); + link_mass = p_mass; + + _update_link_mass(); } -real_t PhysicalBone::get_mass() const { +real_t PhysicalBone::get_link_mass() const { - return mass; + return link_mass; } void PhysicalBone::set_weight(real_t p_weight) { - set_mass(p_weight / real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8))); + set_link_mass(p_weight / real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8))); } real_t PhysicalBone::get_weight() const { - return mass * real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8)); + return link_mass * real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8)); } void PhysicalBone::set_friction(real_t p_friction) { @@ -2568,7 +2461,7 @@ void PhysicalBone::set_friction(real_t p_friction) { ERR_FAIL_COND(p_friction < 0 || p_friction > 1); friction = p_friction; - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, friction); + PhysicsServer::get_singleton()->bone_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, friction); } real_t PhysicalBone::get_friction() const { @@ -2581,7 +2474,7 @@ void PhysicalBone::set_bounce(real_t p_bounce) { ERR_FAIL_COND(p_bounce < 0 || p_bounce > 1); bounce = p_bounce; - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, bounce); + PhysicsServer::get_singleton()->bone_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, bounce); } real_t PhysicalBone::get_bounce() const { @@ -2589,46 +2482,168 @@ real_t PhysicalBone::get_bounce() const { return bounce; } -void PhysicalBone::set_gravity_scale(real_t p_gravity_scale) { +void PhysicalBone::set_contact_monitor(bool p_enabled) { - gravity_scale = p_gravity_scale; - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_GRAVITY_SCALE, gravity_scale); + if (p_enabled == is_contact_monitor_enabled()) + return; + + if (!p_enabled) { + + if (contact_monitor->locked) { + ERR_EXPLAIN("Can't disable contact monitoring during in/out callback. Use call_deferred(\"set_contact_monitor\",false) instead"); + } + ERR_FAIL_COND(contact_monitor->locked); + + for (Map::Element *E = contact_monitor->body_map.front(); E; E = E->next()) { + + //clean up mess + Object *obj = ObjectDB::get_instance(E->key()); + Node *node = Object::cast_to(obj); + + if (node) { + + node->disconnect(SceneStringNames::get_singleton()->tree_entered, this, SceneStringNames::get_singleton()->_body_enter_tree); + node->disconnect(SceneStringNames::get_singleton()->tree_exiting, this, SceneStringNames::get_singleton()->_body_exit_tree); + } + } + + memdelete(contact_monitor); + contact_monitor = NULL; + } else { + + contact_monitor = memnew(ContactMonitor); + contact_monitor->locked = false; + } } -real_t PhysicalBone::get_gravity_scale() const { +bool PhysicalBone::is_contact_monitor_enabled() const { - return gravity_scale; + return contact_monitor != NULL; +} + +void PhysicalBone::set_max_contacts_reported(int p_amount) { + + max_contacts_reported = p_amount; + PhysicsServer::get_singleton()->bone_set_max_contacts_reported(get_rid(), p_amount); +} + +int PhysicalBone::get_max_contacts_reported() const { + + return max_contacts_reported; +} + +Array PhysicalBone::get_colliding_bodies() const { + + ERR_FAIL_COND_V(!contact_monitor, Array()); + + Array ret; + ret.resize(contact_monitor->body_map.size()); + int idx = 0; + for (const Map::Element *E = contact_monitor->body_map.front(); E; E = E->next()) { + Object *obj = ObjectDB::get_instance(E->key()); + if (!obj) { + ret.resize(ret.size() - 1); //ops + } else { + ret[idx++] = obj; + } + } + + return ret; +} + +void PhysicalBone::motor_set_active(bool p_active) { + + PhysicsServer::get_singleton()->bone_set_motor_enabled(get_rid(), p_active); +} + +void PhysicalBone::motor_set_position_target(real_t p_position) { + PhysicsServer::get_singleton()->bone_set_position_target(get_rid(), p_position); +} + +void PhysicalBone::motor_set_rotation_target(Vector3 p_rotation) { + PhysicsServer::get_singleton()->bone_set_rotation_target(get_rid(), Basis(p_rotation * Math_PI / 180.)); +} + +void PhysicalBone::motor_set_rotation_target_basis(Basis p_rotation) { + PhysicsServer::get_singleton()->bone_set_rotation_target(get_rid(), p_rotation); +} + +void PhysicalBone::motor_set_velocity(Vector3 p_velocity) { + PhysicsServer::get_singleton()->bone_set_velocity_target(get_rid(), p_velocity); +} + +void PhysicalBone::motor_set_max_impulse(real_t p_impulse) { + PhysicsServer::get_singleton()->bone_set_max_motor_impulse(get_rid(), p_impulse); +} + +void PhysicalBone::motor_set_error_reduction_parameter(real_t p_erp) { + PhysicsServer::get_singleton()->bone_set_error_reduction_parameter(get_rid(), p_erp); +} + +void PhysicalBone::motor_set_spring_constant(real_t p_sk) { + PhysicsServer::get_singleton()->bone_set_spring_constant(get_rid(), p_sk); +} + +void PhysicalBone::motor_set_damping_constant(real_t p_dk) { + PhysicsServer::get_singleton()->bone_set_damping_constant(get_rid(), p_dk); +} + +void PhysicalBone::motor_set_maximum_error(real_t p_me) { + PhysicsServer::get_singleton()->bone_set_maximum_error(get_rid(), p_me); +} + +Vector3 PhysicalBone::get_joint_force() { + + return PhysicsServer::get_singleton()->bone_joint_get_force(get_rid()); +} + +Vector3 PhysicalBone::get_joint_torque() { + + return PhysicsServer::get_singleton()->bone_joint_get_torque(get_rid()); } PhysicalBone::PhysicalBone() : - PhysicsBody(PhysicsServer::BODY_MODE_STATIC), + CollisionObject( + PhysicsServer::get_singleton()->bone_create(), + COLLISION_OBJECT_TYPE_BONE), #ifdef TOOLS_ENABLED gizmo_move_joint(false), #endif + contact_monitor(NULL), + max_contacts_reported(0), joint_data(NULL), + disable_parent_collision(true), parent_skeleton(NULL), - static_body(false), - _internal_static_body(false), - simulate_physics(false), _internal_simulate_physics(false), bone_id(-1), + physical_bone_id(-1), + parent_physical_bone_id(-1), bone_name(""), bounce(0), - mass(1), + link_mass(1), friction(1), gravity_scale(1) { - set_static_body(static_body); - _reset_physics_simulation_state(); + _update_link_mass(); } PhysicalBone::~PhysicalBone() { - if (joint_data) + if (joint_data) { memdelete(joint_data); + joint_data = NULL; + } + + if (contact_monitor) + memdelete(contact_monitor); } void PhysicalBone::update_bone_id() { if (!parent_skeleton) { + + bone_id = -1; + physical_bone_id = -1; + parent_physical_bone_id = -1; + return; } @@ -2643,16 +2658,19 @@ void PhysicalBone::update_bone_id() { bone_id = new_bone_id; - parent_skeleton->bind_physical_bone_to_bone(bone_id, this); + // These are managed by the skeleton in the "_rebuild_physical_tree" + physical_bone_id = -1; + parent_physical_bone_id = -1; - _fix_joint_offset(); - _internal_static_body = !static_body; // Force staticness reset - _reset_staticness_state(); + _reset_joint_offset_origin(); + + parent_skeleton->bind_physical_bone_to_bone(bone_id, this); } } void PhysicalBone::update_offset() { #ifdef TOOLS_ENABLED + if (parent_skeleton) { Transform bone_transform(parent_skeleton->get_global_transform()); @@ -2671,45 +2689,28 @@ void PhysicalBone::update_offset() { void PhysicalBone::reset_to_rest_position() { if (parent_skeleton) { + set_ignore_transform_notification(true); if (-1 == bone_id) { set_global_transform(parent_skeleton->get_global_transform() * body_offset); } else { - set_global_transform(parent_skeleton->get_global_transform() * parent_skeleton->get_bone_global_pose(bone_id) * body_offset); + set_global_transform( + parent_skeleton->get_global_transform() * + parent_skeleton->get_bone_global_pose(bone_id) * + body_offset); } - } -} + set_ignore_transform_notification(false); -void PhysicalBone::_reset_physics_simulation_state() { - if (simulate_physics && !static_body) { - _start_physics_simulation(); - } else { - _stop_physics_simulation(); + PhysicsServer::get_singleton()->bone_set_transform( + get_rid(), + get_global_transform()); } - - _reset_staticness_state(); } -void PhysicalBone::_reset_staticness_state() { +void PhysicalBone::_update_link_mass() { - if (parent_skeleton && -1 != bone_id) { - if (static_body && simulate_physics) { // With this check I'm sure the position of this body is updated only when it's necessary - - if (_internal_static_body) { - return; - } - - parent_skeleton->bind_child_node_to_bone(bone_id, this); - _internal_static_body = true; - } else { - - if (!_internal_static_body) { - return; - } - - parent_skeleton->unbind_child_node_from_bone(bone_id, this); - _internal_static_body = false; - } - } + PhysicsServer::get_singleton()->bone_set_link_mass( + get_rid(), + link_mass); } void PhysicalBone::_start_physics_simulation() { @@ -2717,22 +2718,17 @@ void PhysicalBone::_start_physics_simulation() { return; } reset_to_rest_position(); - PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_RIGID); - PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); - PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); - PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); + PhysicsServer::get_singleton()->bone_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); parent_skeleton->set_bone_ignore_animation(bone_id, true); _internal_simulate_physics = true; + _update_link_mass(); } void PhysicalBone::_stop_physics_simulation() { if (!_internal_simulate_physics || !parent_skeleton) { return; } - PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_STATIC); - PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), 0); - PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), 0); - PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), NULL, ""); + PhysicsServer::get_singleton()->bone_set_force_integration_callback(get_rid(), NULL, ""); parent_skeleton->set_bone_ignore_animation(bone_id, false); _internal_simulate_physics = false; } diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index aa6030d44e40..327e0c5a7e54 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -41,12 +41,6 @@ class PhysicsBody : public CollisionObject { GDCLASS(PhysicsBody, CollisionObject); - uint32_t collision_layer; - uint32_t collision_mask; - - void _set_layers(uint32_t p_mask); - uint32_t _get_layers() const; - protected: static void _bind_methods(); void _notification(int p_what); @@ -57,22 +51,6 @@ class PhysicsBody : public CollisionObject { virtual Vector3 get_angular_velocity() const; virtual float get_inverse_mass() const; - void set_collision_layer(uint32_t p_layer); - uint32_t get_collision_layer() const; - - void set_collision_mask(uint32_t p_mask); - uint32_t get_collision_mask() const; - - void set_collision_layer_bit(int p_bit, bool p_value); - bool get_collision_layer_bit(int p_bit) const; - - void set_collision_mask_bit(int p_bit, bool p_value); - bool get_collision_mask_bit(int p_bit) const; - - Array get_collision_exceptions(); - void add_collision_exception_with(Node *p_node); //must be physicsbody - void remove_collision_exception_with(Node *p_node); - PhysicsBody(); }; @@ -369,180 +347,198 @@ class KinematicCollision : public Reference { KinematicCollision(); }; -class PhysicalBone : public PhysicsBody { +class PhysicalBone : public CollisionObject { + + GDCLASS(PhysicalBone, CollisionObject); - GDCLASS(PhysicalBone, PhysicsBody); + friend class Skeleton; public: enum JointType { JOINT_TYPE_NONE, - JOINT_TYPE_PIN, - JOINT_TYPE_CONE, - JOINT_TYPE_HINGE, + JOINT_TYPE_FIXED, JOINT_TYPE_SLIDER, - JOINT_TYPE_6DOF + JOINT_TYPE_HINGE, + JOINT_TYPE_SPHERICAL, + JOINT_TYPE_PLANAR }; struct JointData { + virtual JointType get_joint_type() { return JOINT_TYPE_NONE; } /// "j" is used to set the parameter inside the PhysicsServer - virtual bool _set(const StringName &p_name, const Variant &p_value, RID j = RID()); + virtual bool _set(const StringName &p_name, const Variant &p_value); virtual bool _get(const StringName &p_name, Variant &r_ret) const; virtual void _get_property_list(List *p_list) const; + JointData() {} + virtual ~JointData() {} }; - struct PinJointData : public JointData { - virtual JointType get_joint_type() { return JOINT_TYPE_PIN; } + struct FixedJointData : public JointData { + virtual JointType get_joint_type() { return JOINT_TYPE_FIXED; } - virtual bool _set(const StringName &p_name, const Variant &p_value, RID j = RID()); + virtual bool _set(const StringName &p_name, const Variant &p_value); virtual bool _get(const StringName &p_name, Variant &r_ret) const; virtual void _get_property_list(List *p_list) const; - real_t bias; - real_t damping; - real_t impulse_clamp; - - PinJointData() : - bias(0.3), - damping(1.), - impulse_clamp(0) {} + FixedJointData() : + JointData() {} }; - struct ConeJointData : public JointData { - virtual JointType get_joint_type() { return JOINT_TYPE_CONE; } + struct SliderJointData : public JointData { + virtual JointType get_joint_type() { return JOINT_TYPE_SLIDER; } - virtual bool _set(const StringName &p_name, const Variant &p_value, RID j = RID()); + virtual bool _set(const StringName &p_name, const Variant &p_value); virtual bool _get(const StringName &p_name, Variant &r_ret) const; virtual void _get_property_list(List *p_list) const; - real_t swing_span; - real_t twist_span; - real_t bias; - real_t softness; - real_t relaxation; - - ConeJointData() : - swing_span(Math_PI * 0.25), - twist_span(Math_PI), - bias(0.3), - softness(0.8), - relaxation(1.) {} + // Limits + bool limit_active; + real_t lower_limit; + real_t upper_limit; + + // Motors + bool motor_is_enabled; + real_t motor_velocity_target; + real_t motor_position_target; + real_t motor_max_impulse; + real_t motor_error_reduction_parameter; + real_t motor_spring_constant; + real_t motor_damping_constant; + real_t motor_maximum_error; + + SliderJointData() : + JointData(), + limit_active(true), + lower_limit(-1), + upper_limit(1), + motor_is_enabled(false), + motor_velocity_target(0), + motor_position_target(0), + motor_max_impulse(1), + motor_error_reduction_parameter(1), + motor_spring_constant(0.1), + motor_damping_constant(1), + motor_maximum_error(99999.) {} }; struct HingeJointData : public JointData { virtual JointType get_joint_type() { return JOINT_TYPE_HINGE; } - virtual bool _set(const StringName &p_name, const Variant &p_value, RID j = RID()); + virtual bool _set(const StringName &p_name, const Variant &p_value); virtual bool _get(const StringName &p_name, Variant &r_ret) const; virtual void _get_property_list(List *p_list) const; - bool angular_limit_enabled; - real_t angular_limit_upper; - real_t angular_limit_lower; - real_t angular_limit_bias; - real_t angular_limit_softness; - real_t angular_limit_relaxation; + // Limits + bool limit_active; + real_t lower_limit; + real_t upper_limit; + + // Motors + bool motor_is_enabled; + real_t motor_velocity_target; + real_t motor_position_target; + real_t motor_max_impulse; + real_t motor_error_reduction_parameter; + real_t motor_spring_constant; + real_t motor_damping_constant; + real_t motor_maximum_error; HingeJointData() : - angular_limit_enabled(false), - angular_limit_upper(Math_PI * 0.5), - angular_limit_lower(-Math_PI * 0.5), - angular_limit_bias(0.3), - angular_limit_softness(0.9), - angular_limit_relaxation(1.) {} + JointData(), + limit_active(true), + lower_limit(-90), + upper_limit(90), + motor_is_enabled(false), + motor_velocity_target(0), + motor_position_target(0), + motor_max_impulse(1), + motor_error_reduction_parameter(1), + motor_spring_constant(0.1), + motor_damping_constant(1), + motor_maximum_error(99999.) {} }; - struct SliderJointData : public JointData { - virtual JointType get_joint_type() { return JOINT_TYPE_SLIDER; } + struct SphericalJointData : public JointData { + virtual JointType get_joint_type() { return JOINT_TYPE_SPHERICAL; } - virtual bool _set(const StringName &p_name, const Variant &p_value, RID j = RID()); + virtual bool _set(const StringName &p_name, const Variant &p_value); virtual bool _get(const StringName &p_name, Variant &r_ret) const; virtual void _get_property_list(List *p_list) const; - real_t linear_limit_upper; - real_t linear_limit_lower; - real_t linear_limit_softness; - real_t linear_limit_restitution; - real_t linear_limit_damping; - real_t angular_limit_upper; - real_t angular_limit_lower; - real_t angular_limit_softness; - real_t angular_limit_restitution; - real_t angular_limit_damping; - - SliderJointData() : - linear_limit_upper(1.), - linear_limit_lower(-1.), - linear_limit_softness(1.), - linear_limit_restitution(0.7), - linear_limit_damping(1.), - angular_limit_upper(0), - angular_limit_lower(0), - angular_limit_softness(1.), - angular_limit_restitution(0.7), - angular_limit_damping(1.) {} + // Motors + bool motor_is_enabled; + Vector3 motor_velocity_target; + Vector3 motor_rotation_target; + real_t motor_max_impulse; + real_t motor_error_reduction_parameter; + real_t motor_spring_constant; + real_t motor_damping_constant; + real_t motor_maximum_error; + + SphericalJointData() : + JointData(), + motor_is_enabled(false), + motor_velocity_target(0, 0, 0), + motor_rotation_target(0, 0, 0), + motor_max_impulse(1), + motor_error_reduction_parameter(1), + motor_spring_constant(0.1), + motor_damping_constant(1), + motor_maximum_error(99999.) {} }; - struct SixDOFJointData : public JointData { - struct SixDOFAxisData { - bool linear_limit_enabled; - real_t linear_limit_upper; - real_t linear_limit_lower; - real_t linear_limit_softness; - real_t linear_restitution; - real_t linear_damping; - bool linear_spring_enabled; - real_t linear_spring_stiffness; - real_t linear_spring_damping; - real_t linear_equilibrium_point; - bool angular_limit_enabled; - real_t angular_limit_upper; - real_t angular_limit_lower; - real_t angular_limit_softness; - real_t angular_restitution; - real_t angular_damping; - real_t erp; - bool angular_spring_enabled; - real_t angular_spring_stiffness; - real_t angular_spring_damping; - real_t angular_equilibrium_point; - - SixDOFAxisData() : - linear_limit_enabled(true), - linear_limit_upper(0), - linear_limit_lower(0), - linear_limit_softness(0.7), - linear_restitution(0.5), - linear_damping(1.), - linear_spring_enabled(false), - linear_spring_stiffness(0), - linear_spring_damping(0), - linear_equilibrium_point(0), - angular_limit_enabled(true), - angular_limit_upper(0), - angular_limit_lower(0), - angular_limit_softness(0.5), - angular_restitution(0), - angular_damping(1.), - erp(0.5), - angular_spring_enabled(false), - angular_spring_stiffness(0), - angular_spring_damping(0.), - angular_equilibrium_point(0) {} - }; - - virtual JointType get_joint_type() { return JOINT_TYPE_6DOF; } - - virtual bool _set(const StringName &p_name, const Variant &p_value, RID j = RID()); + struct PlanarJointData : public JointData { + virtual JointType get_joint_type() { return JOINT_TYPE_PLANAR; } + + virtual bool _set(const StringName &p_name, const Variant &p_value); virtual bool _get(const StringName &p_name, Variant &r_ret) const; virtual void _get_property_list(List *p_list) const; - SixDOFAxisData axis_data[3]; + PlanarJointData() : + JointData() {} + }; + + // Contact monitoring stuff + struct ShapePair { + + int body_shape; + int local_shape; + bool tagged; + bool operator<(const ShapePair &p_sp) const { + if (body_shape == p_sp.body_shape) + return local_shape < p_sp.local_shape; + else + return body_shape < p_sp.body_shape; + } - SixDOFJointData() {} + ShapePair() {} + ShapePair(int p_bs, int p_ls) { + body_shape = p_bs; + local_shape = p_ls; + } + }; + + struct RigidBody_RemoveAction { + + ObjectID body_id; + ShapePair pair; + }; + + struct BodyState { + + //int rc; + bool in_tree; + VSet shapes; + }; + + struct ContactMonitor { + + bool locked; + Map body_map; }; private: @@ -551,22 +547,25 @@ class PhysicalBone : public PhysicsBody { bool gizmo_move_joint; #endif + ContactMonitor *contact_monitor; + int max_contacts_reported; + JointData *joint_data; Transform joint_offset; + bool disable_parent_collision; RID joint; Skeleton *parent_skeleton; Transform body_offset; Transform body_offset_inverse; - bool static_body; - bool _internal_static_body; - bool simulate_physics; bool _internal_simulate_physics; int bone_id; + int physical_bone_id; + int parent_physical_bone_id; String bone_name; real_t bounce; - real_t mass; + real_t link_mass; real_t friction; real_t gravity_scale; @@ -577,16 +576,21 @@ class PhysicalBone : public PhysicsBody { void _notification(int p_what); void _direct_state_changed(Object *p_state); + void _body_enter_tree(ObjectID p_id); + void _body_exit_tree(ObjectID p_id); + + void _body_inout(int p_status, ObjectID p_instance, int p_body_shape, int p_local_shape); + static void _bind_methods(); private: static Skeleton *find_skeleton_parent(Node *p_parent); - void _fix_joint_offset(); - void _reload_joint(); + void _reset_joint_offset_origin(); public: - void _on_bone_parent_changed(); + void _setup_physical_bone(); + void _reload_joint(); void _set_gizmo_move_joint(bool p_move_joint); public: @@ -598,7 +602,8 @@ class PhysicalBone : public PhysicsBody { const JointData *get_joint_data() const; Skeleton *find_skeleton_parent(); - int get_bone_id() const { return bone_id; } + void set_disable_parent_collision(bool p_col); + bool get_disable_parent_collision() const; void set_joint_type(JointType p_joint_type); JointType get_joint_type() const; @@ -612,15 +617,20 @@ class PhysicalBone : public PhysicsBody { void set_static_body(bool p_static); bool is_static_body(); - void set_simulate_physics(bool p_simulate); - bool get_simulate_physics(); + void reset_physics_simulation_state(); bool is_simulating_physics(); + void set_bone_id(int p_bode_id); + int get_bone_id() const { return bone_id; } + void set_bone_name(const String &p_name); const String &get_bone_name() const; - void set_mass(real_t p_mass); - real_t get_mass() const; + void set_is_static(bool p_static); + bool get_is_static() const; + + void set_link_mass(real_t p_mass); + real_t get_link_mass() const; void set_weight(real_t p_weight); real_t get_weight() const; @@ -631,19 +641,37 @@ class PhysicalBone : public PhysicsBody { void set_bounce(real_t p_bounce); real_t get_bounce() const; - void set_gravity_scale(real_t p_gravity_scale); - real_t get_gravity_scale() const; + void set_contact_monitor(bool p_enabled); + bool is_contact_monitor_enabled() const; + + void set_max_contacts_reported(int p_amount); + int get_max_contacts_reported() const; + + Array get_colliding_bodies() const; + + void motor_set_active(bool p_active); + void motor_set_position_target(real_t p_position); + void motor_set_rotation_target(Vector3 p_rotation); + void motor_set_rotation_target_basis(Basis p_rotation); + void motor_set_velocity(Vector3 p_velocity); + void motor_set_max_impulse(real_t p_impulse); + void motor_set_error_reduction_parameter(real_t p_erp); + void motor_set_spring_constant(real_t p_sk); + void motor_set_damping_constant(real_t p_dk); + void motor_set_maximum_error(real_t p_me); + + Vector3 get_joint_force(); + Vector3 get_joint_torque(); PhysicalBone(); - ~PhysicalBone(); + virtual ~PhysicalBone(); private: void update_bone_id(); void update_offset(); void reset_to_rest_position(); - void _reset_physics_simulation_state(); - void _reset_staticness_state(); + void _update_link_mass(); void _start_physics_simulation(); void _stop_physics_simulation(); diff --git a/scene/3d/physics_joint.cpp b/scene/3d/physics_joint.cpp index c261ed3aeb7f..fdae021037d7 100644 --- a/scene/3d/physics_joint.cpp +++ b/scene/3d/physics_joint.cpp @@ -48,8 +48,8 @@ void Joint::_update_joint(bool p_only_free) { Node *node_a = has_node(get_node_a()) ? get_node(get_node_a()) : (Node *)NULL; Node *node_b = has_node(get_node_b()) ? get_node(get_node_b()) : (Node *)NULL; - PhysicsBody *body_a = Object::cast_to(node_a); - PhysicsBody *body_b = Object::cast_to(node_b); + CollisionObject *body_a = Object::cast_to(node_a); + CollisionObject *body_b = Object::cast_to(node_b); if (!body_a && body_b) SWAP(body_a, body_b); @@ -194,7 +194,7 @@ float PinJoint::get_param(Param p_param) const { return params[p_param]; } -RID PinJoint::_configure_joint(PhysicsBody *body_a, PhysicsBody *body_b) { +RID PinJoint::_configure_joint(CollisionObject *body_a, CollisionObject *body_b) { Vector3 pinpos = get_global_transform().origin; Vector3 local_a = body_a->get_global_transform().affine_inverse().xform(pinpos); @@ -315,7 +315,7 @@ bool HingeJoint::get_flag(Flag p_flag) const { return flags[p_flag]; } -RID HingeJoint::_configure_joint(PhysicsBody *body_a, PhysicsBody *body_b) { +RID HingeJoint::_configure_joint(CollisionObject *body_a, CollisionObject *body_b) { Transform gt = get_global_transform(); Transform ainv = body_a->get_global_transform().affine_inverse(); @@ -457,7 +457,7 @@ float SliderJoint::get_param(Param p_param) const { return params[p_param]; } -RID SliderJoint::_configure_joint(PhysicsBody *body_a, PhysicsBody *body_b) { +RID SliderJoint::_configure_joint(CollisionObject *body_a, CollisionObject *body_b) { Transform gt = get_global_transform(); Transform ainv = body_a->get_global_transform().affine_inverse(); @@ -571,7 +571,7 @@ float ConeTwistJoint::get_param(Param p_param) const { return params[p_param]; } -RID ConeTwistJoint::_configure_joint(PhysicsBody *body_a, PhysicsBody *body_b) { +RID ConeTwistJoint::_configure_joint(CollisionObject *body_a, CollisionObject *body_b) { Transform gt = get_global_transform(); //Vector3 cone_twistpos = gt.origin; @@ -920,7 +920,7 @@ void Generic6DOFJoint::set_precision(int p_precision) { precision); } -RID Generic6DOFJoint::_configure_joint(PhysicsBody *body_a, PhysicsBody *body_b) { +RID Generic6DOFJoint::_configure_joint(CollisionObject *body_a, CollisionObject *body_b) { Transform gt = get_global_transform(); //Vector3 cone_twistpos = gt.origin; diff --git a/scene/3d/physics_joint.h b/scene/3d/physics_joint.h index f6df920314d2..86b8c0cb00c5 100644 --- a/scene/3d/physics_joint.h +++ b/scene/3d/physics_joint.h @@ -53,7 +53,7 @@ class Joint : public Spatial { void _notification(int p_what); - virtual RID _configure_joint(PhysicsBody *body_a, PhysicsBody *body_b) = 0; + virtual RID _configure_joint(CollisionObject *body_a, CollisionObject *body_b) = 0; static void _bind_methods(); @@ -89,7 +89,7 @@ class PinJoint : public Joint { protected: float params[3]; - virtual RID _configure_joint(PhysicsBody *body_a, PhysicsBody *body_b); + virtual RID _configure_joint(CollisionObject *body_a, CollisionObject *body_b); static void _bind_methods(); public: @@ -127,7 +127,7 @@ class HingeJoint : public Joint { protected: float params[PARAM_MAX]; bool flags[FLAG_MAX]; - virtual RID _configure_joint(PhysicsBody *body_a, PhysicsBody *body_b); + virtual RID _configure_joint(CollisionObject *body_a, CollisionObject *body_b); static void _bind_methods(); void _set_upper_limit(float p_limit); @@ -190,7 +190,7 @@ class SliderJoint : public Joint { float _get_lower_limit_angular() const; float params[PARAM_MAX]; - virtual RID _configure_joint(PhysicsBody *body_a, PhysicsBody *body_b); + virtual RID _configure_joint(CollisionObject *body_a, CollisionObject *body_b); static void _bind_methods(); public: @@ -225,7 +225,7 @@ class ConeTwistJoint : public Joint { float _get_twist_span() const; float params[PARAM_MAX]; - virtual RID _configure_joint(PhysicsBody *body_a, PhysicsBody *body_b); + virtual RID _configure_joint(CollisionObject *body_a, CollisionObject *body_b); static void _bind_methods(); public: @@ -307,7 +307,7 @@ class Generic6DOFJoint : public Joint { int precision; - virtual RID _configure_joint(PhysicsBody *body_a, PhysicsBody *body_b); + virtual RID _configure_joint(CollisionObject *body_a, CollisionObject *body_b); static void _bind_methods(); public: diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp index e192e040f2e4..7b3cd44e6952 100644 --- a/scene/3d/skeleton.cpp +++ b/scene/3d/skeleton.cpp @@ -32,6 +32,7 @@ #include "core/message_queue.h" +#include "core/engine.h" #include "core/project_settings.h" #include "scene/3d/physics_body.h" #include "scene/resources/surface_tool.h" @@ -200,13 +201,32 @@ void Skeleton::_notification(int p_what) { VS::get_singleton()->skeleton_set_world_transform(skeleton, use_bones_in_world_transform, get_global_transform()); + if (Engine::get_singleton()->is_editor_hint()) { + + add_change_receptor(this); + } + + PhysicsServer::get_singleton()->armature_set_space(physics_rid, get_world()->get_space()); + + skip_physics_tree_rebuild = true; + + } break; + case NOTIFICATION_READY: { +#ifndef _3D_DISABLED + skip_physics_tree_rebuild = false; + _rebuild_physical_tree(); + update_physics_activation(); +#endif } break; case NOTIFICATION_EXIT_WORLD: { + PhysicsServer::get_singleton()->armature_set_space(physics_rid, RID()); + } break; case NOTIFICATION_TRANSFORM_CHANGED: { VS::get_singleton()->skeleton_set_world_transform(skeleton, use_bones_in_world_transform, get_global_transform()); + } break; case NOTIFICATION_UPDATE_SKELETON: { @@ -348,6 +368,15 @@ RID Skeleton::get_skeleton() const { return skeleton; } +RID Skeleton::get_physics_rid() const { + + return physics_rid; +} + +bool Skeleton::get_skip_physics_tree_rebuild() const { + return skip_physics_tree_rebuild; +} + // skeleton creation api void Skeleton::add_bone(const String &p_name) { @@ -598,20 +627,79 @@ void Skeleton::localize_rests() { #ifndef _3D_DISABLED +void Skeleton::set_active_physics(bool p_simulate_physics) { + active_physics = p_simulate_physics; + + if (skip_physics_tree_rebuild) + return; + + update_physics_activation(); +} + +bool Skeleton::get_active_physics() const { + return active_physics; +} + +void Skeleton::set_mass(real_t p_mass) { + mass = p_mass; + PhysicsServer::get_singleton()->armature_set_param( + physics_rid, + PhysicsServer::ARMATURE_PARAM_MASS, + mass); +} + +real_t Skeleton::get_mass() { + return mass; +} + +void _physical_bones_add_remove_collision_exception(bool p_add, Node *p_node, RID p_exception) { + + for (int i = p_node->get_child_count() - 1; 0 <= i; --i) { + _physical_bones_add_remove_collision_exception(p_add, p_node->get_child(i), p_exception); + } + + CollisionObject *co = Object::cast_to(p_node); + if (co) { + if (p_add) { + PhysicsServer::get_singleton()->bone_add_collision_exception(co->get_rid(), p_exception); + } else { + PhysicsServer::get_singleton()->bone_remove_collision_exception(co->get_rid(), p_exception); + } + } +} + +void Skeleton::physical_bones_add_collision_exception(RID p_exception) { + _physical_bones_add_remove_collision_exception(true, this, p_exception); +} + +void Skeleton::physical_bones_remove_collision_exception(RID p_exception) { + _physical_bones_add_remove_collision_exception(false, this, p_exception); +} + void Skeleton::bind_physical_bone_to_bone(int p_bone, PhysicalBone *p_physical_bone) { ERR_FAIL_INDEX(p_bone, bones.size()); - ERR_FAIL_COND(bones[p_bone].physical_bone); - ERR_FAIL_COND(!p_physical_bone); + ERR_FAIL_COND(bones[p_bone].physical_bone != NULL); + ERR_FAIL_COND(p_physical_bone == NULL); + bones.write[p_bone].physical_bone = p_physical_bone; - _rebuild_physical_bones_cache(); + PhysicsServer::get_singleton()->bone_set_armature( + p_physical_bone->get_rid(), + get_physics_rid()); + + _rebuild_physical_tree(); } void Skeleton::unbind_physical_bone_from_bone(int p_bone) { + ERR_FAIL_INDEX(p_bone, bones.size()); - bones.write[p_bone].physical_bone = NULL; - _rebuild_physical_bones_cache(); + PhysicsServer::get_singleton()->bone_set_armature( + bones[p_bone].physical_bone->get_rid(), + RID()); + + bones.write[p_bone].physical_bone = NULL; + _rebuild_physical_tree(); } PhysicalBone *Skeleton::get_physical_bone(int p_bone) { @@ -635,6 +723,7 @@ PhysicalBone *Skeleton::_get_physical_bone_parent(int p_bone) { const int parent_bone = bones[p_bone].parent; if (0 > parent_bone) { + // This happen for the root bone return NULL; } @@ -646,103 +735,74 @@ PhysicalBone *Skeleton::_get_physical_bone_parent(int p_bone) { } } -void Skeleton::_rebuild_physical_bones_cache() { - const int b_size = bones.size(); - for (int i = 0; i < b_size; ++i) { - PhysicalBone *parent_pb = _get_physical_bone_parent(i); - if (parent_pb != bones[i].physical_bone) { - bones.write[i].cache_parent_physical_bone = parent_pb; - if (bones[i].physical_bone) - bones[i].physical_bone->_on_bone_parent_changed(); +void Skeleton::_rebuild_physical_tree() { + + if (skip_physics_tree_rebuild) + return; + + const int bone_count = bones.size(); + + // Count all physical bones, and reset its parent + int physical_bone_count(0); + for (int i = 0; i < bone_count; ++i) { + if (bones[i].physical_bone) { + ++physical_bone_count; + bones.write[i].cache_parent_physical_bone = NULL; } } -} -void _pb_stop_simulation(Node *p_node) { + // Set physical bones id + int physical_bone_id(0); + for (int i = 0; i < bone_count; ++i) { - for (int i = p_node->get_child_count() - 1; 0 <= i; --i) { - _pb_stop_simulation(p_node->get_child(i)); - } + if (bones[i].physical_bone) { - PhysicalBone *pb = Object::cast_to(p_node); - if (pb) { - pb->set_simulate_physics(false); - pb->set_static_body(false); + bones[i].physical_bone->physical_bone_id = physical_bone_id; + bones[i].physical_bone->reset_to_rest_position(); + physical_bone_id++; + } } -} -void Skeleton::physical_bones_stop_simulation() { - _pb_stop_simulation(this); -} + PhysicsServer::get_singleton()->armature_set_bone_count( + physics_rid, + physical_bone_count); -void _pb_start_simulation(const Skeleton *p_skeleton, Node *p_node, const Vector &p_sim_bones) { + for (int i = 0; i < bone_count; ++i) { - for (int i = p_node->get_child_count() - 1; 0 <= i; --i) { - _pb_start_simulation(p_skeleton, p_node->get_child(i), p_sim_bones); - } + if (bones[i].physical_bone) { - PhysicalBone *pb = Object::cast_to(p_node); - if (pb) { - bool sim = false; - for (int i = p_sim_bones.size() - 1; 0 <= i; --i) { - if (p_sim_bones[i] == pb->get_bone_id() || p_skeleton->is_bone_parent_of(pb->get_bone_id(), p_sim_bones[i])) { - sim = true; - break; - } - } + PhysicalBone *parent_pb = _get_physical_bone_parent(i); + bones.write[i].cache_parent_physical_bone = parent_pb; - pb->set_simulate_physics(true); - if (sim) { - pb->set_static_body(false); - } else { - pb->set_static_body(true); + if (parent_pb) + bones[i].physical_bone->parent_physical_bone_id = + parent_pb->physical_bone_id; + else + bones[i].physical_bone->parent_physical_bone_id = -1; + + bones[i].physical_bone->_setup_physical_bone(); } } -} - -void Skeleton::physical_bones_start_simulation_on(const Array &p_bones) { - Vector sim_bones; - if (p_bones.size() <= 0) { - sim_bones.push_back(0); // if no bones is specified, activate ragdoll on full body - } else { - sim_bones.resize(p_bones.size()); - int c = 0; - for (int i = sim_bones.size() - 1; 0 <= i; --i) { - if (Variant::STRING == p_bones.get(i).get_type()) { - int bone_id = find_bone(p_bones.get(i)); - if (bone_id != -1) - sim_bones.write[c++] = bone_id; - } + for (int i = 0; i < bone_count; ++i) { + if (bones[i].physical_bone) { + bones[i].physical_bone->_reload_joint(); } - sim_bones.resize(c); } - - _pb_start_simulation(this, this, sim_bones); } -void _physical_bones_add_remove_collision_exception(bool p_add, Node *p_node, RID p_exception) { +void Skeleton::update_physics_activation() { - for (int i = p_node->get_child_count() - 1; 0 <= i; --i) { - _physical_bones_add_remove_collision_exception(p_add, p_node->get_child(i), p_exception); - } + PhysicsServer::get_singleton()->armature_set_active(physics_rid, active_physics); - CollisionObject *co = Object::cast_to(p_node); - if (co) { - if (p_add) { - PhysicsServer::get_singleton()->body_add_collision_exception(co->get_rid(), p_exception); - } else { - PhysicsServer::get_singleton()->body_remove_collision_exception(co->get_rid(), p_exception); - } - } -} + for (int i = 0; i < get_child_count(); ++i) { -void Skeleton::physical_bones_add_collision_exception(RID p_exception) { - _physical_bones_add_remove_collision_exception(true, this, p_exception); -} + PhysicalBone *pb = Object::cast_to(get_child(i)); + if (!pb) + continue; -void Skeleton::physical_bones_remove_collision_exception(RID p_exception) { - _physical_bones_add_remove_collision_exception(false, this, p_exception); + pb->reset_physics_simulation_state(); + } } #endif // _3D_DISABLED @@ -798,16 +858,23 @@ void Skeleton::_bind_methods() { ClassDB::bind_method(D_METHOD("set_use_bones_in_world_transform", "enable"), &Skeleton::set_use_bones_in_world_transform); ClassDB::bind_method(D_METHOD("is_using_bones_in_world_transform"), &Skeleton::is_using_bones_in_world_transform); + ClassDB::bind_method(D_METHOD("set_bone_ignore_animation", "bone", "ignore"), &Skeleton::set_bone_ignore_animation); + #ifndef _3D_DISABLED - ClassDB::bind_method(D_METHOD("physical_bones_stop_simulation"), &Skeleton::physical_bones_stop_simulation); - ClassDB::bind_method(D_METHOD("physical_bones_start_simulation", "bones"), &Skeleton::physical_bones_start_simulation_on, DEFVAL(Array())); + ClassDB::bind_method(D_METHOD("set_active_physics", "active"), &Skeleton::set_active_physics); + ClassDB::bind_method(D_METHOD("get_active_physics"), &Skeleton::get_active_physics); + + ClassDB::bind_method(D_METHOD("set_mass", "mass"), &Skeleton::set_mass); + ClassDB::bind_method(D_METHOD("get_mass"), &Skeleton::get_mass); + ClassDB::bind_method(D_METHOD("physical_bones_add_collision_exception", "exception"), &Skeleton::physical_bones_add_collision_exception); ClassDB::bind_method(D_METHOD("physical_bones_remove_collision_exception", "exception"), &Skeleton::physical_bones_remove_collision_exception); -#endif // _3D_DISABLED + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "active_physics"), "set_active_physics", "get_active_physics"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "mass"), "set_mass", "get_mass"); - ClassDB::bind_method(D_METHOD("set_bone_ignore_animation", "bone", "ignore"), &Skeleton::set_bone_ignore_animation); +#endif // _3D_DISABLED ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bones_in_world_transform"), "set_use_bones_in_world_transform", "is_using_bones_in_world_transform"); BIND_CONSTANT(NOTIFICATION_UPDATE_SKELETON); @@ -821,8 +888,15 @@ Skeleton::Skeleton() { skeleton = VisualServer::get_singleton()->skeleton_create(); set_notify_transform(true); use_bones_in_world_transform = false; + + physics_rid = PhysicsServer::get_singleton()->armature_create(); + active_physics = false; + mass = 1.f; + + skip_physics_tree_rebuild = false; } Skeleton::~Skeleton() { VisualServer::get_singleton()->free(skeleton); + PhysicsServer::get_singleton()->free(physics_rid); } diff --git a/scene/3d/skeleton.h b/scene/3d/skeleton.h index 5f43b3c6c3b6..5e35446413e0 100644 --- a/scene/3d/skeleton.h +++ b/scene/3d/skeleton.h @@ -97,6 +97,12 @@ class Skeleton : public Spatial { bool process_order_dirty; RID skeleton; + RID physics_rid; + + bool skip_physics_tree_rebuild; + + bool active_physics; + real_t mass; void _make_dirty(); bool dirty; @@ -132,6 +138,9 @@ class Skeleton : public Spatial { }; RID get_skeleton() const; + RID get_physics_rid() const; + + bool get_skip_physics_tree_rebuild() const; // skeleton creation api void add_bone(const String &p_name); @@ -184,8 +193,17 @@ class Skeleton : public Spatial { bool is_using_bones_in_world_transform() const; #ifndef _3D_DISABLED - // Physical bone API + void set_active_physics(bool p_simulate_physics); + bool get_active_physics() const; + + void set_mass(real_t p_mass); + real_t get_mass(); + + void physical_bones_add_collision_exception(RID p_exception); + void physical_bones_remove_collision_exception(RID p_exception); + + // Physical bone APIs void bind_physical_bone_to_bone(int p_bone, PhysicalBone *p_physical_bone); void unbind_physical_bone_from_bone(int p_bone); @@ -195,13 +213,17 @@ class Skeleton : public Spatial { private: /// This is a slow API os it's cached PhysicalBone *_get_physical_bone_parent(int p_bone); - void _rebuild_physical_bones_cache(); -public: - void physical_bones_stop_simulation(); - void physical_bones_start_simulation_on(const Array &p_bones); - void physical_bones_add_collision_exception(RID p_exception); - void physical_bones_remove_collision_exception(RID p_exception); + /// This API rebuild the physical tree. + /// This mean that takes all the physical bones assigned and + /// initialize the structure, the bones and their joint. + /// Every time the structure of the armature change this function + /// must be called. + /// In case you need to skip this is possible to set skip_physics_tree_rebuild = true + void _rebuild_physical_tree(); + + void update_physics_activation(); + #endif // _3D_DISABLED public: diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h index b593e9b5f1b6..8220e109fd75 100644 --- a/servers/physics/physics_server_sw.h +++ b/servers/physics/physics_server_sw.h @@ -242,6 +242,122 @@ class PhysicsServerSW : public PhysicsServer { // this function only works on physics process, errors and returns null otherwise virtual PhysicsDirectBodyState *body_get_direct_state(RID p_body); + /* ARMATURE */ + + virtual RID armature_create() { return RID(); } + + virtual void armature_set_bone_count(RID p_armature, int p_count) {} + virtual int armature_get_bone_count(RID p_armature) const { return 0; } + + virtual void armature_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) {} + + virtual void armature_set_space(RID p_body, RID p_space) {} + virtual RID armature_get_space(RID p_body) const { return RID(); } + + virtual void armature_set_active(RID p_body, bool p_active) {} + + virtual void armature_set_param(RID p_body, ArmatureParameter p_param, float p_value) {} + virtual float armature_get_param(RID p_body, ArmatureParameter p_param) const { return 0; } + + /* BONE */ + + virtual RID bone_create() { return RID(); } + + virtual void bone_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) {} + + virtual void bone_set_armature(RID p_body, RID p_armature) {} + virtual RID bone_get_armature(RID p_body) const { return RID(); } + + virtual void bone_set_max_contacts_reported(RID p_body, int p_contacts) {} + virtual int bone_get_max_contacts_reported(RID p_body) const { return 0; } + + virtual void bone_set_id(RID p_body, int p_link_id) {} + virtual int bone_get_id(RID p_body) const { return 0; } + + virtual void bone_set_parent_id(RID p_body, int p_id) {} + virtual int bone_get_parent_id(RID p_body) const { return 0; } + + virtual void bone_set_transform(RID p_body, const Transform &p_transform) {} + virtual Transform bone_get_transform(RID p_body) { return Transform(); } + + virtual void bone_set_joint_transform(RID p_body, const Transform &p_transform) {} + virtual Transform bone_get_joint_transform(RID p_body) { return Transform(); } + + virtual void bone_add_shape(RID p_body, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false) {} + virtual void bone_set_shape(RID p_body, int p_shape_idx, RID p_shape) {} + virtual void bone_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform) {} + + virtual int bone_get_shape_count(RID p_body) const { return 0; } + virtual RID bone_get_shape(RID p_body, int p_shape_idx) const { return RID(); } + virtual Transform bone_get_shape_transform(RID p_body, int p_shape_idx) const { return Transform(); } + + virtual void bone_remove_shape(RID p_body, int p_shape_idx) {} + virtual void bone_clear_shapes(RID p_body) {} + + virtual void bone_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) {} + + virtual void bone_attach_object_instance_id(RID p_body, uint32_t p_ID) {} + virtual uint32_t bone_get_object_instance_id(RID p_body) const { return 0; } + + virtual void bone_set_disable_parent_collision(RID p_body, bool p_disable) {} + virtual bool bone_get_disable_parent_collision(RID p_body) const { return true; } + + virtual void bone_set_joint_limit_active(RID p_body, bool p_active) {} + virtual void bone_set_joint_lower_limit(RID p_body, real_t p_lower_limits) {} + virtual void bone_set_joint_upper_limit(RID p_body, real_t p_upper_limits) {} + + virtual void bone_set_collision_layer(RID p_body, uint32_t p_layer) {} + virtual uint32_t bone_get_collision_layer(RID p_body) const { return 0; } + + virtual void bone_set_collision_mask(RID p_body, uint32_t p_mask) {} + virtual uint32_t bone_get_collision_mask(RID p_body) const { return 0; } + + virtual void bone_set_link_mass(RID p_body, float p_value) {} + virtual float bone_get_link_mass(RID p_body) const { return 0; } + + virtual void bone_set_param(RID p_body, BodyParameter p_param, float p_value) {} + virtual float bone_get_param(RID p_body, BodyParameter p_param) const { return 0; } + + virtual void bone_joint_fixed_setup(RID p_body) {} + virtual void bone_joint_slider_setup(RID p_body) {} + virtual void bone_joint_hinge_setup(RID p_body) {} + virtual void bone_joint_spherical_setup(RID p_body) {} + virtual void bone_joint_planar_setup(RID p_body) {} + + virtual void bone_set_motor_enabled(RID p_body, bool p_v) {} + virtual bool bone_get_motor_enabled(RID p_body) const { return false; } + + virtual void bone_set_velocity_target(RID p_body, const Vector3 &p_v) {} + virtual Vector3 bone_get_velocity_target(RID p_body) const { return Vector3(); } + + virtual void bone_set_position_target(RID p_body, real_t p_v) {} + virtual real_t bone_get_position_target(RID p_body) const { return 0; } + + virtual void bone_set_rotation_target(RID p_body, const Basis &p_v) {} + virtual Basis bone_get_rotation_target(RID p_body) const { return Basis(); } + + virtual void bone_set_max_motor_impulse(RID p_body, real_t p_v) {} + virtual real_t bone_get_max_motor_impulse(RID p_body) const { return 0; } + + virtual void bone_set_error_reduction_parameter(RID p_body, real_t p_v) {} + virtual real_t bone_get_error_reduction_parameter(RID p_body) const { return 0; } + + virtual void bone_set_spring_constant(RID p_body, real_t p_v) {} + virtual real_t bone_get_spring_constant(RID p_body) const { return 0; } + + virtual void bone_set_damping_constant(RID p_body, real_t p_v) {} + virtual real_t bone_get_damping_constant(RID p_body) const { return 0; } + + virtual void bone_set_maximum_error(RID p_body, real_t p_v) {} + virtual real_t bone_get_maximum_error(RID p_body) const { return 0; } + + virtual void bone_add_collision_exception(RID p_body, RID p_body_b) {} + virtual void bone_remove_collision_exception(RID p_body, RID p_body_b) {} + virtual void bone_get_collision_exceptions(RID p_body, List *p_exceptions) {} + + virtual Vector3 bone_joint_get_force(RID p_body) { return Vector3(); } + virtual Vector3 bone_joint_get_torque(RID p_body) { return Vector3(); } + /* SOFT BODY */ virtual RID soft_body_create(bool p_init_sleeping = false) { return RID(); } diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp index fe8c644f0b1a..175c32128f5f 100644 --- a/servers/physics_server.cpp +++ b/servers/physics_server.cpp @@ -527,6 +527,89 @@ void PhysicsServer::_bind_methods() { ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &PhysicsServer::body_get_direct_state); + /* ARMATURE API */ + + BIND_ENUM_CONSTANT(ARMATURE_PARAM_MASS); + BIND_ENUM_CONSTANT(ARMATURE_PARAM_MAX); + + ClassDB::bind_method(D_METHOD("armature_create"), &PhysicsServer::armature_create); + ClassDB::bind_method(D_METHOD("armature_set_bone_count", "armature", "count"), &PhysicsServer::armature_set_bone_count); + ClassDB::bind_method(D_METHOD("armature_get_bone_count", "armature"), &PhysicsServer::armature_get_bone_count); + ClassDB::bind_method(D_METHOD("armature_set_force_integration_callback", "body", "receiver", "method", "udata"), &PhysicsServer::armature_set_force_integration_callback, DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("armature_set_space", "body", "space"), &PhysicsServer::armature_set_space); + ClassDB::bind_method(D_METHOD("armature_get_space", "body"), &PhysicsServer::armature_get_space); + ClassDB::bind_method(D_METHOD("armature_set_active", "body", "active"), &PhysicsServer::armature_set_active); + ClassDB::bind_method(D_METHOD("armature_set_param", "body", "param", "value"), &PhysicsServer::armature_set_param); + ClassDB::bind_method(D_METHOD("armature_get_param", "body", "param"), &PhysicsServer::armature_get_param); + + /* BONE API */ + + ClassDB::bind_method(D_METHOD("bone_create"), &PhysicsServer::bone_create); + ClassDB::bind_method(D_METHOD("bone_set_force_integration_callback", "body", "receiver", "method", "udata"), &PhysicsServer::bone_set_force_integration_callback, DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("bone_set_armature", "body", "armature"), &PhysicsServer::bone_set_armature); + ClassDB::bind_method(D_METHOD("bone_get_armature", "body"), &PhysicsServer::bone_get_armature); + ClassDB::bind_method(D_METHOD("bone_set_max_contacts_reported", "body", "amount"), &PhysicsServer::bone_set_max_contacts_reported); + ClassDB::bind_method(D_METHOD("bone_get_max_contacts_reported", "body"), &PhysicsServer::body_get_max_contacts_reported); + ClassDB::bind_method(D_METHOD("bone_set_id", "body", "id"), &PhysicsServer::bone_set_id); + ClassDB::bind_method(D_METHOD("bone_get_id", "body"), &PhysicsServer::bone_get_id); + ClassDB::bind_method(D_METHOD("bone_set_parent_id", "body", "id"), &PhysicsServer::bone_set_parent_id); + ClassDB::bind_method(D_METHOD("bone_get_parent_id", "body"), &PhysicsServer::bone_get_parent_id); + ClassDB::bind_method(D_METHOD("bone_set_transform", "body", "transform"), &PhysicsServer::bone_set_transform); + ClassDB::bind_method(D_METHOD("bone_get_transform", "body"), &PhysicsServer::bone_get_transform); + ClassDB::bind_method(D_METHOD("bone_set_joint_transform", "body", "transform"), &PhysicsServer::bone_set_joint_transform); + ClassDB::bind_method(D_METHOD("bone_get_joint_transform", "body"), &PhysicsServer::bone_get_joint_transform); + ClassDB::bind_method(D_METHOD("bone_add_shape", "body", "shape", "transform", "disabled"), &PhysicsServer::bone_add_shape, DEFVAL(Transform()), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("bone_set_shape", "body", "shape_idx", "shape"), &PhysicsServer::bone_set_shape); + ClassDB::bind_method(D_METHOD("bone_set_shape_transform", "body", "shape_idx", "transform"), &PhysicsServer::bone_set_shape_transform); + ClassDB::bind_method(D_METHOD("bone_get_shape_count", "body"), &PhysicsServer::bone_get_shape_count); + ClassDB::bind_method(D_METHOD("bone_get_shape", "body", "shape_idx"), &PhysicsServer::bone_get_shape); + ClassDB::bind_method(D_METHOD("bone_get_shape_transform", "body", "shape_idx"), &PhysicsServer::bone_get_shape_transform); + ClassDB::bind_method(D_METHOD("bone_remove_shape", "body", "shape_idx"), &PhysicsServer::bone_remove_shape); + ClassDB::bind_method(D_METHOD("bone_clear_shapes", "body"), &PhysicsServer::bone_clear_shapes); + ClassDB::bind_method(D_METHOD("bone_set_shape_disabled", "body", "shape_idx", "disabled"), &PhysicsServer::bone_set_shape_disabled); + ClassDB::bind_method(D_METHOD("bone_attach_object_instance_id", "body", "id"), &PhysicsServer::bone_attach_object_instance_id); + ClassDB::bind_method(D_METHOD("bone_get_object_instance_id", "body"), &PhysicsServer::bone_get_object_instance_id); + ClassDB::bind_method(D_METHOD("bone_set_disable_parent_collision", "body", "disable"), &PhysicsServer::bone_set_disable_parent_collision); + ClassDB::bind_method(D_METHOD("bone_get_disable_parent_collision", "body"), &PhysicsServer::bone_get_disable_parent_collision); + ClassDB::bind_method(D_METHOD("bone_set_joint_limit_active", "body", "active"), &PhysicsServer::bone_set_joint_limit_active); + ClassDB::bind_method(D_METHOD("bone_set_joint_lower_limit", "body", "lower_limits"), &PhysicsServer::bone_set_joint_lower_limit); + ClassDB::bind_method(D_METHOD("bone_set_joint_upper_limit", "body", "upper_limits"), &PhysicsServer::bone_set_joint_upper_limit); + ClassDB::bind_method(D_METHOD("bone_set_collision_layer", "body", "layer"), &PhysicsServer::bone_set_collision_layer); + ClassDB::bind_method(D_METHOD("bone_get_collision_layer", "body"), &PhysicsServer::bone_get_collision_layer); + ClassDB::bind_method(D_METHOD("bone_set_collision_mask", "body", "mask"), &PhysicsServer::bone_set_collision_mask); + ClassDB::bind_method(D_METHOD("bone_get_collision_mask", "body"), &PhysicsServer::bone_get_collision_mask); + ClassDB::bind_method(D_METHOD("bone_set_link_mass", "body", "value"), &PhysicsServer::bone_set_link_mass); + ClassDB::bind_method(D_METHOD("bone_get_link_mass", "body"), &PhysicsServer::bone_get_link_mass); + ClassDB::bind_method(D_METHOD("bone_set_param", "body", "param", "value"), &PhysicsServer::bone_set_param); + ClassDB::bind_method(D_METHOD("bone_get_param", "body", "param"), &PhysicsServer::bone_get_param); + ClassDB::bind_method(D_METHOD("bone_joint_fixed_setup", "body"), &PhysicsServer::bone_joint_fixed_setup); + ClassDB::bind_method(D_METHOD("bone_joint_slider_setup", "body"), &PhysicsServer::bone_joint_slider_setup); + ClassDB::bind_method(D_METHOD("bone_joint_hinge_setup", "body"), &PhysicsServer::bone_joint_hinge_setup); + ClassDB::bind_method(D_METHOD("bone_joint_spherical_setup", "body"), &PhysicsServer::bone_joint_spherical_setup); + ClassDB::bind_method(D_METHOD("bone_joint_planar_setup", "body"), &PhysicsServer::bone_joint_planar_setup); + ClassDB::bind_method(D_METHOD("bone_set_motor_enabled", "body", "v"), &PhysicsServer::bone_set_motor_enabled); + ClassDB::bind_method(D_METHOD("bone_get_motor_enabled", "body"), &PhysicsServer::bone_get_motor_enabled); + ClassDB::bind_method(D_METHOD("bone_set_velocity_target", "body", "v"), &PhysicsServer::bone_set_velocity_target); + ClassDB::bind_method(D_METHOD("bone_get_velocity_target", "body"), &PhysicsServer::bone_get_velocity_target); + ClassDB::bind_method(D_METHOD("bone_set_position_target", "body", "v"), &PhysicsServer::bone_set_position_target); + ClassDB::bind_method(D_METHOD("bone_get_position_target", "body"), &PhysicsServer::bone_get_position_target); + ClassDB::bind_method(D_METHOD("bone_set_rotation_target", "body", "v"), &PhysicsServer::bone_set_rotation_target); + ClassDB::bind_method(D_METHOD("bone_get_rotation_target", "body"), &PhysicsServer::bone_get_rotation_target); + ClassDB::bind_method(D_METHOD("bone_set_max_motor_impulse", "body", "v"), &PhysicsServer::bone_set_max_motor_impulse); + ClassDB::bind_method(D_METHOD("bone_get_max_motor_impulse", "body"), &PhysicsServer::bone_get_max_motor_impulse); + ClassDB::bind_method(D_METHOD("bone_set_error_reduction_parameter", "body", "v"), &PhysicsServer::bone_set_error_reduction_parameter); + ClassDB::bind_method(D_METHOD("bone_get_error_reduction_parameter", "body"), &PhysicsServer::bone_get_error_reduction_parameter); + ClassDB::bind_method(D_METHOD("bone_set_spring_constant", "body", "v"), &PhysicsServer::bone_set_spring_constant); + ClassDB::bind_method(D_METHOD("bone_get_spring_constant", "body"), &PhysicsServer::bone_get_spring_constant); + ClassDB::bind_method(D_METHOD("bone_set_damping_constant", "body", "v"), &PhysicsServer::bone_set_damping_constant); + ClassDB::bind_method(D_METHOD("bone_get_damping_constant", "body"), &PhysicsServer::bone_get_damping_constant); + ClassDB::bind_method(D_METHOD("bone_set_maximum_error", "body", "v"), &PhysicsServer::bone_set_maximum_error); + ClassDB::bind_method(D_METHOD("bone_get_maximum_error", "body"), &PhysicsServer::bone_get_maximum_error); + ClassDB::bind_method(D_METHOD("bone_add_collision_exception", "body", "body_b"), &PhysicsServer::bone_add_collision_exception); + ClassDB::bind_method(D_METHOD("bone_remove_collision_exception", "body", "body_b"), &PhysicsServer::bone_remove_collision_exception); + ClassDB::bind_method(D_METHOD("bone_joint_get_force", "body"), &PhysicsServer::bone_joint_get_force); + ClassDB::bind_method(D_METHOD("bone_joint_get_torque", "body"), &PhysicsServer::bone_joint_get_torque); + /* JOINT API */ BIND_ENUM_CONSTANT(JOINT_PIN); diff --git a/servers/physics_server.h b/servers/physics_server.h index 5e5964ca8dbf..b1bb494fb3f9 100644 --- a/servers/physics_server.h +++ b/servers/physics_server.h @@ -517,6 +517,127 @@ class PhysicsServer : public Object { virtual int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001) = 0; + /* ARMATURE */ + + virtual RID armature_create() = 0; + + virtual void armature_set_bone_count(RID p_armature, int p_count) = 0; + virtual int armature_get_bone_count(RID p_armature) const = 0; + + virtual void armature_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) = 0; + + virtual void armature_set_space(RID p_body, RID p_space) = 0; + virtual RID armature_get_space(RID p_body) const = 0; + + virtual void armature_set_active(RID p_body, bool p_active) = 0; + + enum ArmatureParameter { + ARMATURE_PARAM_MASS, + ARMATURE_PARAM_MAX, + }; + + virtual void armature_set_param(RID p_body, ArmatureParameter p_param, float p_value) = 0; + virtual float armature_get_param(RID p_body, ArmatureParameter p_param) const = 0; + + /* BONE */ + + virtual RID bone_create() = 0; + + virtual void bone_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) = 0; + + virtual void bone_set_armature(RID p_body, RID p_armature) = 0; + virtual RID bone_get_armature(RID p_body) const = 0; + + virtual void bone_set_max_contacts_reported(RID p_body, int p_contacts) = 0; + virtual int bone_get_max_contacts_reported(RID p_body) const = 0; + + virtual void bone_set_id(RID p_body, int p_id) = 0; + virtual int bone_get_id(RID p_body) const = 0; + + virtual void bone_set_parent_id(RID p_body, int p_id) = 0; + virtual int bone_get_parent_id(RID p_body) const = 0; + + virtual void bone_set_transform(RID p_body, const Transform &p_transform) = 0; + virtual Transform bone_get_transform(RID p_body) = 0; + + virtual void bone_set_joint_transform(RID p_body, const Transform &p_transform) = 0; + virtual Transform bone_get_joint_transform(RID p_body) = 0; + + virtual void bone_add_shape(RID p_body, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false) = 0; + virtual void bone_set_shape(RID p_body, int p_shape_idx, RID p_shape) = 0; + virtual void bone_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform) = 0; + + virtual int bone_get_shape_count(RID p_body) const = 0; + virtual RID bone_get_shape(RID p_body, int p_shape_idx) const = 0; + virtual Transform bone_get_shape_transform(RID p_body, int p_shape_idx) const = 0; + + virtual void bone_remove_shape(RID p_body, int p_shape_idx) = 0; + virtual void bone_clear_shapes(RID p_body) = 0; + + virtual void bone_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) = 0; + + virtual void bone_attach_object_instance_id(RID p_body, uint32_t p_id) = 0; + virtual uint32_t bone_get_object_instance_id(RID p_body) const = 0; + + virtual void bone_set_disable_parent_collision(RID p_body, bool p_disable) = 0; + virtual bool bone_get_disable_parent_collision(RID p_body) const = 0; + + virtual void bone_set_joint_limit_active(RID p_body, bool p_active) = 0; + virtual void bone_set_joint_lower_limit(RID p_body, real_t p_lower_limits) = 0; + virtual void bone_set_joint_upper_limit(RID p_body, real_t p_upper_limits) = 0; + + virtual void bone_set_collision_layer(RID p_body, uint32_t p_layer) = 0; + virtual uint32_t bone_get_collision_layer(RID p_body) const = 0; + + virtual void bone_set_collision_mask(RID p_body, uint32_t p_mask) = 0; + virtual uint32_t bone_get_collision_mask(RID p_body) const = 0; + + virtual void bone_set_link_mass(RID p_body, float p_value) = 0; + virtual float bone_get_link_mass(RID p_body) const = 0; + + virtual void bone_set_param(RID p_body, BodyParameter p_param, float p_value) = 0; + virtual float bone_get_param(RID p_body, BodyParameter p_param) const = 0; + + virtual void bone_joint_fixed_setup(RID p_body) = 0; + virtual void bone_joint_slider_setup(RID p_body) = 0; + virtual void bone_joint_hinge_setup(RID p_body) = 0; + virtual void bone_joint_spherical_setup(RID p_body) = 0; + virtual void bone_joint_planar_setup(RID p_body) = 0; + + virtual void bone_set_motor_enabled(RID p_body, bool p_v) = 0; + virtual bool bone_get_motor_enabled(RID p_body) const = 0; + + virtual void bone_set_velocity_target(RID p_body, const Vector3 &p_v) = 0; + virtual Vector3 bone_get_velocity_target(RID p_body) const = 0; + + virtual void bone_set_position_target(RID p_body, real_t p_v) = 0; + virtual real_t bone_get_position_target(RID p_body) const = 0; + + virtual void bone_set_rotation_target(RID p_body, const Basis &p_v) = 0; + virtual Basis bone_get_rotation_target(RID p_body) const = 0; + + virtual void bone_set_max_motor_impulse(RID p_body, real_t p_v) = 0; + virtual real_t bone_get_max_motor_impulse(RID p_body) const = 0; + + virtual void bone_set_error_reduction_parameter(RID p_body, real_t p_v) = 0; + virtual real_t bone_get_error_reduction_parameter(RID p_body) const = 0; + + virtual void bone_set_spring_constant(RID p_body, real_t p_v) = 0; + virtual real_t bone_get_spring_constant(RID p_body) const = 0; + + virtual void bone_set_damping_constant(RID p_body, real_t p_v) = 0; + virtual real_t bone_get_damping_constant(RID p_body) const = 0; + + virtual void bone_set_maximum_error(RID p_body, real_t p_v) = 0; + virtual real_t bone_get_maximum_error(RID p_body) const = 0; + + virtual void bone_add_collision_exception(RID p_body, RID p_body_b) = 0; + virtual void bone_remove_collision_exception(RID p_body, RID p_body_b) = 0; + virtual void bone_get_collision_exceptions(RID p_body, List *p_exceptions) = 0; + + virtual Vector3 bone_joint_get_force(RID p_body) = 0; + virtual Vector3 bone_joint_get_torque(RID p_body) = 0; + /* SOFT BODY */ virtual RID soft_body_create(bool p_init_sleeping = false) = 0; @@ -830,6 +951,7 @@ VARIANT_ENUM_CAST(PhysicsServer::BodyMode); VARIANT_ENUM_CAST(PhysicsServer::BodyParameter); VARIANT_ENUM_CAST(PhysicsServer::BodyState); VARIANT_ENUM_CAST(PhysicsServer::BodyAxis); +VARIANT_ENUM_CAST(PhysicsServer::ArmatureParameter); VARIANT_ENUM_CAST(PhysicsServer::PinJointParam); VARIANT_ENUM_CAST(PhysicsServer::JointType); VARIANT_ENUM_CAST(PhysicsServer::HingeJointParam);