Core: Use Math namespace for constants

This commit is contained in:
Thaddeus Crews 2025-04-10 11:21:05 -05:00
parent 06c71fbf40
commit 94282d88f9
No known key found for this signature in database
GPG key ID: 8C6E5FEB5FC03CCC
181 changed files with 812 additions and 818 deletions

View file

@ -48,7 +48,7 @@ static real_t heuristic_manhattan(const Vector2i &p_from, const Vector2i &p_to)
static real_t heuristic_octile(const Vector2i &p_from, const Vector2i &p_to) {
real_t dx = (real_t)Math::abs(p_to.x - p_from.x);
real_t dy = (real_t)Math::abs(p_to.y - p_from.y);
real_t F = Math_SQRT2 - 1;
real_t F = Math::SQRT2 - 1;
return (dx < dy) ? F * dx + dy : F * dy + dx;
}

View file

@ -186,7 +186,7 @@ Basis Basis::diagonalize() {
// Compute the rotation angle
real_t angle;
if (Math::is_equal_approx(rows[j][j], rows[i][i])) {
angle = Math_PI / 4;
angle = Math::PI / 4;
} else {
angle = 0.5f * Math::atan(2 * rows[i][j] / (rows[j][j] - rows[i][i]));
}
@ -486,12 +486,12 @@ Vector3 Basis::get_euler(EulerOrder p_order) const {
}
} else {
euler.x = Math::atan2(rows[2][1], rows[1][1]);
euler.y = -Math_PI / 2.0f;
euler.y = -Math::PI / 2.0f;
euler.z = 0.0f;
}
} else {
euler.x = Math::atan2(rows[2][1], rows[1][1]);
euler.y = Math_PI / 2.0f;
euler.y = Math::PI / 2.0f;
euler.z = 0.0f;
}
return euler;
@ -515,13 +515,13 @@ Vector3 Basis::get_euler(EulerOrder p_order) const {
// It's -1
euler.x = -Math::atan2(rows[1][2], rows[2][2]);
euler.y = 0.0f;
euler.z = Math_PI / 2.0f;
euler.z = Math::PI / 2.0f;
}
} else {
// It's 1
euler.x = -Math::atan2(rows[1][2], rows[2][2]);
euler.y = 0.0f;
euler.z = -Math_PI / 2.0f;
euler.z = -Math::PI / 2.0f;
}
return euler;
}
@ -551,12 +551,12 @@ Vector3 Basis::get_euler(EulerOrder p_order) const {
euler.z = atan2(rows[1][0], rows[1][1]);
}
} else { // m12 == -1
euler.x = Math_PI * 0.5f;
euler.x = Math::PI * 0.5f;
euler.y = atan2(rows[0][1], rows[0][0]);
euler.z = 0;
}
} else { // m12 == 1
euler.x = -Math_PI * 0.5f;
euler.x = -Math::PI * 0.5f;
euler.y = -atan2(rows[0][1], rows[0][0]);
euler.z = 0;
}
@ -582,13 +582,13 @@ Vector3 Basis::get_euler(EulerOrder p_order) const {
// It's -1
euler.x = Math::atan2(rows[2][1], rows[2][2]);
euler.y = 0.0f;
euler.z = -Math_PI / 2.0f;
euler.z = -Math::PI / 2.0f;
}
} else {
// It's 1
euler.x = Math::atan2(rows[2][1], rows[2][2]);
euler.y = 0.0f;
euler.z = Math_PI / 2.0f;
euler.z = Math::PI / 2.0f;
}
return euler;
} break;
@ -608,13 +608,13 @@ Vector3 Basis::get_euler(EulerOrder p_order) const {
euler.z = Math::atan2(-rows[0][1], rows[1][1]);
} else {
// It's -1
euler.x = -Math_PI / 2.0f;
euler.x = -Math::PI / 2.0f;
euler.y = Math::atan2(rows[0][2], rows[0][0]);
euler.z = 0;
}
} else {
// It's 1
euler.x = Math_PI / 2.0f;
euler.x = Math::PI / 2.0f;
euler.y = Math::atan2(rows[0][2], rows[0][0]);
euler.z = 0;
}
@ -637,13 +637,13 @@ Vector3 Basis::get_euler(EulerOrder p_order) const {
} else {
// It's -1
euler.x = 0;
euler.y = Math_PI / 2.0f;
euler.y = Math::PI / 2.0f;
euler.z = -Math::atan2(rows[0][1], rows[1][1]);
}
} else {
// It's 1
euler.x = 0;
euler.y = -Math_PI / 2.0f;
euler.y = -Math::PI / 2.0f;
euler.z = -Math::atan2(rows[0][1], rows[1][1]);
}
return euler;
@ -778,8 +778,8 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
if ((xx > yy) && (xx > zz)) { // rows[0][0] is the largest diagonal term.
if (xx < CMP_EPSILON) {
x = 0;
y = Math_SQRT12;
z = Math_SQRT12;
y = Math::SQRT12;
z = Math::SQRT12;
} else {
x = Math::sqrt(xx);
y = xy / x;
@ -787,9 +787,9 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
}
} else if (yy > zz) { // rows[1][1] is the largest diagonal term.
if (yy < CMP_EPSILON) {
x = Math_SQRT12;
x = Math::SQRT12;
y = 0;
z = Math_SQRT12;
z = Math::SQRT12;
} else {
y = Math::sqrt(yy);
x = xy / y;
@ -797,8 +797,8 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
}
} else { // rows[2][2] is the largest diagonal term so base result on this.
if (zz < CMP_EPSILON) {
x = Math_SQRT12;
y = Math_SQRT12;
x = Math::SQRT12;
y = Math::SQRT12;
z = 0;
} else {
z = Math::sqrt(zz);
@ -807,7 +807,7 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
}
}
r_axis = Vector3(x, y, z);
r_angle = Math_PI;
r_angle = Math::PI;
return;
}
// As we have reached here there are no singularities so we can handle normally.

View file

@ -181,7 +181,7 @@ DynamicBVH::Volume DynamicBVH::_bounds(Node **leaves, int p_count) {
void DynamicBVH::_bottom_up(Node **leaves, int p_count) {
while (p_count > 1) {
real_t minsize = INFINITY;
real_t minsize = Math::INF;
int minidx[2] = { -1, -1 };
for (int i = 0; i < p_count; ++i) {
for (int j = i + 1; j < p_count; ++j) {

View file

@ -454,16 +454,16 @@ Error Expression::_get_token(Token &r_token) {
r_token.value = false;
} else if (id == "PI") {
r_token.type = TK_CONSTANT;
r_token.value = Math_PI;
r_token.value = Math::PI;
} else if (id == "TAU") {
r_token.type = TK_CONSTANT;
r_token.value = Math_TAU;
r_token.value = Math::TAU;
} else if (id == "INF") {
r_token.type = TK_CONSTANT;
r_token.value = INFINITY;
r_token.value = Math::INF;
} else if (id == "NAN") {
r_token.type = TK_CONSTANT;
r_token.value = NAN;
r_token.value = Math::NaN;
} else if (id == "not") {
r_token.type = TK_OP_NOT;
} else if (id == "or") {

View file

@ -744,7 +744,7 @@ Vector<Plane> Geometry3D::build_cylinder_planes(real_t p_radius, real_t p_height
Vector<Plane> planes;
const double sides_step = Math_TAU / p_sides;
const double sides_step = Math::TAU / p_sides;
for (int i = 0; i < p_sides; i++) {
Vector3 normal;
normal[(p_axis + 1) % 3] = Math::cos(i * sides_step);
@ -775,7 +775,7 @@ Vector<Plane> Geometry3D::build_sphere_planes(real_t p_radius, int p_lats, int p
axis_neg[(p_axis + 2) % 3] = 1.0;
axis_neg[p_axis] = -1.0;
const double lon_step = Math_TAU / p_lons;
const double lon_step = Math::TAU / p_lons;
for (int i = 0; i < p_lons; i++) {
Vector3 normal;
normal[(p_axis + 1) % 3] = Math::cos(i * lon_step);
@ -806,7 +806,7 @@ Vector<Plane> Geometry3D::build_capsule_planes(real_t p_radius, real_t p_height,
axis_neg[(p_axis + 2) % 3] = 1.0;
axis_neg[p_axis] = -1.0;
const double sides_step = Math_TAU / p_sides;
const double sides_step = Math::TAU / p_sides;
for (int i = 0; i < p_sides; i++) {
Vector3 normal;
normal[(p_axis + 1) % 3] = Math::cos(i * sides_step);
@ -862,7 +862,6 @@ Vector<Vector3> Geometry3D::compute_convex_mesh_points(const Plane *p_planes, in
}
#define square(m_s) ((m_s) * (m_s))
#define INF 1e20
/* dt of 1d function using squared distance */
static void edt(float *f, int stride, int n) {
@ -872,8 +871,8 @@ static void edt(float *f, int stride, int n) {
int k = 0;
v[0] = 0;
z[0] = -INF;
z[1] = +INF;
z[0] = -Math::INF;
z[1] = +Math::INF;
for (int q = 1; q <= n - 1; q++) {
float s = ((f[q * stride] + square(q)) - (f[v[k] * stride] + square(v[k]))) / (2 * q - 2 * v[k]);
while (s <= z[k]) {
@ -884,7 +883,7 @@ static void edt(float *f, int stride, int n) {
v[k] = q;
z[k] = s;
z[k + 1] = +INF;
z[k + 1] = +Math::INF;
}
k = 0;
@ -909,7 +908,7 @@ Vector<uint32_t> Geometry3D::generate_edf(const Vector<bool> &p_voxels, const Ve
float *work_memory = memnew_arr(float, float_count);
for (uint32_t i = 0; i < float_count; i++) {
work_memory[i] = INF;
work_memory[i] = Math::INF;
}
uint32_t y_mult = p_size.x;

View file

@ -30,19 +30,29 @@
#pragma once
#include "core/typedefs.h"
#include <limits>
namespace Math {
inline constexpr double SQRT2 = 1.4142135623730950488016887242;
inline constexpr double SQRT3 = 1.7320508075688772935274463415059;
inline constexpr double SQRT12 = 0.7071067811865475244008443621048490;
inline constexpr double SQRT13 = 0.57735026918962576450914878050196;
inline constexpr double LN2 = 0.6931471805599453094172321215;
inline constexpr double TAU = 6.2831853071795864769252867666;
inline constexpr double PI = 3.1415926535897932384626433833;
inline constexpr double E = 2.7182818284590452353602874714;
inline constexpr double INF = std::numeric_limits<double>::infinity();
inline constexpr double NaN = std::numeric_limits<double>::quiet_NaN();
} // namespace Math
#define CMP_EPSILON 0.00001
#define CMP_EPSILON2 (CMP_EPSILON * CMP_EPSILON)
#define CMP_NORMALIZE_TOLERANCE 0.000001
#define CMP_POINT_IN_PLANE_EPSILON 0.00001
#define Math_SQRT12 0.7071067811865475244008443621048490
#define Math_SQRT2 1.4142135623730950488016887242
#define Math_LN2 0.6931471805599453094172321215
#define Math_TAU 6.2831853071795864769252867666
#define Math_PI 3.1415926535897932384626433833
#define Math_E 2.7182818284590452353602874714
#ifdef DEBUG_ENABLED
#define MATH_CHECKS
#endif

View file

@ -75,10 +75,10 @@ _ALWAYS_INLINE_ float sinc(float p_x) {
}
_ALWAYS_INLINE_ double sincn(double p_x) {
return sinc(Math_PI * p_x);
return sinc(PI * p_x);
}
_ALWAYS_INLINE_ float sincn(float p_x) {
return sinc((float)Math_PI * p_x);
return sinc((float)PI * p_x);
}
_ALWAYS_INLINE_ double cosh(double p_x) {
@ -97,18 +97,18 @@ _ALWAYS_INLINE_ float tanh(float p_x) {
// Always does clamping so always safe to use.
_ALWAYS_INLINE_ double asin(double p_x) {
return p_x < -1 ? (-Math_PI / 2) : (p_x > 1 ? (Math_PI / 2) : ::asin(p_x));
return p_x < -1 ? (-PI / 2) : (p_x > 1 ? (PI / 2) : ::asin(p_x));
}
_ALWAYS_INLINE_ float asin(float p_x) {
return p_x < -1 ? (-Math_PI / 2) : (p_x > 1 ? (Math_PI / 2) : ::asinf(p_x));
return p_x < -1 ? (-(float)PI / 2) : (p_x > 1 ? ((float)PI / 2) : ::asinf(p_x));
}
// Always does clamping so always safe to use.
_ALWAYS_INLINE_ double acos(double p_x) {
return p_x < -1 ? Math_PI : (p_x > 1 ? 0 : ::acos(p_x));
return p_x < -1 ? PI : (p_x > 1 ? 0 : ::acos(p_x));
}
_ALWAYS_INLINE_ float acos(float p_x) {
return p_x < -1 ? Math_PI : (p_x > 1 ? 0 : ::acosf(p_x));
return p_x < -1 ? (float)PI : (p_x > 1 ? 0 : ::acosf(p_x));
}
_ALWAYS_INLINE_ double atan(double p_x) {
@ -142,10 +142,10 @@ _ALWAYS_INLINE_ float acosh(float p_x) {
// Always does clamping so always safe to use.
_ALWAYS_INLINE_ double atanh(double p_x) {
return p_x <= -1 ? -INFINITY : (p_x >= 1 ? INFINITY : ::atanh(p_x));
return p_x <= -1 ? -INF : (p_x >= 1 ? INF : ::atanh(p_x));
}
_ALWAYS_INLINE_ float atanh(float p_x) {
return p_x <= -1 ? -INFINITY : (p_x >= 1 ? INFINITY : ::atanhf(p_x));
return p_x <= -1 ? (float)-INF : (p_x >= 1 ? (float)INF : ::atanhf(p_x));
}
_ALWAYS_INLINE_ double sqrt(double p_x) {
@ -383,17 +383,17 @@ _ALWAYS_INLINE_ int64_t posmod(int64_t p_x, int64_t p_y) {
}
_ALWAYS_INLINE_ double deg_to_rad(double p_y) {
return p_y * (Math_PI / 180.0);
return p_y * (PI / 180.0);
}
_ALWAYS_INLINE_ float deg_to_rad(float p_y) {
return p_y * (float)(Math_PI / 180.0);
return p_y * ((float)PI / 180.0f);
}
_ALWAYS_INLINE_ double rad_to_deg(double p_y) {
return p_y * (180.0 / Math_PI);
return p_y * (180.0 / PI);
}
_ALWAYS_INLINE_ float rad_to_deg(float p_y) {
return p_y * (float)(180.0 / Math_PI);
return p_y * (180.0f / (float)PI);
}
_ALWAYS_INLINE_ double lerp(double p_from, double p_to, double p_weight) {
@ -419,31 +419,31 @@ _ALWAYS_INLINE_ float cubic_interpolate(float p_from, float p_to, float p_pre, f
}
_ALWAYS_INLINE_ double cubic_interpolate_angle(double p_from, double p_to, double p_pre, double p_post, double p_weight) {
double from_rot = fmod(p_from, Math_TAU);
double from_rot = fmod(p_from, TAU);
double pre_diff = fmod(p_pre - from_rot, Math_TAU);
double pre_rot = from_rot + fmod(2.0 * pre_diff, Math_TAU) - pre_diff;
double pre_diff = fmod(p_pre - from_rot, TAU);
double pre_rot = from_rot + fmod(2.0 * pre_diff, TAU) - pre_diff;
double to_diff = fmod(p_to - from_rot, Math_TAU);
double to_rot = from_rot + fmod(2.0 * to_diff, Math_TAU) - to_diff;
double to_diff = fmod(p_to - from_rot, TAU);
double to_rot = from_rot + fmod(2.0 * to_diff, TAU) - to_diff;
double post_diff = fmod(p_post - to_rot, Math_TAU);
double post_rot = to_rot + fmod(2.0 * post_diff, Math_TAU) - post_diff;
double post_diff = fmod(p_post - to_rot, TAU);
double post_rot = to_rot + fmod(2.0 * post_diff, TAU) - post_diff;
return cubic_interpolate(from_rot, to_rot, pre_rot, post_rot, p_weight);
}
_ALWAYS_INLINE_ float cubic_interpolate_angle(float p_from, float p_to, float p_pre, float p_post, float p_weight) {
float from_rot = fmod(p_from, (float)Math_TAU);
float from_rot = fmod(p_from, (float)TAU);
float pre_diff = fmod(p_pre - from_rot, (float)Math_TAU);
float pre_rot = from_rot + fmod(2.0f * pre_diff, (float)Math_TAU) - pre_diff;
float pre_diff = fmod(p_pre - from_rot, (float)TAU);
float pre_rot = from_rot + fmod(2.0f * pre_diff, (float)TAU) - pre_diff;
float to_diff = fmod(p_to - from_rot, (float)Math_TAU);
float to_rot = from_rot + fmod(2.0f * to_diff, (float)Math_TAU) - to_diff;
float to_diff = fmod(p_to - from_rot, (float)TAU);
float to_rot = from_rot + fmod(2.0f * to_diff, (float)TAU) - to_diff;
float post_diff = fmod(p_post - to_rot, (float)Math_TAU);
float post_rot = to_rot + fmod(2.0f * post_diff, (float)Math_TAU) - post_diff;
float post_diff = fmod(p_post - to_rot, (float)TAU);
float post_rot = to_rot + fmod(2.0f * post_diff, (float)TAU) - post_diff;
return cubic_interpolate(from_rot, to_rot, pre_rot, post_rot, p_weight);
}
@ -473,31 +473,31 @@ _ALWAYS_INLINE_ float cubic_interpolate_in_time(float p_from, float p_to, float
_ALWAYS_INLINE_ double cubic_interpolate_angle_in_time(double p_from, double p_to, double p_pre, double p_post, double p_weight,
double p_to_t, double p_pre_t, double p_post_t) {
double from_rot = fmod(p_from, Math_TAU);
double from_rot = fmod(p_from, TAU);
double pre_diff = fmod(p_pre - from_rot, Math_TAU);
double pre_rot = from_rot + fmod(2.0 * pre_diff, Math_TAU) - pre_diff;
double pre_diff = fmod(p_pre - from_rot, TAU);
double pre_rot = from_rot + fmod(2.0 * pre_diff, TAU) - pre_diff;
double to_diff = fmod(p_to - from_rot, Math_TAU);
double to_rot = from_rot + fmod(2.0 * to_diff, Math_TAU) - to_diff;
double to_diff = fmod(p_to - from_rot, TAU);
double to_rot = from_rot + fmod(2.0 * to_diff, TAU) - to_diff;
double post_diff = fmod(p_post - to_rot, Math_TAU);
double post_rot = to_rot + fmod(2.0 * post_diff, Math_TAU) - post_diff;
double post_diff = fmod(p_post - to_rot, TAU);
double post_rot = to_rot + fmod(2.0 * post_diff, TAU) - post_diff;
return cubic_interpolate_in_time(from_rot, to_rot, pre_rot, post_rot, p_weight, p_to_t, p_pre_t, p_post_t);
}
_ALWAYS_INLINE_ float cubic_interpolate_angle_in_time(float p_from, float p_to, float p_pre, float p_post, float p_weight,
float p_to_t, float p_pre_t, float p_post_t) {
float from_rot = fmod(p_from, (float)Math_TAU);
float from_rot = fmod(p_from, (float)TAU);
float pre_diff = fmod(p_pre - from_rot, (float)Math_TAU);
float pre_rot = from_rot + fmod(2.0f * pre_diff, (float)Math_TAU) - pre_diff;
float pre_diff = fmod(p_pre - from_rot, (float)TAU);
float pre_rot = from_rot + fmod(2.0f * pre_diff, (float)TAU) - pre_diff;
float to_diff = fmod(p_to - from_rot, (float)Math_TAU);
float to_rot = from_rot + fmod(2.0f * to_diff, (float)Math_TAU) - to_diff;
float to_diff = fmod(p_to - from_rot, (float)TAU);
float to_rot = from_rot + fmod(2.0f * to_diff, (float)TAU) - to_diff;
float post_diff = fmod(p_post - to_rot, (float)Math_TAU);
float post_rot = to_rot + fmod(2.0f * post_diff, (float)Math_TAU) - post_diff;
float post_diff = fmod(p_post - to_rot, (float)TAU);
float post_rot = to_rot + fmod(2.0f * post_diff, (float)TAU) - post_diff;
return cubic_interpolate_in_time(from_rot, to_rot, pre_rot, post_rot, p_weight, p_to_t, p_pre_t, p_post_t);
}
@ -543,12 +543,12 @@ _ALWAYS_INLINE_ float bezier_derivative(float p_start, float p_control_1, float
}
_ALWAYS_INLINE_ double angle_difference(double p_from, double p_to) {
double difference = fmod(p_to - p_from, Math_TAU);
return fmod(2.0 * difference, Math_TAU) - difference;
double difference = fmod(p_to - p_from, TAU);
return fmod(2.0 * difference, TAU) - difference;
}
_ALWAYS_INLINE_ float angle_difference(float p_from, float p_to) {
float difference = fmod(p_to - p_from, (float)Math_TAU);
return fmod(2.0f * difference, (float)Math_TAU) - difference;
float difference = fmod(p_to - p_from, (float)TAU);
return fmod(2.0f * difference, (float)TAU) - difference;
}
_ALWAYS_INLINE_ double lerp_angle(double p_from, double p_to, double p_weight) {
@ -662,13 +662,13 @@ _ALWAYS_INLINE_ double rotate_toward(double p_from, double p_to, double p_delta)
double difference = angle_difference(p_from, p_to);
double abs_difference = abs(difference);
// When `p_delta < 0` move no further than to PI radians away from `p_to` (as PI is the max possible angle distance).
return p_from + CLAMP(p_delta, abs_difference - Math_PI, abs_difference) * (difference >= 0.0 ? 1.0 : -1.0);
return p_from + CLAMP(p_delta, abs_difference - PI, abs_difference) * (difference >= 0.0 ? 1.0 : -1.0);
}
_ALWAYS_INLINE_ float rotate_toward(float p_from, float p_to, float p_delta) {
float difference = angle_difference(p_from, p_to);
float abs_difference = abs(difference);
// When `p_delta < 0` move no further than to PI radians away from `p_to` (as PI is the max possible angle distance).
return p_from + CLAMP(p_delta, abs_difference - (float)Math_PI, abs_difference) * (difference >= 0.0f ? 1.0f : -1.0f);
return p_from + CLAMP(p_delta, abs_difference - (float)PI, abs_difference) * (difference >= 0.0f ? 1.0f : -1.0f);
}
_ALWAYS_INLINE_ double linear_to_db(double p_linear) {

View file

@ -134,14 +134,14 @@ public:
if (temp < CMP_EPSILON) {
temp += CMP_EPSILON; // To prevent generating of INF value in log function, resulting to return NaN value from this function.
}
return p_mean + p_deviation * (cos(Math_TAU * randd()) * sqrt(-2.0 * log(temp))); // Box-Muller transform.
return p_mean + p_deviation * (cos(Math::TAU * randd()) * sqrt(-2.0 * log(temp))); // Box-Muller transform.
}
_FORCE_INLINE_ float randfn(float p_mean, float p_deviation) {
float temp = randf();
if (temp < CMP_EPSILON) {
temp += CMP_EPSILON; // To prevent generating of INF value in log function, resulting to return NaN value from this function.
}
return p_mean + p_deviation * (cos((float)Math_TAU * randf()) * sqrt(-2.0 * log(temp))); // Box-Muller transform.
return p_mean + p_deviation * (cos((float)Math::TAU * randf()) * sqrt(-2.0 * log(temp))); // Box-Muller transform.
}
double random(double p_from, double p_to);

View file

@ -51,7 +51,7 @@ public:
_FORCE_INLINE_ Ray(const Vector3 &p_org,
const Vector3 &p_dir,
float p_tnear = 0.0f,
float p_tfar = INFINITY) :
float p_tfar = Math::INF) :
org(p_org),
tnear(p_tnear),
dir(p_dir),

View file

@ -71,12 +71,12 @@ void Transform2D::rotate(real_t p_angle) {
real_t Transform2D::get_skew() const {
real_t det = determinant();
return Math::acos(columns[0].normalized().dot(SIGN(det) * columns[1].normalized())) - (real_t)Math_PI * 0.5f;
return Math::acos(columns[0].normalized().dot(SIGN(det) * columns[1].normalized())) - (real_t)Math::PI * 0.5f;
}
void Transform2D::set_skew(real_t p_angle) {
real_t det = determinant();
columns[1] = SIGN(det) * columns[0].rotated(((real_t)Math_PI * 0.5f + p_angle)).normalized() * columns[1].length();
columns[1] = SIGN(det) * columns[0].rotated(((real_t)Math::PI * 0.5f + p_angle)).normalized() * columns[1].length();
}
real_t Transform2D::get_rotation() const {