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