summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/classes/float.xml8
-rw-r--r--doc/classes/int.xml2
-rw-r--r--methods.py9
-rw-r--r--modules/bullet/space_bullet.cpp25
4 files changed, 40 insertions, 4 deletions
diff --git a/doc/classes/float.xml b/doc/classes/float.xml
index 60878eb0bd..4bf04fe25f 100644
--- a/doc/classes/float.xml
+++ b/doc/classes/float.xml
@@ -4,9 +4,13 @@
Float built-in type.
</brief_description>
<description>
- Float built-in type.
+ The [float] built-in type is a 64-bit double-precision floating-point number, equivalent to [code]double[/code] in C++. This type has 14 reliable decimal digits of precision. The [float] type can be stored in [Variant], which is the generic type used by the engine. The maximum value of [float] is approximately [code]1.79769e308[/code], and the minimum is approximately [code]-1.79769e308[/code].
+ Many methods and properties in the engine use 32-bit single-precision floating-point numbers instead, equivalent to [code]float[/code] in C++, which have 6 reliable decimal digits of precision. For data structures such as [Vector2] and [Vector3], Godot uses 32-bit floating-point numbers by default, but it can be changed to use 64-bit doubles if Godot is compiled with the [code]float=64[/code] option.
+ Math done using the [float] type is not guaranteed to be exact or deterministic, and will often result in small errors. You should usually use the [method @GlobalScope.is_equal_approx] and [method @GlobalScope.is_zero_approx] methods instead of [code]==[/code] to compare [float] values for equality.
</description>
<tutorials>
+ <link title="Wikipedia: Double-precision floating-point format">https://en.wikipedia.org/wiki/Double-precision_floating-point_format</link>
+ <link title="Wikipedia: Single-precision floating-point format">https://en.wikipedia.org/wiki/Single-precision_floating-point_format</link>
</tutorials>
<methods>
<method name="float" qualifiers="constructor">
@@ -231,11 +235,13 @@
<method name="operator unary+" qualifiers="operator">
<return type="float" />
<description>
+ Returns the same value as if the [code]+[/code] was not there. Unary [code]+[/code] does nothing, but sometimes it can make your code more readable.
</description>
</method>
<method name="operator unary-" qualifiers="operator">
<return type="float" />
<description>
+ Returns the negative value of the [float]. If positive, turns the number negative. If negative, turns the number positive. With floats, the number zero can be either positive or negative.
</description>
</method>
</methods>
diff --git a/doc/classes/int.xml b/doc/classes/int.xml
index 84a01aa0d0..32b5fe1012 100644
--- a/doc/classes/int.xml
+++ b/doc/classes/int.xml
@@ -327,11 +327,13 @@
<method name="operator unary+" qualifiers="operator">
<return type="int" />
<description>
+ Returns the same value as if the [code]+[/code] was not there. Unary [code]+[/code] does nothing, but sometimes it can make your code more readable.
</description>
</method>
<method name="operator unary-" qualifiers="operator">
<return type="int" />
<description>
+ Returns the negated value of the [int]. If positive, turns the number negative. If negative, turns the number positive. If zero, does nothing.
</description>
</method>
<method name="operator |" qualifiers="operator">
diff --git a/methods.py b/methods.py
index 970bd10aa3..86a802bf5f 100644
--- a/methods.py
+++ b/methods.py
@@ -934,9 +934,12 @@ def show_progress(env):
def progress_finish(target, source, env):
nonlocal node_count, progressor
- with open(node_count_fname, "w") as f:
- f.write("%d\n" % node_count)
- progressor.delete(progressor.file_list())
+ try:
+ with open(node_count_fname, "w") as f:
+ f.write("%d\n" % node_count)
+ progressor.delete(progressor.file_list())
+ except Exception:
+ pass
try:
with open(node_count_fname) as f:
diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp
index c6d835742d..a9a811c445 100644
--- a/modules/bullet/space_bullet.cpp
+++ b/modules/bullet/space_bullet.cpp
@@ -945,6 +945,11 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform3D &p
G_TO_B(p_from, body_transform);
UNSCALE_BT_BASIS(body_transform);
+ if (!p_body->get_kinematic_utilities()) {
+ p_body->init_kinematic_utilities();
+ p_body->reload_kinematic_shapes();
+ }
+
btVector3 initial_recover_motion(0, 0, 0);
{ /// Phase one - multi shapes depenetration using margin
for (int t(RECOVERING_MOVEMENT_CYCLES); 0 < t; --t) {
@@ -958,6 +963,9 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform3D &p
btVector3 motion;
G_TO_B(p_motion, motion);
+ real_t total_length = motion.length();
+ real_t unsafe_fraction = 1.0;
+ real_t safe_fraction = 1.0;
{
// Phase two - sweep test, from a secure position without margin
@@ -1007,6 +1015,15 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform3D &p
dynamicsWorld->convexSweepTest(convex_shape_test, shape_world_from, shape_world_to, btResult, dynamicsWorld->getDispatchInfo().m_allowedCcdPenetration);
if (btResult.hasHit()) {
+ if (total_length > CMP_EPSILON) {
+ real_t hit_fraction = btResult.m_closestHitFraction * motion.length() / total_length;
+ if (hit_fraction < unsafe_fraction) {
+ unsafe_fraction = hit_fraction;
+ real_t margin = p_body->get_kinematic_utilities()->safe_margin;
+ safe_fraction = MAX(hit_fraction - (1 - ((total_length - margin) / total_length)), 0);
+ }
+ }
+
/// Since for each sweep test I fix the motion of new shapes in base the recover result,
/// if another shape will hit something it means that has a deepest penetration respect the previous shape
motion *= btResult.m_closestHitFraction;
@@ -1043,6 +1060,9 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform3D &p
r_result->collider_id = collisionObject->get_instance_id();
r_result->collider_shape = r_recover_result.other_compound_shape_index;
r_result->collision_local_shape = r_recover_result.local_shape_most_recovered;
+ r_result->collision_depth = Math::abs(r_recover_result.penetration_distance);
+ r_result->collision_safe_fraction = safe_fraction;
+ r_result->collision_unsafe_fraction = unsafe_fraction;
#if debug_test_motion
Vector3 sup_line2;
@@ -1067,6 +1087,11 @@ int SpaceBullet::test_ray_separation(RigidBodyBullet *p_body, const Transform3D
G_TO_B(p_transform, body_transform);
UNSCALE_BT_BASIS(body_transform);
+ if (!p_body->get_kinematic_utilities()) {
+ p_body->init_kinematic_utilities();
+ p_body->reload_kinematic_shapes();
+ }
+
btVector3 recover_motion(0, 0, 0);
int rays_found = 0;