Added a Math singleton exposing math functions directly to scripts. The idea is to make the disrepancies between scripts and engine side code smaller.

This commit is contained in:
Relintai 2023-04-22 12:47:56 +02:00
parent 4ab9936fc8
commit e80dfcee2e
4 changed files with 415 additions and 0 deletions

View File

@ -1615,6 +1615,101 @@ _OS::_OS() {
singleton = this;
}
///////////////////// MATH
_Math *_Math::singleton = nullptr;
_Math *_Math::get_singleton() {
return singleton;
}
_Math::_Math() {
singleton = this;
}
void _Math::_bind_methods() {
ClassDB::bind_method(D_METHOD("sin", "x"), &_Math::sin);
ClassDB::bind_method(D_METHOD("cos", "x"), &_Math::cos);
ClassDB::bind_method(D_METHOD("tan", "x"), &_Math::tan);
ClassDB::bind_method(D_METHOD("sinh", "x"), &_Math::sinh);
ClassDB::bind_method(D_METHOD("sinc", "x"), &_Math::sinc);
ClassDB::bind_method(D_METHOD("sincn", "x"), &_Math::sincn);
ClassDB::bind_method(D_METHOD("cosh", "x"), &_Math::cosh);
ClassDB::bind_method(D_METHOD("tanh", "x"), &_Math::tanh);
ClassDB::bind_method(D_METHOD("asin", "x"), &_Math::asin);
ClassDB::bind_method(D_METHOD("acos", "x"), &_Math::acos);
ClassDB::bind_method(D_METHOD("atan", "x"), &_Math::atan);
ClassDB::bind_method(D_METHOD("atan2", "y", "x"), &_Math::atan2);
ClassDB::bind_method(D_METHOD("sqrt", "x"), &_Math::sqrt);
ClassDB::bind_method(D_METHOD("fmod", "x", "y"), &_Math::fmod);
ClassDB::bind_method(D_METHOD("floor", "x"), &_Math::floor);
ClassDB::bind_method(D_METHOD("floorf_int", "x"), &_Math::floorf_int);
ClassDB::bind_method(D_METHOD("ceil", "x"), &_Math::ceil);
ClassDB::bind_method(D_METHOD("pow", "x", "y"), &_Math::pow);
ClassDB::bind_method(D_METHOD("log", "x"), &_Math::log);
ClassDB::bind_method(D_METHOD("log1p", "x"), &_Math::log1p);
ClassDB::bind_method(D_METHOD("log10", "x"), &_Math::log10);
ClassDB::bind_method(D_METHOD("log2", "x"), &_Math::log2);
ClassDB::bind_method(D_METHOD("exp", "x"), &_Math::exp);
ClassDB::bind_method(D_METHOD("is_nan", "val"), &_Math::is_nan);
ClassDB::bind_method(D_METHOD("is_inf", "val"), &_Math::is_inf);
ClassDB::bind_method(D_METHOD("abs", "g"), &_Math::abs);
ClassDB::bind_method(D_METHOD("absi", "g"), &_Math::absi);
ClassDB::bind_method(D_METHOD("fposmod", "x", "y"), &_Math::fposmod);
ClassDB::bind_method(D_METHOD("fposmodp", "x", "y"), &_Math::fposmodp);
ClassDB::bind_method(D_METHOD("posmod", "x", "y"), &_Math::posmod);
ClassDB::bind_method(D_METHOD("deg2rad", "y"), &_Math::deg2rad);
ClassDB::bind_method(D_METHOD("rad2deg", "y"), &_Math::rad2deg);
ClassDB::bind_method(D_METHOD("lerp", "from", "to", "weight"), &_Math::lerp);
ClassDB::bind_method(D_METHOD("lerp_angle", "from", "to", "weight"), &_Math::lerp_angle);
ClassDB::bind_method(D_METHOD("inverse_lerp", "from", "to", "value"), &_Math::inverse_lerp);
ClassDB::bind_method(D_METHOD("range_lerp", "value", "istart", "istop", "ostart", "ostop"), &_Math::range_lerp);
ClassDB::bind_method(D_METHOD("cubic_interpolate", "from", "to", "pre", "post", "weight"), &_Math::cubic_interpolate);
ClassDB::bind_method(D_METHOD("bezier_interpolate", "start", "control_1", "control_2", "end", "t"), &_Math::bezier_interpolate);
ClassDB::bind_method(D_METHOD("smoothstep", "from", "to", "s"), &_Math::smoothstep);
ClassDB::bind_method(D_METHOD("move_toward", "from", "to", "delta"), &_Math::move_toward);
ClassDB::bind_method(D_METHOD("linear2db", "linear"), &_Math::linear2db);
ClassDB::bind_method(D_METHOD("db2linear", "db"), &_Math::db2linear);
ClassDB::bind_method(D_METHOD("round", "val"), &_Math::round);
ClassDB::bind_method(D_METHOD("wrapi", "value", "min", "max"), &_Math::wrapi);
ClassDB::bind_method(D_METHOD("wrapf", "value", "min", "max"), &_Math::wrapf);
ClassDB::bind_method(D_METHOD("fract", "value"), &_Math::fract);
ClassDB::bind_method(D_METHOD("pingpong", "value", "length"), &_Math::pingpong);
ClassDB::bind_method(D_METHOD("ease", "x", "c"), &_Math::ease);
ClassDB::bind_method(D_METHOD("step_decimals", "step"), &_Math::step_decimals);
ClassDB::bind_method(D_METHOD("range_step_decimals", "step"), &_Math::range_step_decimals);
ClassDB::bind_method(D_METHOD("stepify", "value", "step"), &_Math::stepify);
ClassDB::bind_method(D_METHOD("dectime", "value", "amount", "step"), &_Math::dectime);
ClassDB::bind_method(D_METHOD("larger_prime", "val"), &_Math::larger_prime);
ClassDB::bind_method(D_METHOD("seed", "x"), &_Math::seed);
ClassDB::bind_method(D_METHOD("randomize"), &_Math::randomize);
ClassDB::bind_method(D_METHOD("rand"), &_Math::rand);
ClassDB::bind_method(D_METHOD("randd"), &_Math::randd);
ClassDB::bind_method(D_METHOD("randf"), &_Math::randf);
ClassDB::bind_method(D_METHOD("randfn", "mean", "deviation"), &_Math::randfn);
ClassDB::bind_method(D_METHOD("random", "from", "to"), &_Math::random);
ClassDB::bind_method(D_METHOD("randomi", "from", "to"), &_Math::randomi);
ClassDB::bind_method(D_METHOD("is_equal_approx_ratio", "a", "b", "epsilon", "min_epsilon"), &_Math::is_equal_approx_ratio, CMP_EPSILON, CMP_EPSILON);
ClassDB::bind_method(D_METHOD("is_equal_approx", "a", "b"), &_Math::is_equal_approx);
ClassDB::bind_method(D_METHOD("is_equal_approxt", "a", "b", "tolerance"), &_Math::is_equal_approxt);
ClassDB::bind_method(D_METHOD("is_zero_approx", "s"), &_Math::is_zero_approx);
ClassDB::bind_method(D_METHOD("absd", "g"), &_Math::absd);
ClassDB::bind_method(D_METHOD("fast_ftoi", "a"), &_Math::fast_ftoi);
ClassDB::bind_method(D_METHOD("halfbits_to_floatbits", "h"), &_Math::halfbits_to_floatbits);
ClassDB::bind_method(D_METHOD("half_to_float", "h"), &_Math::half_to_float);
ClassDB::bind_method(D_METHOD("make_half_float", "f"), &_Math::make_half_float);
ClassDB::bind_method(D_METHOD("snap_scalar", "offset", "step", "target"), &_Math::snap_scalar);
ClassDB::bind_method(D_METHOD("snap_scalar_separation", "offset", "step", "target", "separation"), &_Math::snap_scalar_separation);
}
///////////////////// GEOMETRY
_Geometry *_Geometry::singleton = nullptr;

View File

@ -34,6 +34,7 @@
#include "core/io/image.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
#include "core/math/math_funcs.h"
#include "core/os/dir_access.h"
#include "core/os/file_access.h"
#include "core/os/os.h"
@ -433,6 +434,302 @@ VARIANT_ENUM_CAST(_OS::SystemDir);
VARIANT_ENUM_CAST(_OS::ScreenOrientation);
VARIANT_ENUM_CAST(_OS::HandleType);
class _Math : public Object {
GDCLASS(_Math, Object);
public:
_ALWAYS_INLINE_ real_t sin(real_t p_x) {
return Math::sin(p_x);
}
_ALWAYS_INLINE_ real_t cos(real_t p_x) {
return Math::cos(p_x);
}
_ALWAYS_INLINE_ real_t tan(real_t p_x) {
return Math::tan(p_x);
}
_ALWAYS_INLINE_ real_t sinh(real_t p_x) {
return Math::sinh(p_x);
}
_ALWAYS_INLINE_ real_t sinc(real_t p_x) {
return Math::sinc(p_x);
}
_ALWAYS_INLINE_ real_t sincn(real_t p_x) {
return Math::sincn(p_x);
}
_ALWAYS_INLINE_ real_t cosh(real_t p_x) {
return Math::cosh(p_x);
}
_ALWAYS_INLINE_ real_t tanh(real_t p_x) {
return Math::tanh(p_x);
}
_ALWAYS_INLINE_ real_t asin(real_t p_x) {
return Math::asin(p_x);
}
_ALWAYS_INLINE_ real_t acos(real_t p_x) {
return Math::acos(p_x);
}
_ALWAYS_INLINE_ real_t atan(real_t p_x) {
return Math::atan(p_x);
}
_ALWAYS_INLINE_ real_t atan2(real_t p_y, real_t p_x) {
return Math::atan2(p_y, p_x);
}
_ALWAYS_INLINE_ real_t sqrt(real_t p_x) {
return Math::sqrt(p_x);
}
_ALWAYS_INLINE_ real_t fmod(real_t p_x, real_t p_y) {
return Math::fmod(p_x, p_y);
}
_ALWAYS_INLINE_ real_t floor(real_t p_x) {
return Math::floor(p_x);
}
_ALWAYS_INLINE_ int floorf_int(const float p_x) {
return Math::floorf_int(p_x);
}
_ALWAYS_INLINE_ real_t ceil(real_t p_x) {
return Math::ceil(p_x);
}
_ALWAYS_INLINE_ real_t pow(real_t p_x, real_t p_y) {
return Math::pow(p_x, p_y);
}
_ALWAYS_INLINE_ real_t log(real_t p_x) {
return Math::log(p_x);
}
_ALWAYS_INLINE_ real_t log1p(real_t p_x) {
return Math::log1p(p_x);
}
_ALWAYS_INLINE_ real_t log10(real_t p_x) {
return Math::log10(p_x);
}
_ALWAYS_INLINE_ real_t log2(real_t p_x) {
return Math::log2(p_x);
}
_ALWAYS_INLINE_ real_t exp(real_t p_x) {
return Math::exp(p_x);
}
_ALWAYS_INLINE_ bool is_nan(real_t p_val) {
return Math::is_nan(p_val);
}
_ALWAYS_INLINE_ bool is_inf(real_t p_val) {
return Math::is_inf(p_val);
}
_ALWAYS_INLINE_ real_t abs(real_t g) {
return Math::abs(g);
}
_ALWAYS_INLINE_ int absi(int g) {
return Math::abs(g);
}
_ALWAYS_INLINE_ real_t fposmod(real_t p_x, real_t p_y) {
return Math::fposmod(p_x, p_y);
}
_ALWAYS_INLINE_ real_t fposmodp(real_t p_x, real_t p_y) {
return Math::fposmodp(p_x, p_y);
}
_ALWAYS_INLINE_ int64_t posmod(int64_t p_x, int64_t p_y) {
return Math::posmod(p_x, p_y);
}
_ALWAYS_INLINE_ real_t deg2rad(real_t p_y) {
return Math::deg2rad(p_y);
}
_ALWAYS_INLINE_ real_t rad2deg(real_t p_y) {
return Math::rad2deg(p_y);
}
_ALWAYS_INLINE_ real_t lerp(real_t p_from, real_t p_to, real_t p_weight) {
return Math::lerp(p_from, p_to, p_weight);
}
_ALWAYS_INLINE_ real_t lerp_angle(real_t p_from, real_t p_to, real_t p_weight) {
return Math::lerp_angle(p_from, p_to, p_weight);
}
_ALWAYS_INLINE_ real_t inverse_lerp(real_t p_from, real_t p_to, real_t p_value) {
return Math::inverse_lerp(p_from, p_to, p_value);
}
_ALWAYS_INLINE_ real_t range_lerp(real_t p_value, real_t p_istart, real_t p_istop, real_t p_ostart, real_t p_ostop) {
return Math::range_lerp(p_value, p_istart, p_istop, p_ostart, p_ostop);
}
_ALWAYS_INLINE_ real_t cubic_interpolate(real_t p_from, real_t p_to, real_t p_pre, real_t p_post, real_t p_weight) {
return Math::cubic_interpolate(p_from, p_to, p_pre, p_post, p_weight);
}
_ALWAYS_INLINE_ real_t bezier_interpolate(real_t p_start, real_t p_control_1, real_t p_control_2, real_t p_end, real_t p_t) {
return Math::bezier_interpolate(p_start, p_control_1, p_control_2, p_end, p_t);
}
_ALWAYS_INLINE_ real_t smoothstep(real_t p_from, real_t p_to, real_t p_s) {
return Math::smoothstep(p_from, p_to, p_s);
}
_ALWAYS_INLINE_ real_t move_toward(real_t p_from, real_t p_to, real_t p_delta) {
return Math::move_toward(p_from, p_to, p_delta);
}
_ALWAYS_INLINE_ real_t linear2db(real_t p_linear) {
return Math::linear2db(p_linear);
}
_ALWAYS_INLINE_ real_t db2linear(real_t p_db) {
return Math::db2linear(p_db);
}
_ALWAYS_INLINE_ real_t round(real_t p_val) {
return Math::round(p_val);
}
_ALWAYS_INLINE_ int64_t wrapi(int64_t value, int64_t min, int64_t max) {
return Math::wrapi(value, min, max);
}
_ALWAYS_INLINE_ real_t wrapf(real_t value, real_t min, real_t max) {
return Math::wrapf(value, min, max);
}
_ALWAYS_INLINE_ real_t fract(real_t value) {
return Math::fract(value);
}
_ALWAYS_INLINE_ real_t pingpong(real_t value, real_t length) {
return Math::pingpong(value, length);
}
_ALWAYS_INLINE_ double ease(double p_x, double p_c) {
return Math::ease(p_x, p_c);
}
_ALWAYS_INLINE_ int step_decimals(double p_step) {
return Math::step_decimals(p_step);
}
_ALWAYS_INLINE_ int range_step_decimals(double p_step) {
return Math::range_step_decimals(p_step);
}
_ALWAYS_INLINE_ double stepify(double p_value, double p_step) {
return Math::stepify(p_value, p_step);
}
_ALWAYS_INLINE_ double dectime(double p_value, double p_amount, double p_step) {
return Math::dectime(p_value, p_amount, p_step);
}
_ALWAYS_INLINE_ uint32_t larger_prime(uint32_t p_val) {
return Math::larger_prime(p_val);
}
_ALWAYS_INLINE_ void seed(uint64_t x) {
return Math::seed(x);
}
_ALWAYS_INLINE_ void randomize() {
return Math::randomize();
}
_ALWAYS_INLINE_ uint32_t rand() {
return Math::rand();
}
_ALWAYS_INLINE_ double randd() {
return Math::randd();
}
_ALWAYS_INLINE_ float randf() {
return Math::randf();
}
_ALWAYS_INLINE_ double randfn(double mean, double deviation) {
return Math::randfn(mean, deviation);
}
_ALWAYS_INLINE_ real_t random(real_t from, real_t to) {
return Math::random(from, to);
}
_ALWAYS_INLINE_ int randomi(int from, int to) {
return Math::random(from, to);
}
_ALWAYS_INLINE_ bool is_equal_approx_ratio(real_t a, real_t b, real_t epsilon = CMP_EPSILON, real_t min_epsilon = CMP_EPSILON) {
return Math::is_equal_approx_ratio(a, b, epsilon, min_epsilon);
}
_ALWAYS_INLINE_ bool is_equal_approx(real_t a, real_t b) {
return Math::is_equal_approx(a, b);
}
_ALWAYS_INLINE_ bool is_equal_approxt(real_t a, real_t b, real_t tolerance) {
return Math::is_equal_approx(a, b, tolerance);
}
_ALWAYS_INLINE_ bool is_zero_approx(real_t s) {
return Math::is_zero_approx(s);
}
_ALWAYS_INLINE_ real_t absd(real_t g) {
return Math::absd(g);
}
_ALWAYS_INLINE_ int fast_ftoi(float a) {
return Math::fast_ftoi(a);
}
_ALWAYS_INLINE_ uint32_t halfbits_to_floatbits(uint16_t h) {
return Math::halfbits_to_floatbits(h);
}
_ALWAYS_INLINE_ float half_to_float(const uint16_t h) {
return Math::half_to_float(h);
}
_ALWAYS_INLINE_ uint16_t make_half_float(float f) {
return Math::make_half_float(f);
}
_ALWAYS_INLINE_ float snap_scalar(float p_offset, float p_step, float p_target) {
return Math::snap_scalar(p_offset, p_step, p_target);
}
_ALWAYS_INLINE_ float snap_scalar_separation(float p_offset, float p_step, float p_target, float p_separation) {
return Math::snap_scalar_separation(p_offset, p_step, p_target, p_separation);
}
static _Math *get_singleton();
_Math();
protected:
static void _bind_methods();
static _Math *singleton;
};
class _Geometry : public Object {
GDCLASS(_Geometry, Object);

View File

@ -204,6 +204,12 @@ public:
static _ALWAYS_INLINE_ int64_t abs(int64_t g) {
return g > 0 ? g : -g;
}
static _ALWAYS_INLINE_ int absi(int g) {
return g > 0 ? g : -g;
}
static _ALWAYS_INLINE_ int64_t absi(int64_t g) {
return g > 0 ? g : -g;
}
static _ALWAYS_INLINE_ double fposmod(double p_x, double p_y) {
double value = Math::fmod(p_x, p_y);
@ -431,6 +437,9 @@ public:
static float random(float from, float to);
static real_t randomr(real_t from, real_t to);
static int random(int from, int to);
static _ALWAYS_INLINE_ int randomi(int from, int to) {
return random(from, to);
}
static _ALWAYS_INLINE_ bool is_equal_approx_ratio(real_t a, real_t b, real_t epsilon = CMP_EPSILON, real_t min_epsilon = CMP_EPSILON) {
// this is an approximate way to check that numbers are close, as a ratio of their average size
@ -466,6 +475,15 @@ public:
return abs(a - b) < tolerance;
}
static _ALWAYS_INLINE_ bool is_equal_approxt(float a, float b, float tolerance) {
// Check for exact equality first, required to handle "infinity" values.
if (a == b) {
return true;
}
// Then check for approximate equality.
return abs(a - b) < tolerance;
}
static _ALWAYS_INLINE_ bool is_zero_approx(float s) {
return abs(s) < (float)CMP_EPSILON;
}

View File

@ -100,6 +100,7 @@ static ThreadPool *thread_pool = NULL;
static IP *ip = nullptr;
static _Math *_math = nullptr;
static _Geometry *_geometry = nullptr;
extern Mutex _global_mutex;
@ -227,6 +228,7 @@ void register_core_types() {
ip = IP::create();
_math = memnew(_Math);
_geometry = memnew(_Geometry);
_resource_loader = memnew(_ResourceLoader);
@ -257,6 +259,7 @@ void register_core_settings() {
void register_core_singletons() {
ClassDB::register_class<ProjectSettings>();
ClassDB::register_virtual_class<IP>();
ClassDB::register_class<_Math>();
ClassDB::register_class<_Geometry>();
ClassDB::register_class<_ResourceLoader>();
ClassDB::register_class<_ResourceSaver>();
@ -277,6 +280,7 @@ void register_core_singletons() {
Engine::get_singleton()->add_singleton(Engine::Singleton("ProjectSettings", ProjectSettings::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("IP", IP::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("Math", _Math::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("Geometry", _Geometry::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("ResourceLoader", _ResourceLoader::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("ResourceSaver", _ResourceSaver::get_singleton()));
@ -303,6 +307,7 @@ void unregister_core_types() {
memdelete(_json);
memdelete(_plogger);
memdelete(_math);
memdelete(_geometry);
memdelete(thread_pool);