summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/math/quaternion.cpp52
-rw-r--r--doc/classes/ShapeCast2D.xml18
-rw-r--r--doc/classes/ShapeCast3D.xml24
-rw-r--r--platform/linuxbsd/detect.py1
4 files changed, 50 insertions, 45 deletions
diff --git a/core/math/quaternion.cpp b/core/math/quaternion.cpp
index 252c108166..c681c60694 100644
--- a/core/math/quaternion.cpp
+++ b/core/math/quaternion.cpp
@@ -188,45 +188,49 @@ Quaternion Quaternion::spherical_cubic_interpolate(const Quaternion &p_b, const
ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
#endif
- Quaternion ret_q = *this;
+ Quaternion from_q = *this;
Quaternion pre_q = p_pre_a;
Quaternion to_q = p_b;
Quaternion post_q = p_post_b;
// Align flip phases.
- ret_q = Basis(ret_q).get_rotation_quaternion();
+ from_q = Basis(from_q).get_rotation_quaternion();
pre_q = Basis(pre_q).get_rotation_quaternion();
to_q = Basis(to_q).get_rotation_quaternion();
post_q = Basis(post_q).get_rotation_quaternion();
// Flip quaternions to shortest path if necessary.
- bool flip1 = signbit(ret_q.dot(pre_q));
+ bool flip1 = signbit(from_q.dot(pre_q));
pre_q = flip1 ? -pre_q : pre_q;
- bool flip2 = signbit(ret_q.dot(to_q));
+ bool flip2 = signbit(from_q.dot(to_q));
to_q = flip2 ? -to_q : to_q;
bool flip3 = flip2 ? to_q.dot(post_q) <= 0 : signbit(to_q.dot(post_q));
post_q = flip3 ? -post_q : post_q;
- if (flip1 || flip2 || flip3) {
- // Angle is too large, calc by Approximate.
- ret_q.x = Math::cubic_interpolate(ret_q.x, to_q.x, pre_q.x, post_q.x, p_weight);
- ret_q.y = Math::cubic_interpolate(ret_q.y, to_q.y, pre_q.y, post_q.y, p_weight);
- ret_q.z = Math::cubic_interpolate(ret_q.z, to_q.z, pre_q.z, post_q.z, p_weight);
- ret_q.w = Math::cubic_interpolate(ret_q.w, to_q.w, pre_q.w, post_q.w, p_weight);
- ret_q.normalize();
- } else {
- // Calc by Expmap.
- Quaternion ln_ret = ret_q.log();
- Quaternion ln_to = to_q.log();
- Quaternion ln_pre = pre_q.log();
- Quaternion ln_post = post_q.log();
- Quaternion ln = Quaternion(0, 0, 0, 0);
- ln.x = Math::cubic_interpolate(ln_ret.x, ln_to.x, ln_pre.x, ln_post.x, p_weight);
- ln.y = Math::cubic_interpolate(ln_ret.y, ln_to.y, ln_pre.y, ln_post.y, p_weight);
- ln.z = Math::cubic_interpolate(ln_ret.z, ln_to.z, ln_pre.z, ln_post.z, p_weight);
- ret_q = ln.exp();
- }
- return ret_q;
+ // Calc by Expmap in from_q space.
+ Quaternion ln_from = Quaternion(0, 0, 0, 0);
+ Quaternion ln_to = (from_q.inverse() * to_q).log();
+ Quaternion ln_pre = (from_q.inverse() * pre_q).log();
+ Quaternion ln_post = (from_q.inverse() * post_q).log();
+ Quaternion ln = Quaternion(0, 0, 0, 0);
+ ln.x = Math::cubic_interpolate(ln_from.x, ln_to.x, ln_pre.x, ln_post.x, p_weight);
+ ln.y = Math::cubic_interpolate(ln_from.y, ln_to.y, ln_pre.y, ln_post.y, p_weight);
+ ln.z = Math::cubic_interpolate(ln_from.z, ln_to.z, ln_pre.z, ln_post.z, p_weight);
+ Quaternion q1 = from_q * ln.exp();
+
+ // Calc by Expmap in to_q space.
+ ln_from = (to_q.inverse() * from_q).log();
+ ln_to = Quaternion(0, 0, 0, 0);
+ ln_pre = (to_q.inverse() * pre_q).log();
+ ln_post = (to_q.inverse() * post_q).log();
+ ln = Quaternion(0, 0, 0, 0);
+ ln.x = Math::cubic_interpolate(ln_from.x, ln_to.x, ln_pre.x, ln_post.x, p_weight);
+ ln.y = Math::cubic_interpolate(ln_from.y, ln_to.y, ln_pre.y, ln_post.y, p_weight);
+ ln.z = Math::cubic_interpolate(ln_from.z, ln_to.z, ln_pre.z, ln_post.z, p_weight);
+ Quaternion q2 = to_q * ln.exp();
+
+ // To cancel error made by Expmap ambiguity, do blends.
+ return q1.slerp(q2, p_weight);
}
Quaternion::operator String() const {
diff --git a/doc/classes/ShapeCast2D.xml b/doc/classes/ShapeCast2D.xml
index 5fcb60dd09..70da03dc6e 100644
--- a/doc/classes/ShapeCast2D.xml
+++ b/doc/classes/ShapeCast2D.xml
@@ -6,7 +6,7 @@
<description>
Shape casting allows to detect collision objects by sweeping the [member shape] along the cast direction determined by [member target_position] (useful for things like beam weapons).
Immediate collision overlaps can be done with the [member target_position] set to [code]Vector2(0, 0)[/code] and by calling [method force_shapecast_update] within the same [b]physics_frame[/b]. This also helps to overcome some limitations of [Area2D] when used as a continuous detection area, often requiring waiting a couple of frames before collision information is available to [Area2D] nodes, and when using the signals creates unnecessary complexity.
- The node can detect multiple collision objects, but usually the first detected collision
+ The node can detect multiple collision objects, but it's usually used to detect the first collision.
[b]Note:[/b] shape casting is more computationally expensive compared to ray casting.
</description>
<tutorials>
@@ -42,27 +42,27 @@
<method name="get_closest_collision_safe_fraction" qualifiers="const">
<return type="float" />
<description>
- The fraction of the motion (between 0 and 1) of how far the shape can move without triggering a collision. The motion is determined by [member target_position].
+ The fraction from the [ShapeCast2D]'s origin to its [member target_position] (between 0 and 1) of how far the shape can move without triggering a collision.
</description>
</method>
<method name="get_closest_collision_unsafe_fraction" qualifiers="const">
<return type="float" />
<description>
- The fraction of the motion (between 0 and 1) when the shape triggers a collision. The motion is determined by [member target_position].
+ The fraction from the [ShapeCast2D]'s origin to its [member target_position] (between 0 and 1) of how far the shape must move to trigger a collision.
</description>
</method>
<method name="get_collider" qualifiers="const">
<return type="Object" />
<argument index="0" name="index" type="int" />
<description>
- Returns the [Object] of one of the multiple collisions at [code]index[/code], or [code]null[/code] if no object is intersecting the shape (i.e. [method is_colliding] returns [code]false[/code]).
+ Returns the collided [Object] of one of the multiple collisions at [code]index[/code], or [code]null[/code] if no object is intersecting the shape (i.e. [method is_colliding] returns [code]false[/code]).
</description>
</method>
<method name="get_collider_shape" qualifiers="const">
<return type="int" />
<argument index="0" name="index" type="int" />
<description>
- Returns the shape ID of one of the multiple collisions at [code]index[/code] that the shape intersects, or [code]0[/code] if no object is intersecting the shape (i.e. [method is_colliding] returns [code]false[/code]).
+ Returns the shape ID of the colliding shape of one of the multiple collisions at [code]index[/code], or [code]0[/code] if no object is intersecting the shape (i.e. [method is_colliding] returns [code]false[/code]).
</description>
</method>
<method name="get_collision_count" qualifiers="const">
@@ -82,14 +82,14 @@
<return type="Vector2" />
<argument index="0" name="index" type="int" />
<description>
- Returns the normal containing one of the multiple collisions at [code]index[/code] of the intersecting object.
+ Returns the normal of one of the multiple collisions at [code]index[/code] of the intersecting object.
</description>
</method>
<method name="get_collision_point" qualifiers="const">
<return type="Vector2" />
<argument index="0" name="index" type="int" />
<description>
- Returns the collision point containing one of the multiple collisions at [code]index[/code] at which the shape intersects the object.
+ Returns the collision point of one of the multiple collisions at [code]index[/code] where the shape intersects the colliding object.
[b]Note:[/b] this point is in the [b]global[/b] coordinate system.
</description>
</method>
@@ -133,7 +133,7 @@
The shape's collision mask. Only objects in at least one collision layer enabled in the mask will be detected.
</member>
<member name="collision_result" type="Array" setter="" getter="_get_collision_result" default="[]">
- A complete collision information. The data returned is the same as in the [method PhysicsDirectSpaceState2D.get_rest_info] method.
+ Returns the complete collision information from the collision sweep. The data returned is the same as in the [method PhysicsDirectSpaceState2D.get_rest_info] method.
</member>
<member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="true">
If [code]true[/code], collisions will be reported.
@@ -148,7 +148,7 @@
The number of intersections can be limited with this parameter, to reduce the processing time.
</member>
<member name="shape" type="Shape2D" setter="set_shape" getter="get_shape">
- Any [Shape2D] derived shape used for collision queries.
+ The [Shape2D]-derived shape to be used for collision queries.
</member>
<member name="target_position" type="Vector2" setter="set_target_position" getter="get_target_position" default="Vector2(0, 50)">
The shape's destination point, relative to this node's [code]position[/code].
diff --git a/doc/classes/ShapeCast3D.xml b/doc/classes/ShapeCast3D.xml
index 1f2ea96f42..085bc9acd1 100644
--- a/doc/classes/ShapeCast3D.xml
+++ b/doc/classes/ShapeCast3D.xml
@@ -6,7 +6,7 @@
<description>
Shape casting allows to detect collision objects by sweeping the [member shape] along the cast direction determined by [member target_position] (useful for things like beam weapons).
Immediate collision overlaps can be done with the [member target_position] set to [code]Vector3(0, 0, 0)[/code] and by calling [method force_shapecast_update] within the same [b]physics_frame[/b]. This also helps to overcome some limitations of [Area3D] when used as a continuous detection area, often requiring waiting a couple of frames before collision information is available to [Area3D] nodes, and when using the signals creates unnecessary complexity.
- The node can detect multiple collision objects, but usually the first detected collision.
+ The node can detect multiple collision objects, but it's usually used to detect the first collision.
[b]Note:[/b] Shape casting is more computationally expensive compared to ray casting.
</description>
<tutorials>
@@ -29,7 +29,7 @@
<method name="clear_exceptions">
<return type="void" />
<description>
- Removes all collision exceptions for this shape.
+ Removes all collision exceptions for this [ShapeCast3D].
</description>
</method>
<method name="force_shapecast_update">
@@ -42,27 +42,27 @@
<method name="get_closest_collision_safe_fraction" qualifiers="const">
<return type="float" />
<description>
- The fraction of the motion (between 0 and 1) of how far the shape can move without triggering a collision. The motion is determined by [member target_position].
+ The fraction from the [ShapeCast3D]'s origin to its [member target_position] (between 0 and 1) of how far the shape can move without triggering a collision.
</description>
</method>
<method name="get_closest_collision_unsafe_fraction" qualifiers="const">
<return type="float" />
<description>
- The fraction of the motion (between 0 and 1) when the shape triggers a collision. The motion is determined by [member target_position].
+ The fraction from the [ShapeCast3D]'s origin to its [member target_position] (between 0 and 1) of how far the shape must move to trigger a collision.
</description>
</method>
<method name="get_collider" qualifiers="const">
<return type="Object" />
<argument index="0" name="index" type="int" />
<description>
- Returns the [Object] of one of the multiple collisions at [code]index[/code], or [code]null[/code] if no object is intersecting the shape (i.e. [method is_colliding] returns [code]false[/code]).
+ Returns the collided [Object] of one of the multiple collisions at [code]index[/code], or [code]null[/code] if no object is intersecting the shape (i.e. [method is_colliding] returns [code]false[/code]).
</description>
</method>
<method name="get_collider_shape" qualifiers="const">
<return type="int" />
<argument index="0" name="index" type="int" />
<description>
- Returns the shape ID of one of the multiple collisions at [code]index[/code] that the shape intersects, or [code]0[/code] if no object is intersecting the shape (i.e. [method is_colliding] returns [code]false[/code]).
+ Returns the shape ID of the colliding shape of one of the multiple collisions at [code]index[/code], or [code]0[/code] if no object is intersecting the shape (i.e. [method is_colliding] returns [code]false[/code]).
</description>
</method>
<method name="get_collision_count" qualifiers="const">
@@ -82,14 +82,14 @@
<return type="Vector3" />
<argument index="0" name="index" type="int" />
<description>
- Returns the normal containing one of the multiple collisions at [code]index[/code] of the intersecting object.
+ Returns the normal of one of the multiple collisions at [code]index[/code] of the intersecting object.
</description>
</method>
<method name="get_collision_point" qualifiers="const">
<return type="Vector3" />
<argument index="0" name="index" type="int" />
<description>
- Returns the collision point containing one of the multiple collisions at [code]index[/code] at which the shape intersects the object.
+ Returns the collision point of one of the multiple collisions at [code]index[/code] where the shape intersects the colliding object.
[b]Note:[/b] this point is in the [b]global[/b] coordinate system.
</description>
</method>
@@ -117,7 +117,7 @@
<return type="void" />
<argument index="0" name="resource" type="Resource" />
<description>
- Used internally to update the debug gizmo in the editor. Any code placed in this function will be called whenever the [member shape] resource is modified.
+ This method is used internally to update the debug gizmo in the editor. Any code placed in this function will be called whenever the [member shape] resource is modified.
</description>
</method>
<method name="set_collision_mask_value">
@@ -137,10 +137,10 @@
If [code]true[/code], collision with [PhysicsBody3D]s will be reported.
</member>
<member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1">
- The shape's collision mask. Only objects in at least one collision layer enabled in the mask will be detected.
+ The shape's collision mask. Only objects in at least one collision layer enabled in the mask will be detected. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information.
</member>
<member name="collision_result" type="Array" setter="" getter="_get_collision_result" default="[]">
- A complete collision information. The data returned is the same as in the [method PhysicsDirectSpaceState3D.get_rest_info] method.
+ Returns the complete collision information from the collision sweep. The data returned is the same as in the [method PhysicsDirectSpaceState3D.get_rest_info] method.
</member>
<member name="debug_shape_custom_color" type="Color" setter="set_debug_shape_custom_color" getter="get_debug_shape_custom_color" default="Color(0, 0, 0, 1)">
The custom color to use to draw the shape in the editor and at run-time if [b]Visible Collision Shapes[/b] is enabled in the [b]Debug[/b] menu. This color will be highlighted at run-time if the [ShapeCast3D] is colliding with something.
@@ -159,7 +159,7 @@
The number of intersections can be limited with this parameter, to reduce the processing time.
</member>
<member name="shape" type="Shape3D" setter="set_shape" getter="get_shape">
- Any [Shape3D] derived shape used for collision queries.
+ The [Shape3D]-derived shape to be used for collision queries.
</member>
<member name="target_position" type="Vector3" setter="set_target_position" getter="get_target_position" default="Vector3(0, -1, 0)">
The shape's destination point, relative to this node's [code]position[/code].
diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py
index 87fe2ced33..00e2b9e6eb 100644
--- a/platform/linuxbsd/detect.py
+++ b/platform/linuxbsd/detect.py
@@ -327,6 +327,7 @@ def configure(env):
env.Append(CPPDEFINES=["DBUS_ENABLED"])
env.ParseConfig("pkg-config dbus-1 --cflags") # Only cflags, we dlopen the library.
else:
+ env["dbus"] = False
print("Warning: D-Bus development libraries not found. Disabling screensaver prevention.")
if env["speechd"]: