Skip to content

Commit

Permalink
Merge pull request #76902 from lawnjelly/safe_acos
Browse files Browse the repository at this point in the history
[3.x] Make acos and asin safe
  • Loading branch information
akien-mga authored May 12, 2023
2 parents 3762fe3 + 6f8e632 commit bf56a3a
Show file tree
Hide file tree
Showing 7 changed files with 21 additions and 11 deletions.
1 change: 1 addition & 0 deletions core/math/basis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,7 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
// as we have reached here there are no singularities so we can handle normally
real_t s = Math::sqrt((elements[1][2] - elements[2][1]) * (elements[1][2] - elements[2][1]) + (elements[2][0] - elements[0][2]) * (elements[2][0] - elements[0][2]) + (elements[0][1] - elements[1][0]) * (elements[0][1] - elements[1][0])); // s=|axis||sin(angle)|, used to normalise

// acos does clamping.
angle = Math::acos((elements[0][0] + elements[1][1] + elements[2][2] - 1) / 2);
if (angle < 0) {
s = -s;
Expand Down
10 changes: 6 additions & 4 deletions core/math/math_funcs.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,13 @@ class Math {
static _ALWAYS_INLINE_ double tanh(double p_x) { return ::tanh(p_x); }
static _ALWAYS_INLINE_ float tanh(float p_x) { return ::tanhf(p_x); }

static _ALWAYS_INLINE_ double asin(double p_x) { return ::asin(p_x); }
static _ALWAYS_INLINE_ float asin(float p_x) { return ::asinf(p_x); }
// Always does clamping so always safe to use.
static _ALWAYS_INLINE_ double asin(double p_x) { return p_x < -1 ? (-Math_PI / 2) : (p_x > 1 ? (Math_PI / 2) : ::asin(p_x)); }
static _ALWAYS_INLINE_ float asin(float p_x) { return p_x < -1 ? (-Math_PI / 2) : (p_x > 1 ? (Math_PI / 2) : ::asinf(p_x)); }

static _ALWAYS_INLINE_ double acos(double p_x) { return ::acos(p_x); }
static _ALWAYS_INLINE_ float acos(float p_x) { return ::acosf(p_x); }
// Always does clamping so always safe to use.
static _ALWAYS_INLINE_ double acos(double p_x) { return p_x < -1 ? Math_PI : (p_x > 1 ? 0 : ::acos(p_x)); }
static _ALWAYS_INLINE_ float acos(float p_x) { return p_x < -1 ? Math_PI : (p_x > 1 ? 0 : ::acosf(p_x)); }

static _ALWAYS_INLINE_ double atan(double p_x) { return ::atan(p_x); }
static _ALWAYS_INLINE_ float atan(float p_x) { return ::atanf(p_x); }
Expand Down
4 changes: 3 additions & 1 deletion core/math/quat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@

real_t Quat::angle_to(const Quat &p_to) const {
real_t d = dot(p_to);
return Math::acos(CLAMP(d * d * 2 - 1, -1, 1));

// acos does clamping.
return Math::acos(d * d * 2 - 1);
}

// set_euler_xyz expects a vector containing the Euler angles in the format
Expand Down
4 changes: 2 additions & 2 deletions modules/gdscript/doc_classes/@GDScript.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
<return type="float" />
<argument index="0" name="s" type="float" />
<description>
Returns the arc cosine of [code]s[/code] in radians. Use to get the angle of cosine [code]s[/code]. [code]s[/code] must be between [code]-1.0[/code] and [code]1.0[/code] (inclusive), otherwise, [method acos] will return [constant NAN].
Returns the arc cosine of [code]s[/code] in radians. Use to get the angle of cosine [code]s[/code]. [code]s[/code] will be clamped between [code]-1.0[/code] and [code]1.0[/code] (inclusive), in order to prevent [method acos] from returning [constant NAN].
[codeblock]
# c is 0.523599 or 30 degrees if converted with rad2deg(s)
c = acos(0.866025)
Expand All @@ -63,7 +63,7 @@
<return type="float" />
<argument index="0" name="s" type="float" />
<description>
Returns the arc sine of [code]s[/code] in radians. Use to get the angle of sine [code]s[/code]. [code]s[/code] must be between [code]-1.0[/code] and [code]1.0[/code] (inclusive), otherwise, [method asin] will return [constant NAN].
Returns the arc sine of [code]s[/code] in radians. Use to get the angle of sine [code]s[/code]. [code]s[/code] will be clamped between [code]-1.0[/code] and [code]1.0[/code] (inclusive), in order to prevent [method asin] from returning [constant NAN].
[codeblock]
# s is 0.523599 or 30 degrees if converted with rad2deg(s)
s = asin(0.5)
Expand Down
4 changes: 3 additions & 1 deletion scene/3d/path.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,9 @@ void PathFollow::_update_transform(bool p_update_xyz_rot) {

Vector3 axis = t_prev.cross(t_cur);
float dot = t_prev.dot(t_cur);
float angle = Math::acos(CLAMP(dot, -1, 1));

// acos does clamping.
float angle = Math::acos(dot);

if (likely(!Math::is_zero_approx(angle))) {
if (rotation_mode == ROTATION_Y) {
Expand Down
3 changes: 2 additions & 1 deletion scene/animation/skeleton_ik.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,8 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove
const Vector3 rot_axis(initial_ori.cross(ci->current_ori).normalized());

if (rot_axis[0] != 0 && rot_axis[1] != 0 && rot_axis[2] != 0) {
const real_t rot_angle(Math::acos(CLAMP(initial_ori.dot(ci->current_ori), -1, 1)));
// acos does clamping.
const real_t rot_angle(Math::acos(initial_ori.dot(ci->current_ori)));
new_bone_pose.basis.rotate(rot_axis, rot_angle);
}

Expand Down
6 changes: 4 additions & 2 deletions scene/resources/sky.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,8 @@ Ref<Image> ProceduralSky::_generate_sky() {

normal.normalize();

float v_angle = Math::acos(CLAMP(normal.y, -1.0, 1.0));
// acos does clamping.
float v_angle = Math::acos(normal.y);

Color color;

Expand All @@ -192,7 +193,8 @@ Ref<Image> ProceduralSky::_generate_sky() {
color.g *= sky_energy;
color.b *= sky_energy;

float sun_angle = Math::rad2deg(Math::acos(CLAMP(sun.dot(normal), -1.0, 1.0)));
// acos does clamping.
float sun_angle = Math::rad2deg(Math::acos(sun.dot(normal)));

if (sun_angle < sun_angle_min) {
color = color.blend(sun_linear);
Expand Down

0 comments on commit bf56a3a

Please sign in to comment.