GDScript: Clarified/fixed inaccuracies in the built-in function docs.

The input to smoothstep is not actually a weight, and the decscription
of smoothstep was pretty hard to understand and easy to misinterpret.

Clarified what it means to be approximately equal.

nearest_po2 does not do what the descriptions says it does. For one,
it returns the same power if the input is a power of 2. Second, it
returns 0 if the input is negative or 0, while the smallest possible
integral power of 2 actually is 1 (2^0 = 1). Due to the implementation
and how it is used in a lot of places, it does not seem wise to change
such a core function however, and I decided it is better to alter the
description of the built-in.

Added a few examples/clarifications/edge-cases.

(cherry picked from commit 7f9bfee0ac)
This commit is contained in:
Meriipu 2020-07-25 16:11:23 +02:00 committed by Rémi Verschelde
parent 5e978d1df5
commit 347a9df0a1
No known key found for this signature in database
GPG key ID: C3336907360768E1
3 changed files with 33 additions and 17 deletions

View file

@ -233,15 +233,19 @@ public:
static _ALWAYS_INLINE_ double range_lerp(double p_value, double p_istart, double p_istop, double p_ostart, double p_ostop) { return Math::lerp(p_ostart, p_ostop, Math::inverse_lerp(p_istart, p_istop, p_value)); }
static _ALWAYS_INLINE_ float range_lerp(float p_value, float p_istart, float p_istop, float p_ostart, float p_ostop) { return Math::lerp(p_ostart, p_ostop, Math::inverse_lerp(p_istart, p_istop, p_value)); }
static _ALWAYS_INLINE_ double smoothstep(double p_from, double p_to, double p_weight) {
if (is_equal_approx(p_from, p_to)) return p_from;
double x = CLAMP((p_weight - p_from) / (p_to - p_from), 0.0, 1.0);
return x * x * (3.0 - 2.0 * x);
static _ALWAYS_INLINE_ double smoothstep(double p_from, double p_to, double p_s) {
if (is_equal_approx(p_from, p_to)) {
return p_from;
}
double s = CLAMP((p_s - p_from) / (p_to - p_from), 0.0, 1.0);
return s * s * (3.0 - 2.0 * s);
}
static _ALWAYS_INLINE_ float smoothstep(float p_from, float p_to, float p_weight) {
if (is_equal_approx(p_from, p_to)) return p_from;
float x = CLAMP((p_weight - p_from) / (p_to - p_from), 0.0f, 1.0f);
return x * x * (3.0f - 2.0f * x);
static _ALWAYS_INLINE_ float smoothstep(float p_from, float p_to, float p_s) {
if (is_equal_approx(p_from, p_to)) {
return p_from;
}
float s = CLAMP((p_s - p_from) / (p_to - p_from), 0.0f, 1.0f);
return s * s * (3.0f - 2.0f * s);
}
static _ALWAYS_INLINE_ double move_toward(double p_from, double p_to, double p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SGN(p_to - p_from) * p_delta; }
static _ALWAYS_INLINE_ float move_toward(float p_from, float p_to, float p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SGN(p_to - p_from) * p_delta; }

View file

@ -320,7 +320,7 @@
</argument>
<description>
The natural exponential function. It raises the mathematical constant [b]e[/b] to the power of [code]s[/code] and returns it.
[b]e[/b] has an approximate value of 2.71828.
[b]e[/b] has an approximate value of 2.71828, and can be obtained with [code]exp(1)[/code].
For exponents to other bases use the method [method pow].
[codeblock]
a = exp(2) # Approximately 7.39
@ -501,6 +501,8 @@
</argument>
<description>
Returns [code]true[/code] if [code]a[/code] and [code]b[/code] are approximately equal to each other.
Here, approximately equal means that [code]a[/code] and [code]b[/code] are within a small internal epsilon of each other, which scales with the magnitude of the numbers.
Infinity values of the same sign are considered equal.
</description>
</method>
<method name="is_inf">
@ -638,6 +640,7 @@
[codeblock]
log(10) # Returns 2.302585
[/codeblock]
[b]Note:[/b] The logarithm of [code]0[/code] returns [code]-inf[/code], while negative values return [code]-nan[/code].
</description>
</method>
<method name="max">
@ -683,7 +686,9 @@
Moves [code]from[/code] toward [code]to[/code] by the [code]delta[/code] value.
Use a negative [code]delta[/code] value to move away.
[codeblock]
move_toward(5, 10, 4) # Returns 9
move_toward(10, 5, 4) # Returns 6
move_toward(10, 5, -1.5) # Returns 11.5
[/codeblock]
</description>
</method>
@ -693,12 +698,17 @@
<argument index="0" name="value" type="int">
</argument>
<description>
Returns the nearest larger power of 2 for integer [code]value[/code].
Returns the nearest equal or larger power of 2 for integer [code]value[/code].
In other words, returns the smallest value [code]a[/code] where [code]a = pow(2, n)[/code] such that [code]value &lt;= a[/code] for some non-negative integer [code]n[/code].
[codeblock]
nearest_po2(3) # Returns 4
nearest_po2(4) # Returns 4
nearest_po2(5) # Returns 8
nearest_po2(0) # Returns 0 (this may not be what you expect)
nearest_po2(-1) # Returns 0 (this may not be what you expect)
[/codeblock]
[b]WARNING:[/b] Due to the way it is implemented, this function returns [code]0[/code] rather than [code]1[/code] for non-positive values of [code]value[/code] (in reality, 1 is the smallest integer power of 2).
</description>
</method>
<method name="ord">
@ -1078,15 +1088,17 @@
</argument>
<argument index="1" name="to" type="float">
</argument>
<argument index="2" name="weight" type="float">
<argument index="2" name="s" type="float">
</argument>
<description>
Returns a number smoothly interpolated between the [code]from[/code] and [code]to[/code], based on the [code]weight[/code]. Similar to [method lerp], but interpolates faster at the beginning and slower at the end.
Returns the result of smoothly interpolating the value of [code]s[/code] between [code]0[/code] and [code]1[/code], based on the where [code]s[/code] lies with respect to the edges [code]from[/code] and [code]to[/code].
The return value is [code]0[/code] if [code]s &lt;= from[/code], and [code]1[/code] if [code]s &gt;= to[/code]. If [code]s[/code] lies between [code]from[/code] and [code]to[/code], the returned value follows an S-shaped curve that maps [code]s[/code] between [code]0[/code] and [code]1[/code].
This S-shaped curve is the cubic Hermite interpolator, given by [code]f(s) = 3*s^2 - 2*s^3[/code].
[codeblock]
smoothstep(0, 2, -5.0) # Returns 0.0
smoothstep(0, 2, 0.5) # Returns 0.15625
smoothstep(0, 2, 1.0) # Returns 0.5
smoothstep(0, 2, 2.0) # Returns 1.0
smoothstep(0, 2, 0.5) # Returns 0.15625
smoothstep(0, 2, 1.0) # Returns 0.5
smoothstep(0, 2, 2.0) # Returns 1.0
[/codeblock]
</description>
</method>
@ -1100,7 +1112,7 @@
[codeblock]
sqrt(9) # Returns 3
[/codeblock]
If you need negative inputs, use [code]System.Numerics.Complex[/code] in C#.
[b]Note:[/b]Negative values of [code]s[/code] return NaN. If you need negative inputs, use [code]System.Numerics.Complex[/code] in C#.
</description>
</method>
<method name="step_decimals">

View file

@ -1715,7 +1715,7 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
return mi;
} break;
case MATH_SMOOTHSTEP: {
MethodInfo mi("smoothstep", PropertyInfo(Variant::REAL, "from"), PropertyInfo(Variant::REAL, "to"), PropertyInfo(Variant::REAL, "weight"));
MethodInfo mi("smoothstep", PropertyInfo(Variant::REAL, "from"), PropertyInfo(Variant::REAL, "to"), PropertyInfo(Variant::REAL, "s"));
mi.return_val.type = Variant::REAL;
return mi;
} break;