summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/classes/KinematicCollision2D.xml103
-rw-r--r--doc/classes/KinematicCollision3D.xml75
-rw-r--r--doc/classes/PhysicsServer2D.xml12
-rw-r--r--doc/classes/PhysicsServer3D.xml13
-rw-r--r--doc/classes/PhysicsTestMotionParameters2D.xml29
-rw-r--r--doc/classes/PhysicsTestMotionParameters3D.xml32
-rw-r--r--doc/classes/PhysicsTestMotionResult2D.xml108
-rw-r--r--doc/classes/PhysicsTestMotionResult3D.xml75
-rw-r--r--doc/classes/TileMap.xml2
-rw-r--r--scene/2d/physics_body_2d.cpp83
-rw-r--r--scene/2d/physics_body_2d.h6
-rw-r--r--scene/3d/physics_body_3d.cpp126
-rw-r--r--scene/3d/physics_body_3d.h16
-rw-r--r--servers/physics_2d/physics_server_2d_sw.cpp4
-rw-r--r--servers/physics_2d/physics_server_2d_sw.h2
-rw-r--r--servers/physics_2d/physics_server_2d_wrap_mt.h4
-rw-r--r--servers/physics_2d/space_2d_sw.cpp55
-rw-r--r--servers/physics_2d/space_2d_sw.h2
-rw-r--r--servers/physics_3d/physics_server_3d_sw.cpp4
-rw-r--r--servers/physics_3d/physics_server_3d_sw.h2
-rw-r--r--servers/physics_3d/physics_server_3d_wrap_mt.h4
-rw-r--r--servers/physics_3d/space_3d_sw.cpp62
-rw-r--r--servers/physics_3d/space_3d_sw.h2
-rw-r--r--servers/physics_server_2d.cpp78
-rw-r--r--servers/physics_server_2d.h60
-rw-r--r--servers/physics_server_3d.cpp137
-rw-r--r--servers/physics_server_3d.h70
-rw-r--r--servers/register_server_types.cpp2
28 files changed, 679 insertions, 489 deletions
diff --git a/doc/classes/KinematicCollision2D.xml b/doc/classes/KinematicCollision2D.xml
index 29fc4700fd..23b01a0fc9 100644
--- a/doc/classes/KinematicCollision2D.xml
+++ b/doc/classes/KinematicCollision2D.xml
@@ -14,43 +14,74 @@
<return type="float" />
<argument index="0" name="up_direction" type="Vector2" default="Vector2(0, -1)" />
<description>
- The collision angle according to [code]up_direction[/code], which is [code]Vector2.UP[/code] by default. This value is always positive.
+ Returns the collision angle according to [code]up_direction[/code], which is [code]Vector2.UP[/code] by default. This value is always positive.
+ </description>
+ </method>
+ <method name="get_collider" qualifiers="const">
+ <return type="Object" />
+ <description>
+ Returns the colliding body's attached [Object].
+ </description>
+ </method>
+ <method name="get_collider_id" qualifiers="const">
+ <return type="int" />
+ <description>
+ Returns the unique instance ID of the colliding body's attached [Object]. See [method Object.get_instance_id].
+ </description>
+ </method>
+ <method name="get_collider_rid" qualifiers="const">
+ <return type="RID" />
+ <description>
+ Returns the colliding body's [RID] used by the [PhysicsServer2D].
+ </description>
+ </method>
+ <method name="get_collider_shape" qualifiers="const">
+ <return type="Object" />
+ <description>
+ Returns the colliding body's shape.
+ </description>
+ </method>
+ <method name="get_collider_shape_index" qualifiers="const">
+ <return type="int" />
+ <description>
+ Returns the colliding body's shape index. See [CollisionObject2D].
+ </description>
+ </method>
+ <method name="get_collider_velocity" qualifiers="const">
+ <return type="Vector2" />
+ <description>
+ Returns the colliding body's velocity.
+ </description>
+ </method>
+ <method name="get_local_shape" qualifiers="const">
+ <return type="Object" />
+ <description>
+ Returns the moving object's colliding shape.
+ </description>
+ </method>
+ <method name="get_normal" qualifiers="const">
+ <return type="Vector2" />
+ <description>
+ Returns the colliding body's shape's normal at the point of collision.
+ </description>
+ </method>
+ <method name="get_position" qualifiers="const">
+ <return type="Vector2" />
+ <description>
+ Returns the point of collision in global coordinates.
+ </description>
+ </method>
+ <method name="get_remainder" qualifiers="const">
+ <return type="Vector2" />
+ <description>
+ Returns the moving object's remaining movement vector.
+ </description>
+ </method>
+ <method name="get_travel" qualifiers="const">
+ <return type="Vector2" />
+ <description>
+ Returns the moving object's travel before collision.
</description>
</method>
</methods>
- <members>
- <member name="collider" type="Object" setter="" getter="get_collider">
- The colliding body.
- </member>
- <member name="collider_id" type="int" setter="" getter="get_collider_id" default="0">
- The colliding body's unique instance ID. See [method Object.get_instance_id].
- </member>
- <member name="collider_rid" type="RID" setter="" getter="get_collider_rid">
- The colliding body's [RID] used by the [PhysicsServer2D].
- </member>
- <member name="collider_shape" type="Object" setter="" getter="get_collider_shape">
- The colliding body's shape.
- </member>
- <member name="collider_shape_index" type="int" setter="" getter="get_collider_shape_index" default="0">
- The colliding shape's index. See [CollisionObject2D].
- </member>
- <member name="collider_velocity" type="Vector2" setter="" getter="get_collider_velocity" default="Vector2(0, 0)">
- The colliding object's velocity.
- </member>
- <member name="local_shape" type="Object" setter="" getter="get_local_shape">
- The moving object's colliding shape.
- </member>
- <member name="normal" type="Vector2" setter="" getter="get_normal" default="Vector2(0, 0)">
- The colliding body's shape's normal at the point of collision.
- </member>
- <member name="position" type="Vector2" setter="" getter="get_position" default="Vector2(0, 0)">
- The point of collision, in global coordinates.
- </member>
- <member name="remainder" type="Vector2" setter="" getter="get_remainder" default="Vector2(0, 0)">
- The moving object's remaining movement vector.
- </member>
- <member name="travel" type="Vector2" setter="" getter="get_travel" default="Vector2(0, 0)">
- The distance the moving object traveled before collision.
- </member>
- </members>
</class>
diff --git a/doc/classes/KinematicCollision3D.xml b/doc/classes/KinematicCollision3D.xml
index 3db6fe019b..372113b281 100644
--- a/doc/classes/KinematicCollision3D.xml
+++ b/doc/classes/KinematicCollision3D.xml
@@ -15,108 +15,89 @@
<argument index="0" name="collision_index" type="int" default="0" />
<argument index="1" name="up_direction" type="Vector3" default="Vector3(0, 1, 0)" />
<description>
- The collision angle according to [code]up_direction[/code], which is [code]Vector3.UP[/code] by default. This value is always positive.
+ Returns the collision angle according to [code]up_direction[/code], which is [code]Vector3.UP[/code] by default. This value is always positive.
</description>
</method>
<method name="get_collider" qualifiers="const">
<return type="Object" />
<argument index="0" name="collision_index" type="int" default="0" />
<description>
- Returns the collider by index (the latest by default).
+ Returns the colliding body's attached [Object] given a collision index (the deepest collision by default).
</description>
</method>
<method name="get_collider_id" qualifiers="const">
<return type="int" />
<argument index="0" name="collision_index" type="int" default="0" />
<description>
- Returns the collider ID by index (the latest by default).
+ Returns the unique instance ID of the colliding body's attached [Object] given a collision index (the deepest collision by default). See [method Object.get_instance_id].
</description>
</method>
<method name="get_collider_rid" qualifiers="const">
<return type="RID" />
<argument index="0" name="collision_index" type="int" default="0" />
<description>
- Returns the collider RID by index (the latest by default).
+ Returns the colliding body's [RID] used by the [PhysicsServer3D] given a collision index (the deepest collision by default).
</description>
</method>
<method name="get_collider_shape" qualifiers="const">
<return type="Object" />
<argument index="0" name="collision_index" type="int" default="0" />
<description>
- Returns the collider shape by index (the latest by default).
+ Returns the colliding body's shape given a collision index (the deepest collision by default).
</description>
</method>
<method name="get_collider_shape_index" qualifiers="const">
<return type="int" />
<argument index="0" name="collision_index" type="int" default="0" />
<description>
- Returns the collider shape index by index (the latest by default).
+ Returns the colliding body's shape index given a collision index (the deepest collision by default). See [CollisionObject3D].
</description>
</method>
<method name="get_collider_velocity" qualifiers="const">
<return type="Vector3" />
<argument index="0" name="collision_index" type="int" default="0" />
<description>
- Returns the collider velocity by index (the latest by default).
+ Returns the colliding body's velocity given a collision index (the deepest collision by default).
+ </description>
+ </method>
+ <method name="get_collision_count" qualifiers="const">
+ <return type="int" />
+ <description>
+ Returns the number of detected collisions.
</description>
</method>
<method name="get_local_shape" qualifiers="const">
<return type="Object" />
<argument index="0" name="collision_index" type="int" default="0" />
<description>
- Returns the collider velocity by index (the latest by default).
+ Returns the moving object's colliding shape given a collision index (the deepest collision by default).
</description>
</method>
<method name="get_normal" qualifiers="const">
<return type="Vector3" />
<argument index="0" name="collision_index" type="int" default="0" />
<description>
- Returns the collider normal by index (the latest by default).
+ Returns the colliding body's shape's normal at the point of collision given a collision index (the deepest collision by default).
</description>
</method>
<method name="get_position" qualifiers="const">
<return type="Vector3" />
<argument index="0" name="collision_index" type="int" default="0" />
<description>
- Returns the collider collision point by index (the latest by default).
+ Returns the point of collision in global coordinates given a collision index (the deepest collision by default).
+ </description>
+ </method>
+ <method name="get_remainder" qualifiers="const">
+ <return type="Vector3" />
+ <description>
+ Returns the moving object's remaining movement vector.
+ </description>
+ </method>
+ <method name="get_travel" qualifiers="const">
+ <return type="Vector3" />
+ <description>
+ Returns the moving object's travel before collision.
</description>
</method>
</methods>
- <members>
- <member name="collider" type="Object" setter="" getter="get_best_collider">
- The colliding body.
- </member>
- <member name="collider_id" type="int" setter="" getter="get_best_collider_id" default="0">
- The colliding body's unique instance ID. See [method Object.get_instance_id].
- </member>
- <member name="collider_rid" type="RID" setter="" getter="get_best_collider_rid">
- The colliding body's [RID] used by the [PhysicsServer3D].
- </member>
- <member name="collider_shape" type="Object" setter="" getter="get_best_collider_shape">
- The colliding body's shape.
- </member>
- <member name="collider_shape_index" type="int" setter="" getter="get_best_collider_shape_index" default="0">
- The colliding shape's index. See [CollisionObject3D].
- </member>
- <member name="collider_velocity" type="Vector3" setter="" getter="get_best_collider_velocity" default="Vector3(0, 0, 0)">
- The colliding object's velocity.
- </member>
- <member name="collision_count" type="int" setter="" getter="get_collision_count" default="0">
- </member>
- <member name="local_shape" type="Object" setter="" getter="get_best_local_shape">
- The moving object's colliding shape.
- </member>
- <member name="normal" type="Vector3" setter="" getter="get_best_normal" default="Vector3(0, 0, 0)">
- The colliding body's shape's normal at the point of collision.
- </member>
- <member name="position" type="Vector3" setter="" getter="get_best_position" default="Vector3(0, 0, 0)">
- The point of collision, in global coordinates.
- </member>
- <member name="remainder" type="Vector3" setter="" getter="get_remainder" default="Vector3(0, 0, 0)">
- The moving object's remaining movement vector.
- </member>
- <member name="travel" type="Vector3" setter="" getter="get_travel" default="Vector3(0, 0, 0)">
- The distance the moving object traveled before collision.
- </member>
- </members>
</class>
diff --git a/doc/classes/PhysicsServer2D.xml b/doc/classes/PhysicsServer2D.xml
index b5b6a7ea58..d55feff829 100644
--- a/doc/classes/PhysicsServer2D.xml
+++ b/doc/classes/PhysicsServer2D.xml
@@ -584,14 +584,10 @@
<method name="body_test_motion">
<return type="bool" />
<argument index="0" name="body" type="RID" />
- <argument index="1" name="from" type="Transform2D" />
- <argument index="2" name="motion" type="Vector2" />
- <argument index="3" name="margin" type="float" default="0.08" />
- <argument index="4" name="result" type="PhysicsTestMotionResult2D" default="null" />
- <argument index="5" name="collide_separation_ray" type="bool" default="false" />
- <argument index="6" name="exclude" type="Array" default="[]" />
- <description>
- Returns [code]true[/code] if a collision would result from moving in the given direction from a given point in space. Margin increases the size of the shapes involved in the collision detection. [PhysicsTestMotionResult2D] can be passed to return additional information in.
+ <argument index="1" name="parameters" type="PhysicsTestMotionParameters2D" />
+ <argument index="2" name="result" type="PhysicsTestMotionResult2D" default="null" />
+ <description>
+ Returns [code]true[/code] if a collision would result from moving along a motion vector from a given point in space. [PhysicsTestMotionParameters2D] is passed to set motion parameters. [PhysicsTestMotionResult2D] can be passed to return additional information.
</description>
</method>
<method name="capsule_shape_create">
diff --git a/doc/classes/PhysicsServer3D.xml b/doc/classes/PhysicsServer3D.xml
index 1d1ca54dbb..0e32d1defa 100644
--- a/doc/classes/PhysicsServer3D.xml
+++ b/doc/classes/PhysicsServer3D.xml
@@ -577,15 +577,10 @@
<method name="body_test_motion">
<return type="bool" />
<argument index="0" name="body" type="RID" />
- <argument index="1" name="from" type="Transform3D" />
- <argument index="2" name="motion" type="Vector3" />
- <argument index="3" name="margin" type="float" default="0.001" />
- <argument index="4" name="result" type="PhysicsTestMotionResult3D" default="null" />
- <argument index="5" name="collide_separation_ray" type="bool" default="false" />
- <argument index="6" name="exclude" type="Array" default="[]" />
- <argument index="7" name="max_collisions" type="int" default="1" />
- <description>
- Returns [code]true[/code] if a collision would result from moving in the given direction from a given point in space. Margin increases the size of the shapes involved in the collision detection. [PhysicsTestMotionResult3D] can be passed to return additional information in.
+ <argument index="1" name="parameters" type="PhysicsTestMotionParameters3D" />
+ <argument index="2" name="result" type="PhysicsTestMotionResult3D" default="null" />
+ <description>
+ Returns [code]true[/code] if a collision would result from moving along a motion vector from a given point in space. [PhysicsTestMotionParameters3D] is passed to set motion parameters. [PhysicsTestMotionResult3D] can be passed to return additional information.
</description>
</method>
<method name="box_shape_create">
diff --git a/doc/classes/PhysicsTestMotionParameters2D.xml b/doc/classes/PhysicsTestMotionParameters2D.xml
new file mode 100644
index 0000000000..7cea848039
--- /dev/null
+++ b/doc/classes/PhysicsTestMotionParameters2D.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="PhysicsTestMotionParameters2D" inherits="RefCounted" version="4.0">
+ <brief_description>
+ Parameters to be sent to a 2D body motion test.
+ </brief_description>
+ <description>
+ This class contains parameters used in [method PhysicsServer2D.body_test_motion].
+ </description>
+ <tutorials>
+ </tutorials>
+ <members>
+ <member name="collide_separation_ray" type="bool" setter="set_collide_separation_ray_enabled" getter="is_collide_separation_ray_enabled" default="false">
+ If set to [code]true[/code], shapes of type [constant PhysicsServer2D.SHAPE_SEPARATION_RAY] are used to detect collisions and can stop the motion. Can be useful when snapping to the ground.
+ If set to [code]false[/code], shapes of type [constant PhysicsServer2D.SHAPE_SEPARATION_RAY] are only used for separation when overlapping with other bodies. That's the main use for separation ray shapes.
+ </member>
+ <member name="exclude_bodies" type="Array" setter="set_exclude_bodies" getter="get_exclude_bodies" default="[]">
+ Optional array of body [RID] to exclude from collision.
+ </member>
+ <member name="from" type="Transform2D" setter="set_from" getter="get_from" default="Transform2D(1, 0, 0, 1, 0, 0)">
+ Transform in global space where the motion should start. Usually set to [member Node2D.global_transform] for the current body's transform.
+ </member>
+ <member name="margin" type="float" setter="set_margin" getter="get_margin" default="0.08">
+ Increases the size of the shapes involved in the collision detection.
+ </member>
+ <member name="motion" type="Vector2" setter="set_motion" getter="get_motion" default="Vector2(0, 0)">
+ Motion vector to define the length and direction of the motion to test.
+ </member>
+ </members>
+</class>
diff --git a/doc/classes/PhysicsTestMotionParameters3D.xml b/doc/classes/PhysicsTestMotionParameters3D.xml
new file mode 100644
index 0000000000..07abbb1cb1
--- /dev/null
+++ b/doc/classes/PhysicsTestMotionParameters3D.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="PhysicsTestMotionParameters3D" inherits="RefCounted" version="4.0">
+ <brief_description>
+ Parameters to be sent to a 3D body motion test.
+ </brief_description>
+ <description>
+ This class contains parameters used in [method PhysicsServer3D.body_test_motion].
+ </description>
+ <tutorials>
+ </tutorials>
+ <members>
+ <member name="collide_separation_ray" type="bool" setter="set_collide_separation_ray_enabled" getter="is_collide_separation_ray_enabled" default="false">
+ If set to [code]true[/code], shapes of type [constant PhysicsServer3D.SHAPE_SEPARATION_RAY] are used to detect collisions and can stop the motion. Can be useful when snapping to the ground.
+ If set to [code]false[/code], shapes of type [constant PhysicsServer3D.SHAPE_SEPARATION_RAY] are only used for separation when overlapping with other bodies. That's the main use for separation ray shapes.
+ </member>
+ <member name="exclude_bodies" type="Array" setter="set_exclude_bodies" getter="get_exclude_bodies" default="[]">
+ Optional array of body [RID] to exclude from collision.
+ </member>
+ <member name="from" type="Transform3D" setter="set_from" getter="get_from" default="Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)">
+ Transform in global space where the motion should start. Usually set to [member Node3D.global_transform] for the current body's transform.
+ </member>
+ <member name="margin" type="float" setter="set_margin" getter="get_margin" default="0.001">
+ Increases the size of the shapes involved in the collision detection.
+ </member>
+ <member name="max_collisions" type="int" setter="set_max_collisions" getter="get_max_collisions" default="1">
+ Maximum number of returned collisions, between [code]1[/code] and [code]32[/code]. Always returns the deepest detected collisions.
+ </member>
+ <member name="motion" type="Vector3" setter="set_motion" getter="get_motion" default="Vector3(0, 0, 0)">
+ Motion vector to define the length and direction of the motion to test.
+ </member>
+ </members>
+</class>
diff --git a/doc/classes/PhysicsTestMotionResult2D.xml b/doc/classes/PhysicsTestMotionResult2D.xml
index 8d594af673..355365cf25 100644
--- a/doc/classes/PhysicsTestMotionResult2D.xml
+++ b/doc/classes/PhysicsTestMotionResult2D.xml
@@ -1,35 +1,91 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="PhysicsTestMotionResult2D" inherits="RefCounted" version="4.0">
<brief_description>
+ Result from a 2D body motion test.
</brief_description>
<description>
+ This class contains the motion and collision result from [method PhysicsServer2D.body_test_motion].
</description>
<tutorials>
</tutorials>
- <members>
- <member name="collider" type="Object" setter="" getter="get_collider">
- </member>
- <member name="collider_id" type="int" setter="" getter="get_collider_id" default="0">
- </member>
- <member name="collider_rid" type="RID" setter="" getter="get_collider_rid">
- </member>
- <member name="collider_shape" type="int" setter="" getter="get_collider_shape" default="0">
- </member>
- <member name="collider_velocity" type="Vector2" setter="" getter="get_collider_velocity" default="Vector2(0, 0)">
- </member>
- <member name="collision_depth" type="float" setter="" getter="get_collision_depth" default="0.0">
- </member>
- <member name="collision_normal" type="Vector2" setter="" getter="get_collision_normal" default="Vector2(0, 0)">
- </member>
- <member name="collision_point" type="Vector2" setter="" getter="get_collision_point" default="Vector2(0, 0)">
- </member>
- <member name="collision_safe_fraction" type="float" setter="" getter="get_collision_safe_fraction" default="0.0">
- </member>
- <member name="collision_unsafe_fraction" type="float" setter="" getter="get_collision_unsafe_fraction" default="0.0">
- </member>
- <member name="remainder" type="Vector2" setter="" getter="get_remainder" default="Vector2(0, 0)">
- </member>
- <member name="travel" type="Vector2" setter="" getter="get_travel" default="Vector2(0, 0)">
- </member>
- </members>
+ <methods>
+ <method name="get_collider" qualifiers="const">
+ <return type="Object" />
+ <description>
+ Returns the colliding body's attached [Object], if a collision occured.
+ </description>
+ </method>
+ <method name="get_collider_id" qualifiers="const">
+ <return type="int" />
+ <description>
+ Returns the unique instance ID of the colliding body's attached [Object], if a collision occured. See [method Object.get_instance_id].
+ </description>
+ </method>
+ <method name="get_collider_rid" qualifiers="const">
+ <return type="RID" />
+ <description>
+ Returns the colliding body's [RID] used by the [PhysicsServer2D], if a collision occured.
+ </description>
+ </method>
+ <method name="get_collider_shape" qualifiers="const">
+ <return type="int" />
+ <description>
+ Returns the colliding body's shape index, if a collision occured. See [CollisionObject2D].
+ </description>
+ </method>
+ <method name="get_collider_velocity" qualifiers="const">
+ <return type="Vector2" />
+ <description>
+ Returns the colliding body's velocity, if a collision occured.
+ </description>
+ </method>
+ <method name="get_collision_depth" qualifiers="const">
+ <return type="float" />
+ <description>
+ Returns the length of overlap along the collision normal, if a collision occured.
+ </description>
+ </method>
+ <method name="get_collision_local_shape" qualifiers="const">
+ <return type="int" />
+ <description>
+ Returns the moving object's colliding shape, if a collision occured.
+ </description>
+ </method>
+ <method name="get_collision_normal" qualifiers="const">
+ <return type="Vector2" />
+ <description>
+ Returns the colliding body's shape's normal at the point of collision, if a collision occured.
+ </description>
+ </method>
+ <method name="get_collision_point" qualifiers="const">
+ <return type="Vector2" />
+ <description>
+ Returns the point of collision in global coordinates, if a collision occured.
+ </description>
+ </method>
+ <method name="get_collision_safe_fraction" qualifiers="const">
+ <return type="float" />
+ <description>
+ Returns the maximum fraction of the motion that can occur without a collision, between [code]0[/code] and [code]1[/code].
+ </description>
+ </method>
+ <method name="get_collision_unsafe_fraction" qualifiers="const">
+ <return type="float" />
+ <description>
+ Returns the minimum fraction of the motion needed to collide, if a collision occured, between [code]0[/code] and [code]1[/code].
+ </description>
+ </method>
+ <method name="get_remainder" qualifiers="const">
+ <return type="Vector2" />
+ <description>
+ Returns the moving object's remaining movement vector.
+ </description>
+ </method>
+ <method name="get_travel" qualifiers="const">
+ <return type="Vector2" />
+ <description>
+ Returns the moving object's travel before collision.
+ </description>
+ </method>
+ </methods>
</class>
diff --git a/doc/classes/PhysicsTestMotionResult3D.xml b/doc/classes/PhysicsTestMotionResult3D.xml
index 8aa087e99a..282c140568 100644
--- a/doc/classes/PhysicsTestMotionResult3D.xml
+++ b/doc/classes/PhysicsTestMotionResult3D.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="PhysicsTestMotionResult3D" inherits="RefCounted" version="4.0">
<brief_description>
+ Result from a 3D body motion test.
</brief_description>
<description>
+ This class contains the motion and collision result from [method PhysicsServer3D.body_test_motion].
</description>
<tutorials>
</tutorials>
@@ -11,77 +13,94 @@
<return type="Object" />
<argument index="0" name="collision_index" type="int" default="0" />
<description>
+ Returns the colliding body's attached [Object] given a collision index (the deepest collision by default), if a collision occured.
</description>
</method>
<method name="get_collider_id" qualifiers="const">
<return type="int" />
<argument index="0" name="collision_index" type="int" default="0" />
<description>
+ Returns the unique instance ID of the colliding body's attached [Object] given a collision index (the deepest collision by default), if a collision occured. See [method Object.get_instance_id].
</description>
</method>
<method name="get_collider_rid" qualifiers="const">
<return type="RID" />
<argument index="0" name="collision_index" type="int" default="0" />
<description>
+ Returns the colliding body's [RID] used by the [PhysicsServer3D] given a collision index (the deepest collision by default), if a collision occured.
</description>
</method>
<method name="get_collider_shape" qualifiers="const">
<return type="int" />
<argument index="0" name="collision_index" type="int" default="0" />
<description>
+ Returns the colliding body's shape index given a collision index (the deepest collision by default), if a collision occured. See [CollisionObject3D].
</description>
</method>
<method name="get_collider_velocity" qualifiers="const">
<return type="Vector3" />
<argument index="0" name="collision_index" type="int" default="0" />
<description>
+ Returns the colliding body's velocity given a collision index (the deepest collision by default), if a collision occured.
+ </description>
+ </method>
+ <method name="get_collision_count" qualifiers="const">
+ <return type="int" />
+ <description>
+ Returns the number of detected collisions.
</description>
</method>
<method name="get_collision_depth" qualifiers="const">
<return type="float" />
<argument index="0" name="collision_index" type="int" default="0" />
<description>
+ Returns the length of overlap along the collision normal given a collision index (the deepest collision by default), if a collision occured.
+ </description>
+ </method>
+ <method name="get_collision_local_shape" qualifiers="const">
+ <return type="int" />
+ <argument index="0" name="collision_index" type="int" default="0" />
+ <description>
+ Returns the moving object's colliding shape given a collision index (the deepest collision by default), if a collision occured.
</description>
</method>
<method name="get_collision_normal" qualifiers="const">
<return type="Vector3" />
<argument index="0" name="collision_index" type="int" default="0" />
<description>
+ Returns the colliding body's shape's normal at the point of collision given a collision index (the deepest collision by default), if a collision occured.
</description>
</method>
<method name="get_collision_point" qualifiers="const">
<return type="Vector3" />
<argument index="0" name="collision_index" type="int" default="0" />
<description>
+ Returns the point of collision in global coordinates given a collision index (the deepest collision by default), if a collision occured.
+ </description>
+ </method>
+ <method name="get_collision_safe_fraction" qualifiers="const">
+ <return type="float" />
+ <description>
+ Returns the maximum fraction of the motion that can occur without a collision, between [code]0[/code] and [code]1[/code].
+ </description>
+ </method>
+ <method name="get_collision_unsafe_fraction" qualifiers="const">
+ <return type="float" />
+ <description>
+ Returns the minimum fraction of the motion needed to collide, if a collision occured, between [code]0[/code] and [code]1[/code].
+ </description>
+ </method>
+ <method name="get_remainder" qualifiers="const">
+ <return type="Vector3" />
+ <description>
+ Returns the moving object's remaining movement vector.
+ </description>
+ </method>
+ <method name="get_travel" qualifiers="const">
+ <return type="Vector3" />
+ <description>
+ Returns the moving object's travel before collision.
</description>
</method>
</methods>
- <members>
- <member name="collider" type="Object" setter="" getter="get_best_collider">
- </member>
- <member name="collider_id" type="int" setter="" getter="get_best_collider_id" default="0">
- </member>
- <member name="collider_rid" type="RID" setter="" getter="get_best_collider_rid">
- </member>
- <member name="collider_shape" type="int" setter="" getter="get_best_collider_shape" default="0">
- </member>
- <member name="collider_velocity" type="Vector3" setter="" getter="get_best_collider_velocity" default="Vector3(0, 0, 0)">
- </member>
- <member name="collision_count" type="int" setter="" getter="get_collision_count" default="0">
- </member>
- <member name="collision_depth" type="float" setter="" getter="get_best_collision_depth" default="0.0">
- </member>
- <member name="collision_normal" type="Vector3" setter="" getter="get_best_collision_normal" default="Vector3(0, 0, 0)">
- </member>
- <member name="collision_point" type="Vector3" setter="" getter="get_best_collision_point" default="Vector3(0, 0, 0)">
- </member>
- <member name="remainder" type="Vector3" setter="" getter="get_remainder" default="Vector3(0, 0, 0)">
- </member>
- <member name="safe_fraction" type="float" setter="" getter="get_safe_fraction" default="0.0">
- </member>
- <member name="travel" type="Vector3" setter="" getter="get_travel" default="Vector3(0, 0, 0)">
- </member>
- <member name="unsafe_fraction" type="float" setter="" getter="get_unsafe_fraction" default="0.0">
- </member>
- </members>
</class>
diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml
index e5fe823be6..532c9a7128 100644
--- a/doc/classes/TileMap.xml
+++ b/doc/classes/TileMap.xml
@@ -73,7 +73,7 @@
<return type="Vector2i" />
<argument index="0" name="body" type="RID" />
<description>
- Returns the coodinates of the tile for given physics body RID. Such RID can be retrieved from [member KinematicCollision2D.collider_rid], when colliding with a tile.
+ Returns the coodinates of the tile for given physics body RID. Such RID can be retrieved from [method KinematicCollision2D.get_collider_rid], when colliding with a tile.
</description>
</method>
<method name="get_layer_name" qualifiers="const">
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 5f56f86029..9a10255acc 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -54,13 +54,14 @@ PhysicsBody2D::~PhysicsBody2D() {
}
}
-Ref<KinematicCollision2D> PhysicsBody2D::_move(const Vector2 &p_motion, bool p_test_only, real_t p_margin) {
- PhysicsServer2D::MotionResult result;
-
+Ref<KinematicCollision2D> PhysicsBody2D::_move(const Vector2 &p_linear_velocity, bool p_test_only, real_t p_margin) {
// Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky.
double delta = Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time();
- if (move_and_collide(p_motion * delta, result, p_margin, p_test_only)) {
+ PhysicsServer2D::MotionParameters parameters(get_global_transform(), p_linear_velocity * delta, p_margin);
+
+ PhysicsServer2D::MotionResult result;
+ if (move_and_collide(parameters, result, p_test_only)) {
// Create a new instance when the cached reference is invalid or still in use in script.
if (motion_cache.is_null() || motion_cache->reference_get_count() > 1) {
motion_cache.instantiate();
@@ -74,18 +75,18 @@ Ref<KinematicCollision2D> PhysicsBody2D::_move(const Vector2 &p_motion, bool p_t
return Ref<KinematicCollision2D>();
}
-bool PhysicsBody2D::move_and_collide(const Vector2 &p_motion, PhysicsServer2D::MotionResult &r_result, real_t p_margin, bool p_test_only, bool p_cancel_sliding, bool p_collide_separation_ray, const Set<RID> &p_exclude) {
+bool PhysicsBody2D::move_and_collide(const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult &r_result, bool p_test_only, bool p_cancel_sliding) {
if (is_only_update_transform_changes_enabled()) {
ERR_PRINT("Move functions do not work together with 'sync to physics' option. Please read the documentation.");
}
- Transform2D gt = get_global_transform();
- bool colliding = PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_margin, &r_result, p_collide_separation_ray, p_exclude);
+
+ bool colliding = PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), p_parameters, &r_result);
// Restore direction of motion to be along original motion,
// in order to avoid sliding due to recovery,
// but only if collision depth is low enough to avoid tunneling.
if (p_cancel_sliding) {
- real_t motion_length = p_motion.length();
+ real_t motion_length = p_parameters.motion.length();
real_t precision = 0.001;
if (colliding) {
@@ -93,7 +94,7 @@ bool PhysicsBody2D::move_and_collide(const Vector2 &p_motion, PhysicsServer2D::M
// so even in normal resting cases the depth can be a bit more than the margin.
precision += motion_length * (r_result.collision_unsafe_fraction - r_result.collision_safe_fraction);
- if (r_result.collision_depth > (real_t)p_margin + precision) {
+ if (r_result.collision_depth > p_parameters.margin + precision) {
p_cancel_sliding = false;
}
}
@@ -102,7 +103,7 @@ bool PhysicsBody2D::move_and_collide(const Vector2 &p_motion, PhysicsServer2D::M
// When motion is null, recovery is the resulting motion.
Vector2 motion_normal;
if (motion_length > CMP_EPSILON) {
- motion_normal = p_motion / motion_length;
+ motion_normal = p_parameters.motion / motion_length;
}
// Check depth of recovery.
@@ -111,15 +112,16 @@ bool PhysicsBody2D::move_and_collide(const Vector2 &p_motion, PhysicsServer2D::M
real_t recovery_length = recovery.length();
// Fixes cases where canceling slide causes the motion to go too deep into the ground,
// because we're only taking rest information into account and not general recovery.
- if (recovery_length < (real_t)p_margin + precision) {
+ if (recovery_length < p_parameters.margin + precision) {
// Apply adjustment to motion.
r_result.travel = motion_normal * projected_length;
- r_result.remainder = p_motion - r_result.travel;
+ r_result.remainder = p_parameters.motion - r_result.travel;
}
}
}
if (!p_test_only) {
+ Transform2D gt = p_parameters.from;
gt.elements[2] += r_result.travel;
set_global_transform(gt);
}
@@ -127,7 +129,7 @@ bool PhysicsBody2D::move_and_collide(const Vector2 &p_motion, PhysicsServer2D::M
return colliding;
}
-bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_motion, const Ref<KinematicCollision2D> &r_collision, real_t p_margin) {
+bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_linear_velocity, const Ref<KinematicCollision2D> &r_collision, real_t p_margin) {
ERR_FAIL_COND_V(!is_inside_tree(), false);
PhysicsServer2D::MotionResult *r = nullptr;
@@ -139,7 +141,9 @@ bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_motion
// Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky.
double delta = Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time();
- return PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), p_from, p_motion * delta, p_margin, r);
+ PhysicsServer2D::MotionParameters parameters(p_from, p_linear_velocity * delta, p_margin);
+
+ return PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), parameters, r);
}
TypedArray<PhysicsBody2D> PhysicsBody2D::get_collision_exceptions() {
@@ -1083,10 +1087,11 @@ bool CharacterBody2D::move_and_slide() {
on_wall = false;
if (!current_platform_velocity.is_equal_approx(Vector2())) {
+ PhysicsServer2D::MotionParameters parameters(get_global_transform(), current_platform_velocity * delta, margin);
+ parameters.exclude_bodies.insert(platform_rid);
+
PhysicsServer2D::MotionResult floor_result;
- Set<RID> exclude;
- exclude.insert(platform_rid);
- if (move_and_collide(current_platform_velocity * delta, floor_result, margin, false, false, false, exclude)) {
+ if (move_and_collide(parameters, floor_result, false, false)) {
motion_results.push_back(floor_result);
_set_collision_direction(floor_result);
}
@@ -1138,11 +1143,13 @@ void CharacterBody2D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
Vector2 last_travel;
for (int iteration = 0; iteration < max_slides; ++iteration) {
- PhysicsServer2D::MotionResult result;
+ PhysicsServer2D::MotionParameters parameters(get_global_transform(), motion, margin);
- Vector2 prev_position = get_global_transform().elements[2];
+ Vector2 prev_position = parameters.from.elements[2];
+
+ PhysicsServer2D::MotionResult result;
+ bool collided = move_and_collide(parameters, result, false, !sliding_enabled);
- bool collided = move_and_collide(motion, result, margin, false, !sliding_enabled);
last_motion = result.travel;
if (collided) {
@@ -1283,9 +1290,11 @@ void CharacterBody2D::_move_and_slide_free(double p_delta) {
bool first_slide = true;
for (int iteration = 0; iteration < max_slides; ++iteration) {
+ PhysicsServer2D::MotionParameters parameters(get_global_transform(), motion, margin);
+
PhysicsServer2D::MotionResult result;
+ bool collided = move_and_collide(parameters, result, false, false);
- bool collided = move_and_collide(motion, result, margin, false, false);
last_motion = result.travel;
if (collided) {
@@ -1327,10 +1336,11 @@ void CharacterBody2D::_snap_on_floor(bool was_on_floor, bool vel_dir_facing_up)
// Snap by at least collision margin to keep floor state consistent.
real_t length = MAX(floor_snap_length, margin);
- Transform2D gt = get_global_transform();
+ PhysicsServer2D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
+ parameters.collide_separation_ray = true;
+
PhysicsServer2D::MotionResult result;
- if (move_and_collide(-up_direction * length, result, margin, true, false, true)) {
- bool apply = true;
+ if (move_and_collide(parameters, result, true, false)) {
if (result.get_angle(up_direction) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
on_floor = true;
floor_normal = result.collision_normal;
@@ -1345,13 +1355,9 @@ void CharacterBody2D::_snap_on_floor(bool was_on_floor, bool vel_dir_facing_up)
result.travel = Vector2();
}
}
- } else {
- apply = false;
- }
- if (apply) {
- gt.elements[2] += result.travel;
- set_global_transform(gt);
+ parameters.from.elements[2] += result.travel;
+ set_global_transform(parameters.from);
}
}
}
@@ -1364,8 +1370,11 @@ bool CharacterBody2D::_on_floor_if_snapped(bool was_on_floor, bool vel_dir_facin
// Snap by at least collision margin to keep floor state consistent.
real_t length = MAX(floor_snap_length, margin);
+ PhysicsServer2D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
+ parameters.collide_separation_ray = true;
+
PhysicsServer2D::MotionResult result;
- if (move_and_collide(-up_direction * length, result, margin, true, false, true)) {
+ if (move_and_collide(parameters, result, true, false)) {
if (result.get_angle(up_direction) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
return true;
}
@@ -1806,16 +1815,4 @@ void KinematicCollision2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_collider_shape"), &KinematicCollision2D::get_collider_shape);
ClassDB::bind_method(D_METHOD("get_collider_shape_index"), &KinematicCollision2D::get_collider_shape_index);
ClassDB::bind_method(D_METHOD("get_collider_velocity"), &KinematicCollision2D::get_collider_velocity);
-
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position"), "", "get_position");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "normal"), "", "get_normal");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "travel"), "", "get_travel");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "remainder"), "", "get_remainder");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "local_shape"), "", "get_local_shape");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "collider"), "", "get_collider");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_id"), "", "get_collider_id");
- ADD_PROPERTY(PropertyInfo(Variant::RID, "collider_rid"), "", "get_collider_rid");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "collider_shape"), "", "get_collider_shape");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_shape_index"), "", "get_collider_shape_index");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "collider_velocity"), "", "get_collider_velocity");
}
diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h
index 70cc5cd9bf..fd8bb66158 100644
--- a/scene/2d/physics_body_2d.h
+++ b/scene/2d/physics_body_2d.h
@@ -47,11 +47,11 @@ protected:
Ref<KinematicCollision2D> motion_cache;
- Ref<KinematicCollision2D> _move(const Vector2 &p_motion, bool p_test_only = false, real_t p_margin = 0.08);
+ Ref<KinematicCollision2D> _move(const Vector2 &p_linear_velocity, bool p_test_only = false, real_t p_margin = 0.08);
public:
- bool move_and_collide(const Vector2 &p_motion, PhysicsServer2D::MotionResult &r_result, real_t p_margin, bool p_test_only = false, bool p_cancel_sliding = true, bool p_collide_separation_ray = false, const Set<RID> &p_exclude = Set<RID>());
- bool test_move(const Transform2D &p_from, const Vector2 &p_motion, const Ref<KinematicCollision2D> &r_collision = Ref<KinematicCollision2D>(), real_t p_margin = 0.08);
+ bool move_and_collide(const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult &r_result, bool p_test_only = false, bool p_cancel_sliding = true);
+ bool test_move(const Transform2D &p_from, const Vector2 &p_linear_velocity, const Ref<KinematicCollision2D> &r_collision = Ref<KinematicCollision2D>(), real_t p_margin = 0.08);
TypedArray<PhysicsBody2D> get_collision_exceptions();
void add_collision_exception_with(Node *p_node); //must be physicsbody
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index fc0df3650f..b7c808398c 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -91,12 +91,15 @@ void PhysicsBody3D::remove_collision_exception_with(Node *p_node) {
PhysicsServer3D::get_singleton()->body_remove_collision_exception(get_rid(), collision_object->get_rid());
}
-Ref<KinematicCollision3D> PhysicsBody3D::_move(const Vector3 &p_motion, bool p_test_only, real_t p_margin, int p_max_collisions) {
- PhysicsServer3D::MotionResult result;
+Ref<KinematicCollision3D> PhysicsBody3D::_move(const Vector3 &p_linear_velocity, bool p_test_only, real_t p_margin, int p_max_collisions) {
// Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky
double delta = Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time();
- if (move_and_collide(p_motion * delta, result, p_margin, p_test_only, p_max_collisions)) {
+ PhysicsServer3D::MotionParameters parameters(get_global_transform(), p_linear_velocity * delta, p_margin);
+ parameters.max_collisions = p_max_collisions;
+
+ PhysicsServer3D::MotionResult result;
+ if (move_and_collide(parameters, result, p_test_only)) {
// Create a new instance when the cached reference is invalid or still in use in script.
if (motion_cache.is_null() || motion_cache->reference_get_count() > 1) {
motion_cache.instantiate();
@@ -111,23 +114,22 @@ Ref<KinematicCollision3D> PhysicsBody3D::_move(const Vector3 &p_motion, bool p_t
return Ref<KinematicCollision3D>();
}
-bool PhysicsBody3D::move_and_collide(const Vector3 &p_motion, PhysicsServer3D::MotionResult &r_result, real_t p_margin, bool p_test_only, int p_max_collisions, bool p_cancel_sliding, bool p_collide_separation_ray, const Set<RID> &p_exclude) {
- Transform3D gt = get_global_transform();
- bool colliding = PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_margin, &r_result, p_max_collisions, p_collide_separation_ray, p_exclude);
+bool PhysicsBody3D::move_and_collide(const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult &r_result, bool p_test_only, bool p_cancel_sliding) {
+ bool colliding = PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), p_parameters, &r_result);
// Restore direction of motion to be along original motion,
// in order to avoid sliding due to recovery,
// but only if collision depth is low enough to avoid tunneling.
if (p_cancel_sliding) {
- real_t motion_length = p_motion.length();
+ real_t motion_length = p_parameters.motion.length();
real_t precision = 0.001;
if (colliding) {
// Can't just use margin as a threshold because collision depth is calculated on unsafe motion,
// so even in normal resting cases the depth can be a bit more than the margin.
- precision += motion_length * (r_result.unsafe_fraction - r_result.safe_fraction);
+ precision += motion_length * (r_result.collision_unsafe_fraction - r_result.collision_safe_fraction);
- if (r_result.collisions[0].depth > (real_t)p_margin + precision) {
+ if (r_result.collisions[0].depth > p_parameters.margin + precision) {
p_cancel_sliding = false;
}
}
@@ -136,7 +138,7 @@ bool PhysicsBody3D::move_and_collide(const Vector3 &p_motion, PhysicsServer3D::M
// When motion is null, recovery is the resulting motion.
Vector3 motion_normal;
if (motion_length > CMP_EPSILON) {
- motion_normal = p_motion / motion_length;
+ motion_normal = p_parameters.motion / motion_length;
}
// Check depth of recovery.
@@ -145,10 +147,10 @@ bool PhysicsBody3D::move_and_collide(const Vector3 &p_motion, PhysicsServer3D::M
real_t recovery_length = recovery.length();
// Fixes cases where canceling slide causes the motion to go too deep into the ground,
// because we're only taking rest information into account and not general recovery.
- if (recovery_length < (real_t)p_margin + precision) {
+ if (recovery_length < p_parameters.margin + precision) {
// Apply adjustment to motion.
r_result.travel = motion_normal * projected_length;
- r_result.remainder = p_motion - r_result.travel;
+ r_result.remainder = p_parameters.motion - r_result.travel;
}
}
}
@@ -160,6 +162,7 @@ bool PhysicsBody3D::move_and_collide(const Vector3 &p_motion, PhysicsServer3D::M
}
if (!p_test_only) {
+ Transform3D gt = p_parameters.from;
gt.origin += r_result.travel;
set_global_transform(gt);
}
@@ -167,7 +170,7 @@ bool PhysicsBody3D::move_and_collide(const Vector3 &p_motion, PhysicsServer3D::M
return colliding;
}
-bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_motion, const Ref<KinematicCollision3D> &r_collision, real_t p_margin, int p_max_collisions) {
+bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_linear_velocity, const Ref<KinematicCollision3D> &r_collision, real_t p_margin, int p_max_collisions) {
ERR_FAIL_COND_V(!is_inside_tree(), false);
PhysicsServer3D::MotionResult *r = nullptr;
@@ -179,7 +182,9 @@ bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_motion
// Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky
double delta = Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time();
- return PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), p_from, p_motion * delta, p_margin, r, p_max_collisions);
+ PhysicsServer3D::MotionParameters parameters(p_from, p_linear_velocity * delta, p_margin);
+
+ return PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), parameters, r);
}
void PhysicsBody3D::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock) {
@@ -1124,10 +1129,11 @@ bool CharacterBody3D::move_and_slide() {
last_motion = Vector3();
if (!current_platform_velocity.is_equal_approx(Vector3())) {
+ PhysicsServer3D::MotionParameters parameters(get_global_transform(), current_platform_velocity * delta, margin);
+ parameters.exclude_bodies.insert(platform_rid);
+
PhysicsServer3D::MotionResult floor_result;
- Set<RID> exclude;
- exclude.insert(platform_rid);
- if (move_and_collide(current_platform_velocity * delta, floor_result, margin, false, 1, false, false, exclude)) {
+ if (move_and_collide(parameters, floor_result, false, false)) {
motion_results.push_back(floor_result);
CollisionState result_state;
@@ -1181,8 +1187,12 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
Vector3 total_travel;
for (int iteration = 0; iteration < max_slides; ++iteration) {
+ PhysicsServer3D::MotionParameters parameters(get_global_transform(), motion, margin);
+ parameters.max_collisions = 4;
+
PhysicsServer3D::MotionResult result;
- bool collided = move_and_collide(motion, result, margin, false, 4, !sliding_enabled);
+ bool collided = move_and_collide(parameters, result, false, !sliding_enabled);
+
last_motion = result.travel;
if (collided) {
@@ -1411,9 +1421,11 @@ void CharacterBody3D::_move_and_slide_free(double p_delta) {
bool first_slide = true;
for (int iteration = 0; iteration < max_slides; ++iteration) {
+ PhysicsServer3D::MotionParameters parameters(get_global_transform(), motion, margin);
+
PhysicsServer3D::MotionResult result;
+ bool collided = move_and_collide(parameters, result, false, false);
- bool collided = move_and_collide(motion, result, margin, false, 1, false);
last_motion = result.travel;
if (collided) {
@@ -1462,9 +1474,12 @@ void CharacterBody3D::_snap_on_floor(bool was_on_floor, bool vel_dir_facing_up)
// Snap by at least collision margin to keep floor state consistent.
real_t length = MAX(floor_snap_length, margin);
- Transform3D gt = get_global_transform();
+ PhysicsServer3D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
+ parameters.max_collisions = 4;
+ parameters.collide_separation_ray = true;
+
PhysicsServer3D::MotionResult result;
- if (move_and_collide(-up_direction * length, result, margin, true, 4, false, true)) {
+ if (move_and_collide(parameters, result, true, false)) {
CollisionState result_state;
// Apply direction for floor only.
_set_collision_direction(result, result_state, CollisionState(true, false, false));
@@ -1480,8 +1495,8 @@ void CharacterBody3D::_snap_on_floor(bool was_on_floor, bool vel_dir_facing_up)
}
}
- gt.origin += result.travel;
- set_global_transform(gt);
+ parameters.from.origin += result.travel;
+ set_global_transform(parameters.from);
}
}
}
@@ -1494,8 +1509,12 @@ bool CharacterBody3D::_on_floor_if_snapped(bool was_on_floor, bool vel_dir_facin
// Snap by at least collision margin to keep floor state consistent.
real_t length = MAX(floor_snap_length, margin);
+ PhysicsServer3D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
+ parameters.max_collisions = 4;
+ parameters.collide_separation_ray = true;
+
PhysicsServer3D::MotionResult result;
- if (move_and_collide(-up_direction * length, result, margin, true, 4, false, true)) {
+ if (move_and_collide(parameters, result, true, false)) {
CollisionState result_state;
// Don't apply direction for any type.
_set_collision_direction(result, result_state, CollisionState());
@@ -2002,42 +2021,6 @@ Vector3 KinematicCollision3D::get_collider_velocity(int p_collision_index) const
return result.collisions[p_collision_index].collider_velocity;
}
-Vector3 KinematicCollision3D::get_best_position() const {
- return result.collision_count ? get_position() : Vector3();
-}
-
-Vector3 KinematicCollision3D::get_best_normal() const {
- return result.collision_count ? get_normal() : Vector3();
-}
-
-Object *KinematicCollision3D::get_best_local_shape() const {
- return result.collision_count ? get_local_shape() : nullptr;
-}
-
-Object *KinematicCollision3D::get_best_collider() const {
- return result.collision_count ? get_collider() : nullptr;
-}
-
-ObjectID KinematicCollision3D::get_best_collider_id() const {
- return result.collision_count ? get_collider_id() : ObjectID();
-}
-
-RID KinematicCollision3D::get_best_collider_rid() const {
- return result.collision_count ? get_collider_rid() : RID();
-}
-
-Object *KinematicCollision3D::get_best_collider_shape() const {
- return result.collision_count ? get_collider_shape() : nullptr;
-}
-
-int KinematicCollision3D::get_best_collider_shape_index() const {
- return result.collision_count ? get_collider_shape_index() : 0;
-}
-
-Vector3 KinematicCollision3D::get_best_collider_velocity() const {
- return result.collision_count ? get_collider_velocity() : Vector3();
-}
-
void KinematicCollision3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_travel"), &KinematicCollision3D::get_travel);
ClassDB::bind_method(D_METHOD("get_remainder"), &KinematicCollision3D::get_remainder);
@@ -2052,29 +2035,6 @@ void KinematicCollision3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_collider_shape", "collision_index"), &KinematicCollision3D::get_collider_shape, DEFVAL(0));
ClassDB::bind_method(D_METHOD("get_collider_shape_index", "collision_index"), &KinematicCollision3D::get_collider_shape_index, DEFVAL(0));
ClassDB::bind_method(D_METHOD("get_collider_velocity", "collision_index"), &KinematicCollision3D::get_collider_velocity, DEFVAL(0));
-
- ClassDB::bind_method(D_METHOD("get_best_position"), &KinematicCollision3D::get_best_position);
- ClassDB::bind_method(D_METHOD("get_best_normal"), &KinematicCollision3D::get_best_normal);
- ClassDB::bind_method(D_METHOD("get_best_local_shape"), &KinematicCollision3D::get_best_local_shape);
- ClassDB::bind_method(D_METHOD("get_best_collider"), &KinematicCollision3D::get_best_collider);
- ClassDB::bind_method(D_METHOD("get_best_collider_id"), &KinematicCollision3D::get_best_collider_id);
- ClassDB::bind_method(D_METHOD("get_best_collider_rid"), &KinematicCollision3D::get_best_collider_rid);
- ClassDB::bind_method(D_METHOD("get_best_collider_shape"), &KinematicCollision3D::get_best_collider_shape);
- ClassDB::bind_method(D_METHOD("get_best_collider_shape_index"), &KinematicCollision3D::get_best_collider_shape_index);
- ClassDB::bind_method(D_METHOD("get_best_collider_velocity"), &KinematicCollision3D::get_best_collider_velocity);
-
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "travel"), "", "get_travel");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "remainder"), "", "get_remainder");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_count"), "", "get_collision_count");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position"), "", "get_best_position");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "normal"), "", "get_best_normal");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "local_shape"), "", "get_best_local_shape");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "collider"), "", "get_best_collider");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_id"), "", "get_best_collider_id");
- ADD_PROPERTY(PropertyInfo(Variant::RID, "collider_rid"), "", "get_best_collider_rid");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "collider_shape"), "", "get_best_collider_shape");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_shape_index"), "", "get_best_collider_shape_index");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "collider_velocity"), "", "get_best_collider_velocity");
}
///////////////////////////////////////
diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h
index fdda681350..d2754e7726 100644
--- a/scene/3d/physics_body_3d.h
+++ b/scene/3d/physics_body_3d.h
@@ -50,11 +50,11 @@ protected:
uint16_t locked_axis = 0;
- Ref<KinematicCollision3D> _move(const Vector3 &p_motion, bool p_test_only = false, real_t p_margin = 0.001, int p_max_collisions = 1);
+ Ref<KinematicCollision3D> _move(const Vector3 &p_linear_velocity, bool p_test_only = false, real_t p_margin = 0.001, int p_max_collisions = 1);
public:
- bool move_and_collide(const Vector3 &p_motion, PhysicsServer3D::MotionResult &r_result, real_t p_margin, bool p_test_only = false, int p_max_collisions = 1, bool p_cancel_sliding = true, bool p_collide_separation_ray = false, const Set<RID> &p_exclude = Set<RID>());
- bool test_move(const Transform3D &p_from, const Vector3 &p_motion, const Ref<KinematicCollision3D> &r_collision = Ref<KinematicCollision3D>(), real_t p_margin = 0.001, int p_max_collisions = 1);
+ bool move_and_collide(const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult &r_result, bool p_test_only = false, bool p_cancel_sliding = true);
+ bool test_move(const Transform3D &p_from, const Vector3 &p_linear_velocity, const Ref<KinematicCollision3D> &r_collision = Ref<KinematicCollision3D>(), real_t p_margin = 0.001, int p_max_collisions = 1);
void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock);
bool get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const;
@@ -487,16 +487,6 @@ public:
Object *get_collider_shape(int p_collision_index = 0) const;
int get_collider_shape_index(int p_collision_index = 0) const;
Vector3 get_collider_velocity(int p_collision_index = 0) const;
-
- Vector3 get_best_position() const;
- Vector3 get_best_normal() const;
- Object *get_best_local_shape() const;
- Object *get_best_collider() const;
- ObjectID get_best_collider_id() const;
- RID get_best_collider_rid() const;
- Object *get_best_collider_shape() const;
- int get_best_collider_shape_index() const;
- Vector3 get_best_collider_velocity() const;
};
class PhysicalBone3D : public PhysicsBody3D {
diff --git a/servers/physics_2d/physics_server_2d_sw.cpp b/servers/physics_2d/physics_server_2d_sw.cpp
index 4315b55df4..c2205e33b0 100644
--- a/servers/physics_2d/physics_server_2d_sw.cpp
+++ b/servers/physics_2d/physics_server_2d_sw.cpp
@@ -948,7 +948,7 @@ void PhysicsServer2DSW::body_set_pickable(RID p_body, bool p_pickable) {
body->set_pickable(p_pickable);
}
-bool PhysicsServer2DSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, MotionResult *r_result, bool p_collide_separation_ray, const Set<RID> &p_exclude) {
+bool PhysicsServer2DSW::body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result) {
Body2DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, false);
ERR_FAIL_COND_V(!body->get_space(), false);
@@ -956,7 +956,7 @@ bool PhysicsServer2DSW::body_test_motion(RID p_body, const Transform2D &p_from,
_update_shapes();
- return body->get_space()->test_body_motion(body, p_from, p_motion, p_margin, r_result, p_collide_separation_ray, p_exclude);
+ return body->get_space()->test_body_motion(body, p_parameters, r_result);
}
PhysicsDirectBodyState2D *PhysicsServer2DSW::body_get_direct_state(RID p_body) {
diff --git a/servers/physics_2d/physics_server_2d_sw.h b/servers/physics_2d/physics_server_2d_sw.h
index 1f35e83995..b8e375a087 100644
--- a/servers/physics_2d/physics_server_2d_sw.h
+++ b/servers/physics_2d/physics_server_2d_sw.h
@@ -246,7 +246,7 @@ public:
virtual void body_set_pickable(RID p_body, bool p_pickable) override;
- virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, MotionResult *r_result = nullptr, bool p_collide_separation_ray = false, const Set<RID> &p_exclude = Set<RID>()) override;
+ virtual bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override;
// this function only works on physics process, errors and returns null otherwise
virtual PhysicsDirectBodyState2D *body_get_direct_state(RID p_body) override;
diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.h b/servers/physics_2d/physics_server_2d_wrap_mt.h
index 7925344d76..8d9e366661 100644
--- a/servers/physics_2d/physics_server_2d_wrap_mt.h
+++ b/servers/physics_2d/physics_server_2d_wrap_mt.h
@@ -254,9 +254,9 @@ public:
FUNC2(body_set_pickable, RID, bool);
- bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, MotionResult *r_result = nullptr, bool p_collide_separation_ray = false, const Set<RID> &p_exclude = Set<RID>()) override {
+ bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
- return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_margin, r_result, p_collide_separation_ray, p_exclude);
+ return physics_2d_server->body_test_motion(p_body, p_parameters, r_result);
}
// this function only works on physics process, errors and returns null otherwise
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index 5cd9bf3223..5e25d7f7c4 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -525,7 +525,7 @@ int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb) {
return amount;
}
-bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, PhysicsServer2D::MotionResult *r_result, bool p_collide_separation_ray, const Set<RID> &p_exclude) {
+bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult *r_result) {
//give me back regular physics engine logic
//this is madness
//and most people using this function will think
@@ -557,25 +557,25 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
if (!shapes_found) {
if (r_result) {
*r_result = PhysicsServer2D::MotionResult();
- r_result->travel = p_motion;
+ r_result->travel = p_parameters.motion;
}
return false;
}
// Undo the currently transform the physics server is aware of and apply the provided one
- body_aabb = p_from.xform(p_body->get_inv_transform().xform(body_aabb));
- body_aabb = body_aabb.grow(p_margin);
+ body_aabb = p_parameters.from.xform(p_body->get_inv_transform().xform(body_aabb));
+ body_aabb = body_aabb.grow(p_parameters.margin);
static const int max_excluded_shape_pairs = 32;
ExcludedShapeSW excluded_shape_pairs[max_excluded_shape_pairs];
int excluded_shape_pair_count = 0;
- real_t min_contact_depth = p_margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
+ real_t min_contact_depth = p_parameters.margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
- real_t motion_length = p_motion.length();
- Vector2 motion_normal = p_motion / motion_length;
+ real_t motion_length = p_parameters.motion.length();
+ Vector2 motion_normal = p_parameters.motion / motion_length;
- Transform2D body_transform = p_from;
+ Transform2D body_transform = p_parameters.from;
bool recovered = false;
@@ -612,7 +612,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
for (int i = 0; i < amount; i++) {
const CollisionObject2DSW *col_obj = intersection_query_results[i];
- if (p_exclude.has(col_obj->get_self())) {
+ if (p_parameters.exclude_bodies.has(col_obj->get_self())) {
continue;
}
@@ -624,7 +624,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
cbk.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
real_t owc_margin = col_obj->get_shape_one_way_collision_margin(shape_idx);
- cbk.valid_depth = MAX(owc_margin, p_margin); //user specified, but never less than actual margin or it won't work
+ cbk.valid_depth = MAX(owc_margin, p_parameters.margin); //user specified, but never less than actual margin or it won't work
cbk.invalid_by_dir = 0;
if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) {
@@ -649,7 +649,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
bool did_collide = false;
Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
- if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, nullptr, p_margin)) {
+ if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, nullptr, p_parameters.margin)) {
did_collide = cbk.passed > current_passed; //more passed, so collision actually existed
}
@@ -714,7 +714,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
// STEP 2 ATTEMPT MOTION
Rect2 motion_aabb = body_aabb;
- motion_aabb.position += p_motion;
+ motion_aabb.position += p_parameters.motion;
motion_aabb = motion_aabb.merge(body_aabb);
int amount = _cull_aabb_for_body(p_body, motion_aabb);
@@ -728,7 +728,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
// Colliding separation rays allows to properly snap to the ground,
// otherwise it's not needed in regular motion.
- if (!p_collide_separation_ray && (body_shape->get_type() == PhysicsServer2D::SHAPE_SEPARATION_RAY)) {
+ if (!p_parameters.collide_separation_ray && (body_shape->get_type() == PhysicsServer2D::SHAPE_SEPARATION_RAY)) {
// When slide on slope is on, separation ray shape acts like a regular shape.
if (!static_cast<SeparationRayShape2DSW *>(body_shape)->get_slide_on_slope()) {
continue;
@@ -744,9 +744,10 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
for (int i = 0; i < amount; i++) {
const CollisionObject2DSW *col_obj = intersection_query_results[i];
- if (p_exclude.has(col_obj->get_self())) {
+ if (p_parameters.exclude_bodies.has(col_obj->get_self())) {
continue;
}
+
int col_shape_idx = intersection_query_subindex_results[i];
Shape2DSW *against_shape = col_obj->get_shape(col_shape_idx);
@@ -765,7 +766,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(col_shape_idx);
//test initial overlap, does it collide if going all the way?
- if (!CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion, against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, nullptr, 0)) {
+ if (!CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_parameters.motion, against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, nullptr, 0)) {
continue;
}
@@ -790,7 +791,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
real_t fraction = low + (hi - low) * fraction_coeff;
Vector2 sep = motion_normal; //important optimization for this to work fast enough
- bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * fraction, against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, &sep, 0);
+ bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_parameters.motion * fraction, against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, &sep, 0);
if (collided) {
hi = fraction;
@@ -827,7 +828,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
cbk.valid_depth = 10e20;
Vector2 sep = motion_normal; //important optimization for this to work fast enough
- bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(col_shape_idx), col_obj_shape_xform, Vector2(), PhysicsServer2DSW::_shape_col_cbk, &cbk, &sep, 0);
+ bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_parameters.motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(col_shape_idx), col_obj_shape_xform, Vector2(), PhysicsServer2DSW::_shape_col_cbk, &cbk, &sep, 0);
if (!collided || cbk.amount == 0) {
continue;
}
@@ -865,7 +866,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
//it collided, let's get the rest info in unsafe advance
Transform2D ugt = body_transform;
- ugt.elements[2] += p_motion * unsafe;
+ ugt.elements[2] += p_parameters.motion * unsafe;
_RestCallbackData2D rcd;
rcd.best_len = 0;
@@ -886,13 +887,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
Transform2D body_shape_xform = ugt * p_body->get_shape_transform(j);
Shape2DSW *body_shape = p_body->get_shape(j);
- body_aabb.position += p_motion * unsafe;
+ body_aabb.position += p_parameters.motion * unsafe;
int amount = _cull_aabb_for_body(p_body, body_aabb);
for (int i = 0; i < amount; i++) {
const CollisionObject2DSW *col_obj = intersection_query_results[i];
- if (p_exclude.has(col_obj->get_self())) {
+ if (p_parameters.exclude_bodies.has(col_obj->get_self())) {
continue;
}
@@ -917,7 +918,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
rcd.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
real_t owc_margin = col_obj->get_shape_one_way_collision_margin(shape_idx);
- rcd.valid_depth = MAX(owc_margin, p_margin); //user specified, but never less than actual margin or it won't work
+ rcd.valid_depth = MAX(owc_margin, p_parameters.margin); //user specified, but never less than actual margin or it won't work
if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) {
const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
@@ -939,7 +940,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
rcd.object = col_obj;
rcd.shape = shape_idx;
rcd.local_shape = j;
- bool sc = CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), _rest_cbk_result, &rcd, nullptr, p_margin);
+ bool sc = CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), _rest_cbk_result, &rcd, nullptr, p_parameters.margin);
if (!sc) {
continue;
}
@@ -962,9 +963,9 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
Vector2 rel_vec = r_result->collision_point - (body->get_transform().get_origin() + body->get_center_of_mass());
r_result->collider_velocity = Vector2(-body->get_angular_velocity() * rel_vec.y, body->get_angular_velocity() * rel_vec.x) + body->get_linear_velocity();
- r_result->travel = safe * p_motion;
- r_result->remainder = p_motion - safe * p_motion;
- r_result->travel += (body_transform.get_origin() - p_from.get_origin());
+ r_result->travel = safe * p_parameters.motion;
+ r_result->remainder = p_parameters.motion - safe * p_parameters.motion;
+ r_result->travel += (body_transform.get_origin() - p_parameters.from.get_origin());
}
collided = true;
@@ -972,9 +973,9 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
}
if (!collided && r_result) {
- r_result->travel = p_motion;
+ r_result->travel = p_parameters.motion;
r_result->remainder = Vector2();
- r_result->travel += (body_transform.get_origin() - p_from.get_origin());
+ r_result->travel += (body_transform.get_origin() - p_parameters.from.get_origin());
}
return collided;
diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h
index a1a8a77ee4..746b5c6c9a 100644
--- a/servers/physics_2d/space_2d_sw.h
+++ b/servers/physics_2d/space_2d_sw.h
@@ -187,7 +187,7 @@ public:
int get_collision_pairs() const { return collision_pairs; }
- bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, PhysicsServer2D::MotionResult *r_result, bool p_collide_separation_ray = false, const Set<RID> &p_exclude = Set<RID>());
+ bool test_body_motion(Body2DSW *p_body, const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult *r_result);
void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); }
_FORCE_INLINE_ bool is_debugging_contacts() const { return !contact_debug.is_empty(); }
diff --git a/servers/physics_3d/physics_server_3d_sw.cpp b/servers/physics_3d/physics_server_3d_sw.cpp
index 36f81e072d..b16e199a03 100644
--- a/servers/physics_3d/physics_server_3d_sw.cpp
+++ b/servers/physics_3d/physics_server_3d_sw.cpp
@@ -868,7 +868,7 @@ void PhysicsServer3DSW::body_set_ray_pickable(RID p_body, bool p_enable) {
body->set_ray_pickable(p_enable);
}
-bool PhysicsServer3DSW::body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, MotionResult *r_result, int p_max_collisions, bool p_collide_separation_ray, const Set<RID> &p_exclude) {
+bool PhysicsServer3DSW::body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result) {
Body3DSW *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND_V(!body, false);
ERR_FAIL_COND_V(!body->get_space(), false);
@@ -876,7 +876,7 @@ bool PhysicsServer3DSW::body_test_motion(RID p_body, const Transform3D &p_from,
_update_shapes();
- return body->get_space()->test_body_motion(body, p_from, p_motion, p_margin, r_result, p_max_collisions, p_collide_separation_ray, p_exclude);
+ return body->get_space()->test_body_motion(body, p_parameters, r_result);
}
PhysicsDirectBodyState3D *PhysicsServer3DSW::body_get_direct_state(RID p_body) {
diff --git a/servers/physics_3d/physics_server_3d_sw.h b/servers/physics_3d/physics_server_3d_sw.h
index 106e260311..54a787198d 100644
--- a/servers/physics_3d/physics_server_3d_sw.h
+++ b/servers/physics_3d/physics_server_3d_sw.h
@@ -242,7 +242,7 @@ public:
virtual void body_set_ray_pickable(RID p_body, bool p_enable) override;
- virtual bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = nullptr, int p_max_collisions = 1, bool p_collide_separation_ray = false, const Set<RID> &p_exclude = Set<RID>()) override;
+ virtual bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override;
// this function only works on physics process, errors and returns null otherwise
virtual PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) override;
diff --git a/servers/physics_3d/physics_server_3d_wrap_mt.h b/servers/physics_3d/physics_server_3d_wrap_mt.h
index a86fb5a3d3..17d02addda 100644
--- a/servers/physics_3d/physics_server_3d_wrap_mt.h
+++ b/servers/physics_3d/physics_server_3d_wrap_mt.h
@@ -253,9 +253,9 @@ public:
FUNC2(body_set_ray_pickable, RID, bool);
- bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = nullptr, int p_max_collisions = 1, bool p_collide_separation_ray = false, const Set<RID> &p_exclude = Set<RID>()) override {
+ bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
- return physics_3d_server->body_test_motion(p_body, p_from, p_motion, p_margin, r_result, p_max_collisions, p_collide_separation_ray, p_exclude);
+ return physics_3d_server->body_test_motion(p_body, p_parameters, r_result);
}
// this function only works on physics process, errors and returns null otherwise
diff --git a/servers/physics_3d/space_3d_sw.cpp b/servers/physics_3d/space_3d_sw.cpp
index 369dad45eb..f5f497e167 100644
--- a/servers/physics_3d/space_3d_sw.cpp
+++ b/servers/physics_3d/space_3d_sw.cpp
@@ -620,7 +620,7 @@ int Space3DSW::_cull_aabb_for_body(Body3DSW *p_body, const AABB &p_aabb) {
return amount;
}
-bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, PhysicsServer3D::MotionResult *r_result, int p_max_collisions, bool p_collide_separation_ray, const Set<RID> &p_exclude) {
+bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult *r_result) {
//give me back regular physics engine logic
//this is madness
//and most people using this function will think
@@ -628,7 +628,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
//this took about a week to get right..
//but is it right? who knows at this point..
- ERR_FAIL_INDEX_V(p_max_collisions, PhysicsServer3D::MotionResult::MAX_COLLISIONS, false);
+ ERR_FAIL_INDEX_V(p_parameters.max_collisions, PhysicsServer3D::MotionResult::MAX_COLLISIONS, false);
if (r_result) {
*r_result = PhysicsServer3D::MotionResult();
@@ -652,22 +652,22 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
if (!shapes_found) {
if (r_result) {
- r_result->travel = p_motion;
+ r_result->travel = p_parameters.motion;
}
return false;
}
// Undo the currently transform the physics server is aware of and apply the provided one
- body_aabb = p_from.xform(p_body->get_inv_transform().xform(body_aabb));
- body_aabb = body_aabb.grow(p_margin);
+ body_aabb = p_parameters.from.xform(p_body->get_inv_transform().xform(body_aabb));
+ body_aabb = body_aabb.grow(p_parameters.margin);
- real_t min_contact_depth = p_margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
+ real_t min_contact_depth = p_parameters.margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
- real_t motion_length = p_motion.length();
- Vector3 motion_normal = p_motion / motion_length;
+ real_t motion_length = p_parameters.motion.length();
+ Vector3 motion_normal = p_parameters.motion / motion_length;
- Transform3D body_transform = p_from;
+ Transform3D body_transform = p_parameters.from;
bool recovered = false;
@@ -701,13 +701,13 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
for (int i = 0; i < amount; i++) {
const CollisionObject3DSW *col_obj = intersection_query_results[i];
- if (p_exclude.has(col_obj->get_self())) {
+ if (p_parameters.exclude_bodies.has(col_obj->get_self())) {
continue;
}
int shape_idx = intersection_query_subindex_results[i];
- if (CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, p_margin)) {
+ if (CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, p_parameters.margin)) {
collided = cbk.amount > 0;
}
}
@@ -757,7 +757,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
// STEP 2 ATTEMPT MOTION
AABB motion_aabb = body_aabb;
- motion_aabb.position += p_motion;
+ motion_aabb.position += p_parameters.motion;
motion_aabb = motion_aabb.merge(body_aabb);
int amount = _cull_aabb_for_body(p_body, motion_aabb);
@@ -771,7 +771,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
// Colliding separation rays allows to properly snap to the ground,
// otherwise it's not needed in regular motion.
- if (!p_collide_separation_ray && (body_shape->get_type() == PhysicsServer3D::SHAPE_SEPARATION_RAY)) {
+ if (!p_parameters.collide_separation_ray && (body_shape->get_type() == PhysicsServer3D::SHAPE_SEPARATION_RAY)) {
// When slide on slope is on, separation ray shape acts like a regular shape.
if (!static_cast<SeparationRayShape3DSW *>(body_shape)->get_slide_on_slope()) {
continue;
@@ -783,7 +783,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
Transform3D body_shape_xform_inv = body_shape_xform.affine_inverse();
MotionShape3DSW mshape;
mshape.shape = body_shape;
- mshape.motion = body_shape_xform_inv.basis.xform(p_motion);
+ mshape.motion = body_shape_xform_inv.basis.xform(p_parameters.motion);
bool stuck = false;
@@ -792,7 +792,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
for (int i = 0; i < amount; i++) {
const CollisionObject3DSW *col_obj = intersection_query_results[i];
- if (p_exclude.has(col_obj->get_self())) {
+ if (p_parameters.exclude_bodies.has(col_obj->get_self())) {
continue;
}
@@ -821,7 +821,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
for (int k = 0; k < 8; k++) { //steps should be customizable..
real_t fraction = low + (hi - low) * fraction_coeff;
- mshape.motion = body_shape_xform_inv.basis.xform(p_motion * fraction);
+ mshape.motion = body_shape_xform_inv.basis.xform(p_parameters.motion * fraction);
Vector3 lA, lB;
Vector3 sep = motion_normal; //important optimization for this to work fast enough
@@ -883,13 +883,13 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
//it collided, let's get the rest info in unsafe advance
Transform3D ugt = body_transform;
- ugt.origin += p_motion * unsafe;
+ ugt.origin += p_parameters.motion * unsafe;
_RestResultData results[PhysicsServer3D::MotionResult::MAX_COLLISIONS];
_RestCallbackData rcd;
- if (p_max_collisions > 1) {
- rcd.max_results = p_max_collisions;
+ if (p_parameters.max_collisions > 1) {
+ rcd.max_results = p_parameters.max_collisions;
rcd.other_results = results;
}
@@ -907,20 +907,20 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
Transform3D body_shape_xform = ugt * p_body->get_shape_transform(j);
Shape3DSW *body_shape = p_body->get_shape(j);
- body_aabb.position += p_motion * unsafe;
+ body_aabb.position += p_parameters.motion * unsafe;
int amount = _cull_aabb_for_body(p_body, body_aabb);
for (int i = 0; i < amount; i++) {
const CollisionObject3DSW *col_obj = intersection_query_results[i];
- if (p_exclude.has(col_obj->get_self())) {
+ if (p_parameters.exclude_bodies.has(col_obj->get_self())) {
continue;
}
int shape_idx = intersection_query_subindex_results[i];
rcd.object = col_obj;
rcd.shape = shape_idx;
- bool sc = CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, p_margin);
+ bool sc = CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, p_parameters.margin);
if (!sc) {
continue;
}
@@ -948,12 +948,12 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
collision.collider_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(rel_vec);
}
- r_result->travel = safe * p_motion;
- r_result->remainder = p_motion - safe * p_motion;
- r_result->travel += (body_transform.get_origin() - p_from.get_origin());
+ r_result->travel = safe * p_parameters.motion;
+ r_result->remainder = p_parameters.motion - safe * p_parameters.motion;
+ r_result->travel += (body_transform.get_origin() - p_parameters.from.get_origin());
- r_result->safe_fraction = safe;
- r_result->unsafe_fraction = unsafe;
+ r_result->collision_safe_fraction = safe;
+ r_result->collision_unsafe_fraction = unsafe;
r_result->collision_count = rcd.result_count;
}
@@ -963,12 +963,12 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
}
if (!collided && r_result) {
- r_result->travel = p_motion;
+ r_result->travel = p_parameters.motion;
r_result->remainder = Vector3();
- r_result->travel += (body_transform.get_origin() - p_from.get_origin());
+ r_result->travel += (body_transform.get_origin() - p_parameters.from.get_origin());
- r_result->safe_fraction = 1.0;
- r_result->unsafe_fraction = 1.0;
+ r_result->collision_safe_fraction = 1.0;
+ r_result->collision_unsafe_fraction = 1.0;
}
return collided;
diff --git a/servers/physics_3d/space_3d_sw.h b/servers/physics_3d/space_3d_sw.h
index daa1244bf8..69cc3c4bbd 100644
--- a/servers/physics_3d/space_3d_sw.h
+++ b/servers/physics_3d/space_3d_sw.h
@@ -207,7 +207,7 @@ public:
void set_elapsed_time(ElapsedTime p_time, uint64_t p_msec) { elapsed_time[p_time] = p_msec; }
uint64_t get_elapsed_time(ElapsedTime p_time) const { return elapsed_time[p_time]; }
- bool test_body_motion(Body3DSW *p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, PhysicsServer3D::MotionResult *r_result, int p_max_collisions = 1, bool p_collide_separation_ray = false, const Set<RID> &p_exclude = Set<RID>());
+ bool test_body_motion(Body3DSW *p_body, const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult *r_result);
Space3DSW();
~Space3DSW();
diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp
index 2a4240baee..ad53f9ed20 100644
--- a/servers/physics_server_2d.cpp
+++ b/servers/physics_server_2d.cpp
@@ -412,6 +412,49 @@ void PhysicsDirectSpaceState2D::_bind_methods() {
///////////////////////////////
+Vector<RID> PhysicsTestMotionParameters2D::get_exclude_bodies() const {
+ Vector<RID> exclude;
+ exclude.resize(parameters.exclude_bodies.size());
+
+ int body_index = 0;
+ for (RID body : parameters.exclude_bodies) {
+ exclude.write[body_index++] = body;
+ }
+
+ return exclude;
+}
+
+void PhysicsTestMotionParameters2D::set_exclude_bodies(const Vector<RID> &p_exclude) {
+ for (RID body : p_exclude) {
+ parameters.exclude_bodies.insert(body);
+ }
+}
+
+void PhysicsTestMotionParameters2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_from"), &PhysicsTestMotionParameters2D::get_from);
+ ClassDB::bind_method(D_METHOD("set_from"), &PhysicsTestMotionParameters2D::set_from);
+
+ ClassDB::bind_method(D_METHOD("get_motion"), &PhysicsTestMotionParameters2D::get_motion);
+ ClassDB::bind_method(D_METHOD("set_motion"), &PhysicsTestMotionParameters2D::set_motion);
+
+ ClassDB::bind_method(D_METHOD("get_margin"), &PhysicsTestMotionParameters2D::get_margin);
+ ClassDB::bind_method(D_METHOD("set_margin"), &PhysicsTestMotionParameters2D::set_margin);
+
+ ClassDB::bind_method(D_METHOD("is_collide_separation_ray_enabled"), &PhysicsTestMotionParameters2D::is_collide_separation_ray_enabled);
+ ClassDB::bind_method(D_METHOD("set_collide_separation_ray_enabled"), &PhysicsTestMotionParameters2D::set_collide_separation_ray_enabled);
+
+ ClassDB::bind_method(D_METHOD("get_exclude_bodies"), &PhysicsTestMotionParameters2D::get_exclude_bodies);
+ ClassDB::bind_method(D_METHOD("set_exclude_bodies"), &PhysicsTestMotionParameters2D::set_exclude_bodies);
+
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "from"), "set_from", "get_from");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "set_motion", "get_motion");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin"), "set_margin", "get_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_separation_ray"), "set_collide_separation_ray_enabled", "is_collide_separation_ray_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies"), "set_exclude_bodies", "get_exclude_bodies");
+}
+
+///////////////////////////////
+
Vector2 PhysicsTestMotionResult2D::get_travel() const {
return result.travel;
}
@@ -448,6 +491,10 @@ int PhysicsTestMotionResult2D::get_collider_shape() const {
return result.collider_shape;
}
+int PhysicsTestMotionResult2D::get_collision_local_shape() const {
+ return result.collision_local_shape;
+}
+
real_t PhysicsTestMotionResult2D::get_collision_depth() const {
return result.collision_depth;
}
@@ -470,36 +517,23 @@ void PhysicsTestMotionResult2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_collider_rid"), &PhysicsTestMotionResult2D::get_collider_rid);
ClassDB::bind_method(D_METHOD("get_collider"), &PhysicsTestMotionResult2D::get_collider);
ClassDB::bind_method(D_METHOD("get_collider_shape"), &PhysicsTestMotionResult2D::get_collider_shape);
+ ClassDB::bind_method(D_METHOD("get_collision_local_shape"), &PhysicsTestMotionResult2D::get_collision_local_shape);
ClassDB::bind_method(D_METHOD("get_collision_depth"), &PhysicsTestMotionResult2D::get_collision_depth);
ClassDB::bind_method(D_METHOD("get_collision_safe_fraction"), &PhysicsTestMotionResult2D::get_collision_safe_fraction);
ClassDB::bind_method(D_METHOD("get_collision_unsafe_fraction"), &PhysicsTestMotionResult2D::get_collision_unsafe_fraction);
-
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "travel"), "", "get_travel");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "remainder"), "", "get_remainder");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "collision_point"), "", "get_collision_point");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "collision_normal"), "", "get_collision_normal");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "collider_velocity"), "", "get_collider_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_id", PROPERTY_HINT_OBJECT_ID), "", "get_collider_id");
- ADD_PROPERTY(PropertyInfo(Variant::RID, "collider_rid"), "", "get_collider_rid");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "collider"), "", "get_collider");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_shape"), "", "get_collider_shape");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_depth"), "", "get_collision_depth");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_safe_fraction"), "", "get_collision_safe_fraction");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_unsafe_fraction"), "", "get_collision_unsafe_fraction");
}
///////////////////////////////////////
-bool PhysicsServer2D::_body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, const Ref<PhysicsTestMotionResult2D> &p_result, bool p_collide_separation_ray, const Vector<RID> &p_exclude) {
- MotionResult *r = nullptr;
+bool PhysicsServer2D::_body_test_motion(RID p_body, const Ref<PhysicsTestMotionParameters2D> &p_parameters, const Ref<PhysicsTestMotionResult2D> &p_result) {
+ ERR_FAIL_COND_V(!p_parameters.is_valid(), false);
+
+ MotionResult *result_ptr = nullptr;
if (p_result.is_valid()) {
- r = p_result->get_result_ptr();
- }
- Set<RID> exclude;
- for (int i = 0; i < p_exclude.size(); i++) {
- exclude.insert(p_exclude[i]);
+ result_ptr = p_result->get_result_ptr();
}
- return body_test_motion(p_body, p_from, p_motion, p_margin, r, p_collide_separation_ray, exclude);
+
+ return body_test_motion(p_body, p_parameters->get_parameters(), result_ptr);
}
void PhysicsServer2D::_bind_methods() {
@@ -626,7 +660,7 @@ void PhysicsServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_force_integration_callback", "body", "callable", "userdata"), &PhysicsServer2D::body_set_force_integration_callback, DEFVAL(Variant()));
- ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "margin", "result", "collide_separation_ray", "exclude"), &PhysicsServer2D::_body_test_motion, DEFVAL(0.08), DEFVAL(Variant()), DEFVAL(false), DEFVAL(Array()));
+ ClassDB::bind_method(D_METHOD("body_test_motion", "body", "parameters", "result"), &PhysicsServer2D::_body_test_motion, DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &PhysicsServer2D::body_get_direct_state);
diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h
index ed0584aaa6..1028be05b7 100644
--- a/servers/physics_server_2d.h
+++ b/servers/physics_server_2d.h
@@ -198,6 +198,7 @@ public:
PhysicsDirectSpaceState2D();
};
+class PhysicsTestMotionParameters2D;
class PhysicsTestMotionResult2D;
class PhysicsServer2D : public Object {
@@ -205,7 +206,7 @@ class PhysicsServer2D : public Object {
static PhysicsServer2D *singleton;
- virtual bool _body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, const Ref<PhysicsTestMotionResult2D> &p_result = Ref<PhysicsTestMotionResult2D>(), bool p_collide_separation_ray = false, const Vector<RID> &p_exclude = Vector<RID>());
+ virtual bool _body_test_motion(RID p_body, const Ref<PhysicsTestMotionParameters2D> &p_parameters, const Ref<PhysicsTestMotionResult2D> &p_result = Ref<PhysicsTestMotionResult2D>());
protected:
static void _bind_methods();
@@ -465,6 +466,21 @@ public:
// this function only works on physics process, errors and returns null otherwise
virtual PhysicsDirectBodyState2D *body_get_direct_state(RID p_body) = 0;
+ struct MotionParameters {
+ Transform2D from;
+ Vector2 motion;
+ real_t margin = 0.08;
+ bool collide_separation_ray = false;
+ Set<RID> exclude_bodies;
+
+ MotionParameters() {}
+
+ MotionParameters(const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08) :
+ from(p_from),
+ motion(p_motion),
+ margin(p_margin) {}
+ };
+
struct MotionResult {
Vector2 travel;
Vector2 remainder;
@@ -485,18 +501,7 @@ public:
}
};
- virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, MotionResult *r_result = nullptr, bool p_collide_separation_ray = false, const Set<RID> &p_exclude = Set<RID>()) = 0;
-
- struct SeparationResult {
- real_t collision_depth;
- Vector2 collision_point;
- Vector2 collision_normal;
- Vector2 collider_velocity;
- int collision_local_shape;
- ObjectID collider_id;
- RID collider;
- int collider_shape;
- };
+ virtual bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) = 0;
/* JOINT API */
@@ -579,11 +584,37 @@ public:
~PhysicsServer2D();
};
+class PhysicsTestMotionParameters2D : public RefCounted {
+ GDCLASS(PhysicsTestMotionParameters2D, RefCounted);
+
+ PhysicsServer2D::MotionParameters parameters;
+
+protected:
+ static void _bind_methods();
+
+public:
+ const PhysicsServer2D::MotionParameters &get_parameters() const { return parameters; }
+
+ const Transform2D &get_from() const { return parameters.from; }
+ void set_from(const Transform2D &p_from) { parameters.from = p_from; }
+
+ const Vector2 &get_motion() const { return parameters.motion; }
+ void set_motion(const Vector2 &p_motion) { parameters.motion = p_motion; }
+
+ real_t get_margin() const { return parameters.margin; }
+ void set_margin(real_t p_margin) { parameters.margin = p_margin; }
+
+ bool is_collide_separation_ray_enabled() const { return parameters.collide_separation_ray; }
+ void set_collide_separation_ray_enabled(bool p_enabled) { parameters.collide_separation_ray = p_enabled; }
+
+ Vector<RID> get_exclude_bodies() const;
+ void set_exclude_bodies(const Vector<RID> &p_exclude);
+};
+
class PhysicsTestMotionResult2D : public RefCounted {
GDCLASS(PhysicsTestMotionResult2D, RefCounted);
PhysicsServer2D::MotionResult result;
- friend class PhysicsServer2D;
protected:
static void _bind_methods();
@@ -601,6 +632,7 @@ public:
RID get_collider_rid() const;
Object *get_collider() const;
int get_collider_shape() const;
+ int get_collision_local_shape() const;
real_t get_collision_depth() const;
real_t get_collision_safe_fraction() const;
real_t get_collision_unsafe_fraction() const;
diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp
index f444c2883d..1b47eba134 100644
--- a/servers/physics_server_3d.cpp
+++ b/servers/physics_server_3d.cpp
@@ -362,6 +362,53 @@ void PhysicsDirectSpaceState3D::_bind_methods() {
///////////////////////////////
+Vector<RID> PhysicsTestMotionParameters3D::get_exclude_bodies() const {
+ Vector<RID> exclude;
+ exclude.resize(parameters.exclude_bodies.size());
+
+ int body_index = 0;
+ for (RID body : parameters.exclude_bodies) {
+ exclude.write[body_index++] = body;
+ }
+
+ return exclude;
+}
+
+void PhysicsTestMotionParameters3D::set_exclude_bodies(const Vector<RID> &p_exclude) {
+ for (RID body : p_exclude) {
+ parameters.exclude_bodies.insert(body);
+ }
+}
+
+void PhysicsTestMotionParameters3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_from"), &PhysicsTestMotionParameters3D::get_from);
+ ClassDB::bind_method(D_METHOD("set_from"), &PhysicsTestMotionParameters3D::set_from);
+
+ ClassDB::bind_method(D_METHOD("get_motion"), &PhysicsTestMotionParameters3D::get_motion);
+ ClassDB::bind_method(D_METHOD("set_motion"), &PhysicsTestMotionParameters3D::set_motion);
+
+ ClassDB::bind_method(D_METHOD("get_margin"), &PhysicsTestMotionParameters3D::get_margin);
+ ClassDB::bind_method(D_METHOD("set_margin"), &PhysicsTestMotionParameters3D::set_margin);
+
+ ClassDB::bind_method(D_METHOD("get_max_collisions"), &PhysicsTestMotionParameters3D::get_max_collisions);
+ ClassDB::bind_method(D_METHOD("set_max_collisions"), &PhysicsTestMotionParameters3D::set_max_collisions);
+
+ ClassDB::bind_method(D_METHOD("is_collide_separation_ray_enabled"), &PhysicsTestMotionParameters3D::is_collide_separation_ray_enabled);
+ ClassDB::bind_method(D_METHOD("set_collide_separation_ray_enabled"), &PhysicsTestMotionParameters3D::set_collide_separation_ray_enabled);
+
+ ClassDB::bind_method(D_METHOD("get_exclude_bodies"), &PhysicsTestMotionParameters3D::get_exclude_bodies);
+ ClassDB::bind_method(D_METHOD("set_exclude_bodies"), &PhysicsTestMotionParameters3D::set_exclude_bodies);
+
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "from"), "set_from", "get_from");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "motion"), "set_motion", "get_motion");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin"), "set_margin", "get_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_collisions"), "set_max_collisions", "get_max_collisions");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_separation_ray"), "set_collide_separation_ray_enabled", "is_collide_separation_ray_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies"), "set_exclude_bodies", "get_exclude_bodies");
+}
+
+///////////////////////////////
+
Vector3 PhysicsTestMotionResult3D::get_travel() const {
return result.travel;
}
@@ -370,12 +417,12 @@ Vector3 PhysicsTestMotionResult3D::get_remainder() const {
return result.remainder;
}
-real_t PhysicsTestMotionResult3D::get_safe_fraction() const {
- return result.safe_fraction;
+real_t PhysicsTestMotionResult3D::get_collision_safe_fraction() const {
+ return result.collision_safe_fraction;
}
-real_t PhysicsTestMotionResult3D::get_unsafe_fraction() const {
- return result.unsafe_fraction;
+real_t PhysicsTestMotionResult3D::get_collision_unsafe_fraction() const {
+ return result.collision_unsafe_fraction;
}
int PhysicsTestMotionResult3D::get_collision_count() const {
@@ -417,48 +464,21 @@ int PhysicsTestMotionResult3D::get_collider_shape(int p_collision_index) const {
return result.collisions[p_collision_index].collider_shape;
}
+int PhysicsTestMotionResult3D::get_collision_local_shape(int p_collision_index) const {
+ ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, 0);
+ return result.collisions[p_collision_index].local_shape;
+}
+
real_t PhysicsTestMotionResult3D::get_collision_depth(int p_collision_index) const {
ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, 0.0);
return result.collisions[p_collision_index].depth;
}
-Vector3 PhysicsTestMotionResult3D::get_best_collision_point() const {
- return result.collision_count ? get_collision_point() : Vector3();
-}
-
-Vector3 PhysicsTestMotionResult3D::get_best_collision_normal() const {
- return result.collision_count ? get_collision_normal() : Vector3();
-}
-
-Vector3 PhysicsTestMotionResult3D::get_best_collider_velocity() const {
- return result.collision_count ? get_collider_velocity() : Vector3();
-}
-
-ObjectID PhysicsTestMotionResult3D::get_best_collider_id() const {
- return result.collision_count ? get_collider_id() : ObjectID();
-}
-
-RID PhysicsTestMotionResult3D::get_best_collider_rid() const {
- return result.collision_count ? get_collider_rid() : RID();
-}
-
-Object *PhysicsTestMotionResult3D::get_best_collider() const {
- return result.collision_count ? get_collider() : nullptr;
-}
-
-int PhysicsTestMotionResult3D::get_best_collider_shape() const {
- return result.collision_count ? get_collider_shape() : 0;
-}
-
-real_t PhysicsTestMotionResult3D::get_best_collision_depth() const {
- return result.collision_count ? get_collision_depth() : 0.0;
-}
-
void PhysicsTestMotionResult3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_travel"), &PhysicsTestMotionResult3D::get_travel);
ClassDB::bind_method(D_METHOD("get_remainder"), &PhysicsTestMotionResult3D::get_remainder);
- ClassDB::bind_method(D_METHOD("get_safe_fraction"), &PhysicsTestMotionResult3D::get_safe_fraction);
- ClassDB::bind_method(D_METHOD("get_unsafe_fraction"), &PhysicsTestMotionResult3D::get_unsafe_fraction);
+ ClassDB::bind_method(D_METHOD("get_collision_safe_fraction"), &PhysicsTestMotionResult3D::get_collision_safe_fraction);
+ ClassDB::bind_method(D_METHOD("get_collision_unsafe_fraction"), &PhysicsTestMotionResult3D::get_collision_unsafe_fraction);
ClassDB::bind_method(D_METHOD("get_collision_count"), &PhysicsTestMotionResult3D::get_collision_count);
ClassDB::bind_method(D_METHOD("get_collision_point", "collision_index"), &PhysicsTestMotionResult3D::get_collision_point, DEFVAL(0));
ClassDB::bind_method(D_METHOD("get_collision_normal", "collision_index"), &PhysicsTestMotionResult3D::get_collision_normal, DEFVAL(0));
@@ -467,44 +487,21 @@ void PhysicsTestMotionResult3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_collider_rid", "collision_index"), &PhysicsTestMotionResult3D::get_collider_rid, DEFVAL(0));
ClassDB::bind_method(D_METHOD("get_collider", "collision_index"), &PhysicsTestMotionResult3D::get_collider, DEFVAL(0));
ClassDB::bind_method(D_METHOD("get_collider_shape", "collision_index"), &PhysicsTestMotionResult3D::get_collider_shape, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_collision_local_shape", "collision_index"), &PhysicsTestMotionResult3D::get_collision_local_shape, DEFVAL(0));
ClassDB::bind_method(D_METHOD("get_collision_depth", "collision_index"), &PhysicsTestMotionResult3D::get_collision_depth, DEFVAL(0));
-
- ClassDB::bind_method(D_METHOD("get_best_collision_point"), &PhysicsTestMotionResult3D::get_best_collision_point);
- ClassDB::bind_method(D_METHOD("get_best_collision_normal"), &PhysicsTestMotionResult3D::get_best_collision_normal);
- ClassDB::bind_method(D_METHOD("get_best_collider_velocity"), &PhysicsTestMotionResult3D::get_best_collider_velocity);
- ClassDB::bind_method(D_METHOD("get_best_collider_id"), &PhysicsTestMotionResult3D::get_best_collider_id);
- ClassDB::bind_method(D_METHOD("get_best_collider_rid"), &PhysicsTestMotionResult3D::get_best_collider_rid);
- ClassDB::bind_method(D_METHOD("get_best_collider"), &PhysicsTestMotionResult3D::get_best_collider);
- ClassDB::bind_method(D_METHOD("get_best_collider_shape"), &PhysicsTestMotionResult3D::get_best_collider_shape);
- ClassDB::bind_method(D_METHOD("get_best_collision_depth"), &PhysicsTestMotionResult3D::get_best_collision_depth);
-
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "travel"), "", "get_travel");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "remainder"), "", "get_remainder");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "safe_fraction"), "", "get_safe_fraction");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "unsafe_fraction"), "", "get_unsafe_fraction");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_count"), "", "get_collision_count");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "collision_point"), "", "get_best_collision_point");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "collision_normal"), "", "get_best_collision_normal");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "collider_velocity"), "", "get_best_collider_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_id", PROPERTY_HINT_OBJECT_ID), "", "get_best_collider_id");
- ADD_PROPERTY(PropertyInfo(Variant::RID, "collider_rid"), "", "get_best_collider_rid");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "collider"), "", "get_best_collider");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_shape"), "", "get_best_collider_shape");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_depth"), "", "get_best_collision_depth");
}
///////////////////////////////////////
-bool PhysicsServer3D::_body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, const Ref<PhysicsTestMotionResult3D> &p_result, bool p_collide_separation_ray, const Vector<RID> &p_exclude, int p_max_collisions) {
- MotionResult *r = nullptr;
+bool PhysicsServer3D::_body_test_motion(RID p_body, const Ref<PhysicsTestMotionParameters3D> &p_parameters, const Ref<PhysicsTestMotionResult3D> &p_result) {
+ ERR_FAIL_COND_V(!p_parameters.is_valid(), false);
+
+ MotionResult *result_ptr = nullptr;
if (p_result.is_valid()) {
- r = p_result->get_result_ptr();
+ result_ptr = p_result->get_result_ptr();
}
- Set<RID> exclude;
- for (int i = 0; i < p_exclude.size(); i++) {
- exclude.insert(p_exclude[i]);
- }
- return body_test_motion(p_body, p_from, p_motion, p_margin, r, p_max_collisions, p_collide_separation_ray, exclude);
+
+ return body_test_motion(p_body, p_parameters->get_parameters(), result_ptr);
}
RID PhysicsServer3D::shape_create(ShapeType p_shape) {
@@ -662,7 +659,7 @@ void PhysicsServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_ray_pickable", "body", "enable"), &PhysicsServer3D::body_set_ray_pickable);
- ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "margin", "result", "collide_separation_ray", "exclude", "max_collisions"), &PhysicsServer3D::_body_test_motion, DEFVAL(0.001), DEFVAL(Variant()), DEFVAL(false), DEFVAL(Array()), DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("body_test_motion", "body", "parameters", "result"), &PhysicsServer3D::_body_test_motion, DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &PhysicsServer3D::body_get_direct_state);
diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h
index dbd734ba32..3d884de095 100644
--- a/servers/physics_server_3d.h
+++ b/servers/physics_server_3d.h
@@ -203,6 +203,7 @@ public:
virtual ~RenderingServerHandler() {}
};
+class PhysicsTestMotionParameters3D;
class PhysicsTestMotionResult3D;
class PhysicsServer3D : public Object {
@@ -210,7 +211,7 @@ class PhysicsServer3D : public Object {
static PhysicsServer3D *singleton;
- virtual bool _body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, const Ref<PhysicsTestMotionResult3D> &p_result = Ref<PhysicsTestMotionResult3D>(), bool p_collide_separation_ray = false, const Vector<RID> &p_exclude = Vector<RID>(), int p_max_collisions = 1);
+ virtual bool _body_test_motion(RID p_body, const Ref<PhysicsTestMotionParameters3D> &p_parameters, const Ref<PhysicsTestMotionResult3D> &p_result = Ref<PhysicsTestMotionResult3D>());
protected:
static void _bind_methods();
@@ -483,6 +484,22 @@ public:
// this function only works on physics process, errors and returns null otherwise
virtual PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) = 0;
+ struct MotionParameters {
+ Transform3D from;
+ Vector3 motion;
+ real_t margin = 0.001;
+ int max_collisions = 1;
+ bool collide_separation_ray = false;
+ Set<RID> exclude_bodies;
+
+ MotionParameters() {}
+
+ MotionParameters(const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001) :
+ from(p_from),
+ motion(p_motion),
+ margin(p_margin) {}
+ };
+
struct MotionCollision {
Vector3 position;
Vector3 normal;
@@ -501,15 +518,15 @@ public:
struct MotionResult {
Vector3 travel;
Vector3 remainder;
- real_t safe_fraction = 0.0;
- real_t unsafe_fraction = 0.0;
+ real_t collision_safe_fraction = 0.0;
+ real_t collision_unsafe_fraction = 0.0;
static const int MAX_COLLISIONS = 32;
MotionCollision collisions[MAX_COLLISIONS];
int collision_count = 0;
};
- virtual bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = nullptr, int p_max_collisions = 1, bool p_collide_separation_ray = false, const Set<RID> &p_exclude = Set<RID>()) = 0;
+ virtual bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) = 0;
/* SOFT BODY */
@@ -760,11 +777,40 @@ public:
~PhysicsServer3D();
};
+class PhysicsTestMotionParameters3D : public RefCounted {
+ GDCLASS(PhysicsTestMotionParameters3D, RefCounted);
+
+ PhysicsServer3D::MotionParameters parameters;
+
+protected:
+ static void _bind_methods();
+
+public:
+ const PhysicsServer3D::MotionParameters &get_parameters() const { return parameters; }
+
+ const Transform3D &get_from() const { return parameters.from; }
+ void set_from(const Transform3D &p_from) { parameters.from = p_from; }
+
+ const Vector3 &get_motion() const { return parameters.motion; }
+ void set_motion(const Vector3 &p_motion) { parameters.motion = p_motion; }
+
+ real_t get_margin() const { return parameters.margin; }
+ void set_margin(real_t p_margin) { parameters.margin = p_margin; }
+
+ int get_max_collisions() const { return parameters.max_collisions; }
+ void set_max_collisions(int p_max_collisions) { parameters.max_collisions = p_max_collisions; }
+
+ bool is_collide_separation_ray_enabled() const { return parameters.collide_separation_ray; }
+ void set_collide_separation_ray_enabled(bool p_enabled) { parameters.collide_separation_ray = p_enabled; }
+
+ Vector<RID> get_exclude_bodies() const;
+ void set_exclude_bodies(const Vector<RID> &p_exclude);
+};
+
class PhysicsTestMotionResult3D : public RefCounted {
GDCLASS(PhysicsTestMotionResult3D, RefCounted);
PhysicsServer3D::MotionResult result;
- friend class PhysicsServer3D;
protected:
static void _bind_methods();
@@ -774,8 +820,8 @@ public:
Vector3 get_travel() const;
Vector3 get_remainder() const;
- real_t get_safe_fraction() const;
- real_t get_unsafe_fraction() const;
+ real_t get_collision_safe_fraction() const;
+ real_t get_collision_unsafe_fraction() const;
int get_collision_count() const;
@@ -786,16 +832,8 @@ public:
RID get_collider_rid(int p_collision_index = 0) const;
Object *get_collider(int p_collision_index = 0) const;
int get_collider_shape(int p_collision_index = 0) const;
+ int get_collision_local_shape(int p_collision_index = 0) const;
real_t get_collision_depth(int p_collision_index = 0) const;
-
- Vector3 get_best_collision_point() const;
- Vector3 get_best_collision_normal() const;
- Vector3 get_best_collider_velocity() const;
- ObjectID get_best_collider_id() const;
- RID get_best_collider_rid() const;
- Object *get_best_collider() const;
- int get_best_collider_shape() const;
- real_t get_best_collision_depth() const;
};
typedef PhysicsServer3D *(*CreatePhysicsServer3DCallback)();
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index c5effeb243..28cd8374c0 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -208,12 +208,14 @@ void register_server_types() {
GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState2D);
GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState2D);
+ GDREGISTER_CLASS(PhysicsTestMotionParameters2D);
GDREGISTER_CLASS(PhysicsTestMotionResult2D);
GDREGISTER_CLASS(PhysicsShapeQueryParameters2D);
GDREGISTER_CLASS(PhysicsShapeQueryParameters3D);
GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState3D);
GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState3D);
+ GDREGISTER_CLASS(PhysicsTestMotionParameters3D);
GDREGISTER_CLASS(PhysicsTestMotionResult3D);
// Physics 2D