diff options
Diffstat (limited to 'core/math')
-rw-r--r-- | core/math/SCsub | 2 | ||||
-rw-r--r-- | core/math/a_star.cpp | 22 | ||||
-rw-r--r-- | core/math/bsp_tree.cpp | 5 | ||||
-rw-r--r-- | core/math/expression.cpp | 39 | ||||
-rw-r--r-- | core/math/face3.cpp | 9 | ||||
-rw-r--r-- | core/math/geometry.h | 15 | ||||
-rw-r--r-- | core/math/math_defs.h | 4 | ||||
-rw-r--r-- | core/math/math_funcs.cpp | 25 | ||||
-rw-r--r-- | core/math/math_funcs.h | 15 | ||||
-rw-r--r-- | core/math/matrix3.cpp | 20 | ||||
-rw-r--r-- | core/math/quat.cpp | 18 | ||||
-rw-r--r-- | core/math/quat.h | 2 | ||||
-rw-r--r-- | core/math/random_number_generator.cpp | 45 | ||||
-rw-r--r-- | core/math/random_number_generator.h | 61 | ||||
-rw-r--r-- | core/math/random_pcg.cpp | 55 | ||||
-rw-r--r-- | core/math/random_pcg.h | 61 | ||||
-rw-r--r-- | core/math/vector2.cpp | 4 | ||||
-rw-r--r-- | core/math/vector2.h | 2 | ||||
-rw-r--r-- | core/math/vector3.h | 6 |
19 files changed, 314 insertions, 96 deletions
diff --git a/core/math/SCsub b/core/math/SCsub index 4efc902717..1c5f954470 100644 --- a/core/math/SCsub +++ b/core/math/SCsub @@ -3,5 +3,3 @@ Import('env') env.add_source_files(env.core_sources, "*.cpp") - -Export('env') diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp index e4f93289e9..451c45cade 100644 --- a/core/math/a_star.cpp +++ b/core/math/a_star.cpp @@ -250,14 +250,9 @@ bool AStar::_solve(Point *begin_point, Point *end_point) { n->distance = _compute_cost(begin_point->id, n->id) * n->weight_scale; n->last_pass = pass; open_list.add(&n->list); - - if (end_point == n) { - found_route = true; - break; - } } - while (!found_route) { + while (true) { if (open_list.first() == NULL) { // No path found @@ -277,13 +272,16 @@ bool AStar::_solve(Point *begin_point, Point *end_point) { cost += _estimate_cost(p->id, end_point->id); if (cost < least_cost) { - least_cost_point = E; least_cost = cost; } } Point *p = least_cost_point->self(); + if (p == end_point) { + found_route = true; + break; + } for (Set<Point *>::Element *E = p->neighbours.front(); E; E = E->next()) { @@ -295,7 +293,6 @@ bool AStar::_solve(Point *begin_point, Point *end_point) { // Already visited, is this cheaper? if (e->distance > distance) { - e->prev_point = p; e->distance = distance; } @@ -306,18 +303,9 @@ bool AStar::_solve(Point *begin_point, Point *end_point) { e->distance = distance; e->last_pass = pass; // Mark as used open_list.add(&e->list); - - if (e == end_point) { - // End reached; stop algorithm - found_route = true; - break; - } } } - if (found_route) - break; - open_list.remove(least_cost_point); } diff --git a/core/math/bsp_tree.cpp b/core/math/bsp_tree.cpp index 6e51c56357..6ffc963783 100644 --- a/core/math/bsp_tree.cpp +++ b/core/math/bsp_tree.cpp @@ -165,7 +165,6 @@ int BSP_Tree::get_points_inside(const Vector3 *p_points, int p_point_count) cons int pass_count = 0; const Node *nodesptr = &nodes[0]; const Plane *planesptr = &planes[0]; - int plane_count = planes.size(); int node_count = nodes.size(); if (node_count == 0) // no nodes! @@ -192,9 +191,9 @@ int BSP_Tree::get_points_inside(const Vector3 *p_points, int p_point_count) cons break; } - uint16_t plane = nodesptr[idx].plane; #ifdef DEBUG_ENABLED - + int plane_count = planes.size(); + uint16_t plane = nodesptr[idx].plane; ERR_FAIL_INDEX_V(plane, plane_count, false); #endif diff --git a/core/math/expression.cpp b/core/math/expression.cpp index c0d7f874d2..0cfb54234c 100644 --- a/core/math/expression.cpp +++ b/core/math/expression.cpp @@ -756,6 +756,10 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant //////// +static bool _is_number(CharType c) { + return (c >= '0' && c <= '9'); +} + Error Expression::_get_token(Token &r_token) { while (true) { @@ -813,17 +817,12 @@ Error Expression::_get_token(Token &r_token) { r_token.type = TK_COLON; return OK; }; - case '.': { - - r_token.type = TK_PERIOD; - return OK; - }; case '$': { r_token.type = TK_INPUT; int index = 0; do { - if (expression[str_ofs] < '0' || expression[str_ofs] > '9') { + if (!_is_number(expression[str_ofs])) { _set_error("Expected number after '$'"); r_token.type = TK_ERROR; return ERR_PARSE_ERROR; @@ -832,7 +831,7 @@ Error Expression::_get_token(Token &r_token) { index += expression[str_ofs] - '0'; str_ofs++; - } while (expression[str_ofs] >= '0' && expression[str_ofs] <= '9'); + } while (_is_number(expression[str_ofs])); r_token.value = index; return OK; @@ -979,14 +978,14 @@ Error Expression::_get_token(Token &r_token) { r_token.type = TK_ERROR; return ERR_PARSE_ERROR; } - if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) { + if (!(_is_number(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) { _set_error("Malformed hex constant in string"); r_token.type = TK_ERROR; return ERR_PARSE_ERROR; } CharType v; - if (c >= '0' && c <= '9') { + if (_is_number(c)) { v = c - '0'; } else if (c >= 'a' && c <= 'f') { v = c - 'a'; @@ -1032,7 +1031,8 @@ Error Expression::_get_token(Token &r_token) { break; } - if (cchar >= '0' && cchar <= '9') { + CharType next_char = (str_ofs >= expression.length()) ? 0 : expression[str_ofs]; + if (_is_number(cchar) || (cchar == '.' && _is_number(next_char))) { //a number String num; @@ -1053,7 +1053,7 @@ Error Expression::_get_token(Token &r_token) { switch (reading) { case READING_INT: { - if (c >= '0' && c <= '9') { + if (_is_number(c)) { //pass } else if (c == '.') { reading = READING_DEC; @@ -1067,7 +1067,7 @@ Error Expression::_get_token(Token &r_token) { } break; case READING_DEC: { - if (c >= '0' && c <= '9') { + if (_is_number(c)) { } else if (c == 'e') { reading = READING_EXP; @@ -1079,7 +1079,7 @@ Error Expression::_get_token(Token &r_token) { } break; case READING_EXP: { - if (c >= '0' && c <= '9') { + if (_is_number(c)) { exp_beg = true; } else if ((c == '-' || c == '+') && !exp_sign && !exp_beg) { @@ -1114,7 +1114,7 @@ Error Expression::_get_token(Token &r_token) { String id; bool first = true; - while ((cchar >= 'A' && cchar <= 'Z') || (cchar >= 'a' && cchar <= 'z') || cchar == '_' || (!first && cchar >= '0' && cchar <= '9')) { + while ((cchar >= 'A' && cchar <= 'Z') || (cchar >= 'a' && cchar <= 'z') || cchar == '_' || (!first && _is_number(cchar))) { id += String::chr(cchar); cchar = GET_CHAR(); @@ -1176,6 +1176,12 @@ Error Expression::_get_token(Token &r_token) { } return OK; + + } else if (cchar == '.') { + // Handled down there as we support '.[0-9]' as numbers above + r_token.type = TK_PERIOD; + return OK; + } else { _set_error("Unexpected character."); r_token.type = TK_ERROR; @@ -1183,6 +1189,7 @@ Error Expression::_get_token(Token &r_token) { } } } +#undef GET_CHAR } r_token.type = TK_ERROR; @@ -2113,6 +2120,10 @@ Error Expression::parse(const String &p_expression, const Vector<String> &p_inpu } Variant Expression::execute(Array p_inputs, Object *p_base, bool p_show_error) { + if (error_set) { + ERR_EXPLAIN("There was previously a parse error: " + error_str); + ERR_FAIL_V(Variant()); + } execution_error = false; Variant output; diff --git a/core/math/face3.cpp b/core/math/face3.cpp index aa46fde7f7..8366137131 100644 --- a/core/math/face3.cpp +++ b/core/math/face3.cpp @@ -202,11 +202,12 @@ bool Face3::intersects_aabb(const AABB &p_aabb) const { { \ real_t aabb_min = p_aabb.position.m_ax; \ real_t aabb_max = p_aabb.position.m_ax + p_aabb.size.m_ax; \ - real_t tri_min, tri_max; \ - for (int i = 0; i < 3; i++) { \ - if (i == 0 || vertex[i].m_ax > tri_max) \ + real_t tri_min = vertex[0].m_ax; \ + real_t tri_max = vertex[0].m_ax; \ + for (int i = 1; i < 3; i++) { \ + if (vertex[i].m_ax > tri_max) \ tri_max = vertex[i].m_ax; \ - if (i == 0 || vertex[i].m_ax < tri_min) \ + if (vertex[i].m_ax < tri_min) \ tri_min = vertex[i].m_ax; \ } \ \ diff --git a/core/math/geometry.h b/core/math/geometry.h index a813a90774..df63f0dabe 100644 --- a/core/math/geometry.h +++ b/core/math/geometry.h @@ -800,6 +800,21 @@ public: return Vector<Vector<Vector2> >(); } + static bool is_polygon_clockwise(const Vector<Vector2> &p_polygon) { + int c = p_polygon.size(); + if (c < 3) + return false; + const Vector2 *p = p_polygon.ptr(); + real_t sum = 0; + for (int i = 0; i < c; i++) { + const Vector2 &v1 = p[i]; + const Vector2 &v2 = p[(i + 1) % c]; + sum += (v2.x - v1.x) * (v2.y + v1.y); + } + + return sum > 0.0f; + } + static PoolVector<PoolVector<Face3> > separate_objects(PoolVector<Face3> p_array); static PoolVector<Face3> wrap_geometry(PoolVector<Face3> p_array, real_t *p_error = NULL); ///< create a "wrap" that encloses the given geometry diff --git a/core/math/math_defs.h b/core/math/math_defs.h index a5feee6eb5..db9055cee2 100644 --- a/core/math/math_defs.h +++ b/core/math/math_defs.h @@ -93,9 +93,9 @@ enum Corner { }; /** - * The "Real" type is an abstract type used for real numbers, such as 1.5, + * The "Real" type is an abstract type used for real numbers, such as 1.5, * in contrast to integer numbers. Precision can be controlled with the - * presence or absence of the REAL_T_IS_DOUBLE define. + * presence or absence of the REAL_T_IS_DOUBLE define. */ #ifdef REAL_T_IS_DOUBLE typedef double real_t; diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp index 0c06d2a2b5..06355d15ed 100644 --- a/core/math/math_funcs.cpp +++ b/core/math/math_funcs.cpp @@ -30,30 +30,27 @@ #include "math_funcs.h" -#include "core/os/os.h" - -pcg32_random_t Math::default_pcg = { 12047754176567800795ULL, PCG_DEFAULT_INC_64 }; +RandomPCG Math::default_rand(RandomPCG::DEFAULT_SEED, RandomPCG::DEFAULT_INC); #define PHI 0x9e3779b9 -// TODO: we should eventually expose pcg.inc too uint32_t Math::rand_from_seed(uint64_t *seed) { - pcg32_random_t pcg = { *seed, PCG_DEFAULT_INC_64 }; - uint32_t r = pcg32_random_r(&pcg); - *seed = pcg.state; + RandomPCG rng = RandomPCG(*seed, RandomPCG::DEFAULT_INC); + uint32_t r = rng.rand(); + *seed = rng.get_seed(); return r; } void Math::seed(uint64_t x) { - default_pcg.state = x; + default_rand.seed(x); } void Math::randomize() { - seed(OS::get_singleton()->get_ticks_usec() * default_pcg.state + PCG_DEFAULT_INC_64); + default_rand.randomize(); } uint32_t Math::rand() { - return pcg32_random_r(&default_pcg); + return default_rand.rand(); } int Math::step_decimals(double p_step) { @@ -169,13 +166,9 @@ uint32_t Math::larger_prime(uint32_t p_val) { } double Math::random(double from, double to) { - unsigned int r = Math::rand(); - double ret = (double)r / (double)RANDOM_MAX; - return (ret) * (to - from) + from; + return default_rand.random(from, to); } float Math::random(float from, float to) { - unsigned int r = Math::rand(); - float ret = (float)r / (float)RANDOM_MAX; - return (ret) * (to - from) + from; + return default_rand.random(from, to); } diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 472baf0484..f9d89d5d5a 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -32,6 +32,7 @@ #define MATH_FUNCS_H #include "core/math/math_defs.h" +#include "core/math/random_pcg.h" #include "core/typedefs.h" #include "thirdparty/misc/pcg.h" @@ -41,12 +42,12 @@ class Math { - static pcg32_random_t default_pcg; + static RandomPCG default_rand; public: Math() {} // useless to instance - static const uint64_t RANDOM_MAX = 4294967295; + static const uint64_t RANDOM_MAX = 0xFFFFFFFF; static _ALWAYS_INLINE_ double sin(double p_x) { return ::sin(p_x); } static _ALWAYS_INLINE_ float sin(float p_x) { return ::sinf(p_x); } @@ -305,16 +306,6 @@ public: return b; } -#if defined(__GNUC__) - - static _ALWAYS_INLINE_ int64_t dtoll(double p_double) { return (int64_t)p_double; } ///@TODO OPTIMIZE - static _ALWAYS_INLINE_ int64_t dtoll(float p_float) { return (int64_t)p_float; } ///@TODO OPTIMIZE and rename -#else - - static _ALWAYS_INLINE_ int64_t dtoll(double p_double) { return (int64_t)p_double; } ///@TODO OPTIMIZE - static _ALWAYS_INLINE_ int64_t dtoll(float p_float) { return (int64_t)p_float; } ///@TODO OPTIMIZE and rename -#endif - static _ALWAYS_INLINE_ uint32_t halfbits_to_floatbits(uint16_t h) { uint16_t h_exp, h_sig; uint32_t f_sgn, f_exp, f_sig; diff --git a/core/math/matrix3.cpp b/core/math/matrix3.cpp index fca54b1556..925a7b3f1e 100644 --- a/core/math/matrix3.cpp +++ b/core/math/matrix3.cpp @@ -299,14 +299,14 @@ Vector3 Basis::rotref_posscale_decomposition(Basis &rotref) const { ERR_FAIL_COND_V(determinant() == 0, Vector3()); Basis m = transposed() * (*this); - ERR_FAIL_COND_V(m.is_diagonal() == false, Vector3()); + ERR_FAIL_COND_V(!m.is_diagonal(), Vector3()); #endif Vector3 scale = get_scale(); Basis inv_scale = Basis().scaled(scale.inverse()); // this will also absorb the sign of scale rotref = (*this) * inv_scale; #ifdef MATH_CHECKS - ERR_FAIL_COND_V(rotref.is_orthogonal() == false, Vector3()); + ERR_FAIL_COND_V(!rotref.is_orthogonal(), Vector3()); #endif return scale.abs(); } @@ -430,7 +430,7 @@ Vector3 Basis::get_euler_xyz() const { Vector3 euler; #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_rotation() == false, euler); + ERR_FAIL_COND_V(!is_rotation(), euler); #endif real_t sy = elements[0][2]; if (sy < 1.0) { @@ -497,7 +497,7 @@ Vector3 Basis::get_euler_yxz() const { Vector3 euler; #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_rotation() == false, euler); + ERR_FAIL_COND_V(!is_rotation(), euler); #endif real_t m12 = elements[1][2]; @@ -556,7 +556,7 @@ bool Basis::is_equal_approx(const Basis &a, const Basis &b) const { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { - if (Math::is_equal_approx(a.elements[i][j], b.elements[i][j]) == false) + if (!Math::is_equal_approx(a.elements[i][j], b.elements[i][j])) return false; } } @@ -600,7 +600,7 @@ Basis::operator String() const { Quat Basis::get_quat() const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_rotation() == false, Quat()); + ERR_FAIL_COND_V(!is_rotation(), Quat()); #endif real_t trace = elements[0][0] + elements[1][1] + elements[2][2]; real_t temp[4]; @@ -697,7 +697,7 @@ void Basis::set_orthogonal_index(int p_index) { void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const { #ifdef MATH_CHECKS - ERR_FAIL_COND(is_rotation() == false); + ERR_FAIL_COND(!is_rotation()); #endif real_t angle, x, y, z; // variables for result real_t epsilon = 0.01; // margin to allow for rounding errors @@ -785,7 +785,7 @@ void Basis::set_quat(const Quat &p_quat) { void Basis::set_axis_angle(const Vector3 &p_axis, real_t p_phi) { // Rotation matrix from axis and angle, see https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_angle #ifdef MATH_CHECKS - ERR_FAIL_COND(p_axis.is_normalized() == false); + ERR_FAIL_COND(!p_axis.is_normalized()); #endif Vector3 axis_sq(p_axis.x * p_axis.x, p_axis.y * p_axis.y, p_axis.z * p_axis.z); @@ -837,8 +837,8 @@ void Basis::set_diagonal(const Vector3 p_diag) { Basis Basis::slerp(const Basis &target, const real_t &t) const { // TODO: implement this directly without using quaternions to make it more efficient #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_rotation() == false, Basis()); - ERR_FAIL_COND_V(target.is_rotation() == false, Basis()); + ERR_FAIL_COND_V(!is_rotation(), Basis()); + ERR_FAIL_COND_V(!target.is_rotation(), Basis()); #endif Quat from(*this); diff --git a/core/math/quat.cpp b/core/math/quat.cpp index d660ce4553..791e84f089 100644 --- a/core/math/quat.cpp +++ b/core/math/quat.cpp @@ -100,7 +100,7 @@ void Quat::set_euler_yxz(const Vector3 &p_euler) { // This implementation uses YXZ convention (Z is the first rotation). Vector3 Quat::get_euler_yxz() const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_normalized() == false, Vector3(0, 0, 0)); + ERR_FAIL_COND_V(!is_normalized(), Vector3(0, 0, 0)); #endif Basis m(*this); return m.get_euler_yxz(); @@ -140,15 +140,15 @@ bool Quat::is_normalized() const { Quat Quat::inverse() const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_normalized() == false, Quat()); + ERR_FAIL_COND_V(!is_normalized(), Quat()); #endif return Quat(-x, -y, -z, w); } Quat Quat::slerp(const Quat &q, const real_t &t) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_normalized() == false, Quat()); - ERR_FAIL_COND_V(q.is_normalized() == false, Quat()); + ERR_FAIL_COND_V(!is_normalized(), Quat()); + ERR_FAIL_COND_V(!q.is_normalized(), Quat()); #endif Quat to1; real_t omega, cosom, sinom, scale0, scale1; @@ -194,8 +194,8 @@ Quat Quat::slerp(const Quat &q, const real_t &t) const { Quat Quat::slerpni(const Quat &q, const real_t &t) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_normalized() == false, Quat()); - ERR_FAIL_COND_V(q.is_normalized() == false, Quat()); + ERR_FAIL_COND_V(!is_normalized(), Quat()); + ERR_FAIL_COND_V(!q.is_normalized(), Quat()); #endif const Quat &from = *this; @@ -216,8 +216,8 @@ Quat Quat::slerpni(const Quat &q, const real_t &t) const { Quat Quat::cubic_slerp(const Quat &q, const Quat &prep, const Quat &postq, const real_t &t) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_normalized() == false, Quat()); - ERR_FAIL_COND_V(q.is_normalized() == false, Quat()); + ERR_FAIL_COND_V(!is_normalized(), Quat()); + ERR_FAIL_COND_V(!q.is_normalized(), Quat()); #endif //the only way to do slerp :| real_t t2 = (1.0 - t) * t * 2; @@ -233,7 +233,7 @@ Quat::operator String() const { void Quat::set_axis_angle(const Vector3 &axis, const real_t &angle) { #ifdef MATH_CHECKS - ERR_FAIL_COND(axis.is_normalized() == false); + ERR_FAIL_COND(!axis.is_normalized()); #endif real_t d = axis.length(); if (d == 0) diff --git a/core/math/quat.h b/core/math/quat.h index 10d3846c87..c4f9b3a732 100644 --- a/core/math/quat.h +++ b/core/math/quat.h @@ -87,7 +87,7 @@ public: _FORCE_INLINE_ Vector3 xform(const Vector3 &v) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_normalized() == false, v); + ERR_FAIL_COND_V(!is_normalized(), v); #endif Vector3 u(x, y, z); Vector3 uv = u.cross(v); diff --git a/core/math/random_number_generator.cpp b/core/math/random_number_generator.cpp new file mode 100644 index 0000000000..e4ec0dac99 --- /dev/null +++ b/core/math/random_number_generator.cpp @@ -0,0 +1,45 @@ +/*************************************************************************/ +/* random_number_generator.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "random_number_generator.h" + +RandomNumberGenerator::RandomNumberGenerator() : + randbase() {} + +void RandomNumberGenerator::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_seed", "seed"), &RandomNumberGenerator::set_seed); + ClassDB::bind_method(D_METHOD("get_seed"), &RandomNumberGenerator::get_seed); + ADD_PROPERTY(PropertyInfo(Variant::INT, "seed"), "set_seed", "get_seed"); + + ClassDB::bind_method(D_METHOD("randi"), &RandomNumberGenerator::randi); + ClassDB::bind_method(D_METHOD("randf"), &RandomNumberGenerator::randf); + ClassDB::bind_method(D_METHOD("rand_range", "from", "to"), &RandomNumberGenerator::rand_range); + ClassDB::bind_method(D_METHOD("randomize"), &RandomNumberGenerator::randomize); +} diff --git a/core/math/random_number_generator.h b/core/math/random_number_generator.h new file mode 100644 index 0000000000..557863fdbd --- /dev/null +++ b/core/math/random_number_generator.h @@ -0,0 +1,61 @@ +/*************************************************************************/ +/* random_number_generator.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RANDOM_NUMBER_GENERATOR_H +#define RANDOM_NUMBER_GENERATOR_H + +#include "core/math/random_pcg.h" +#include "core/reference.h" + +class RandomNumberGenerator : public Reference { + GDCLASS(RandomNumberGenerator, Reference); + + RandomPCG randbase; + +protected: + static void _bind_methods(); + +public: + _FORCE_INLINE_ void set_seed(uint64_t seed) { randbase.seed(seed); } + + _FORCE_INLINE_ uint64_t get_seed() { return randbase.get_seed(); } + + _FORCE_INLINE_ void randomize() { return randbase.randomize(); } + + _FORCE_INLINE_ uint32_t randi() { return randbase.rand(); } + + _FORCE_INLINE_ real_t randf() { return randbase.randf(); } + + _FORCE_INLINE_ real_t rand_range(real_t from, real_t to) { return randbase.random(from, to); } + + RandomNumberGenerator(); +}; + +#endif // RANDOM_NUMBER_GENERATOR_H diff --git a/core/math/random_pcg.cpp b/core/math/random_pcg.cpp new file mode 100644 index 0000000000..16899f79da --- /dev/null +++ b/core/math/random_pcg.cpp @@ -0,0 +1,55 @@ +/*************************************************************************/ +/* random_pcg.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "random_pcg.h" + +#include "core/os/os.h" + +RandomPCG::RandomPCG(uint64_t seed, uint64_t inc) : + pcg() { + pcg.state = seed; + pcg.inc = inc; +} + +void RandomPCG::randomize() { + seed(OS::get_singleton()->get_ticks_usec() * pcg.state + PCG_DEFAULT_INC_64); +} + +double RandomPCG::random(double from, double to) { + unsigned int r = rand(); + double ret = (double)r / (double)RANDOM_MAX; + return (ret) * (to - from) + from; +} + +float RandomPCG::random(float from, float to) { + unsigned int r = rand(); + float ret = (float)r / (float)RANDOM_MAX; + return (ret) * (to - from) + from; +} diff --git a/core/math/random_pcg.h b/core/math/random_pcg.h new file mode 100644 index 0000000000..4a43c36ede --- /dev/null +++ b/core/math/random_pcg.h @@ -0,0 +1,61 @@ +/*************************************************************************/ +/* random_pcg.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RANDOM_PCG_H +#define RANDOM_PCG_H + +#include "core/math/math_defs.h" + +#include "thirdparty/misc/pcg.h" + +class RandomPCG { + pcg32_random_t pcg; + +public: + static const uint64_t DEFAULT_SEED = 12047754176567800795ULL; + static const uint64_t DEFAULT_INC = PCG_DEFAULT_INC_64; + static const uint64_t RANDOM_MAX = 4294967295; + + RandomPCG(uint64_t seed = DEFAULT_SEED, uint64_t inc = PCG_DEFAULT_INC_64); + + _FORCE_INLINE_ void seed(uint64_t seed) { pcg.state = seed; } + _FORCE_INLINE_ uint64_t get_seed() { return pcg.state; } + + void randomize(); + _FORCE_INLINE_ uint32_t rand() { return pcg32_random_r(&pcg); } + _FORCE_INLINE_ double randf() { return (double)rand() / (double)RANDOM_MAX; } + _FORCE_INLINE_ float randd() { return (float)rand() / (float)RANDOM_MAX; } + + double random(double from, double to); + float random(float from, float to); + real_t random(int from, int to) { return (real_t)random((real_t)from, (real_t)to); } +}; + +#endif // RANDOM_PCG_H diff --git a/core/math/vector2.cpp b/core/math/vector2.cpp index 84c9f0fca6..7c6f056f09 100644 --- a/core/math/vector2.cpp +++ b/core/math/vector2.cpp @@ -167,7 +167,7 @@ Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, c // slide returns the component of the vector along the given plane, specified by its normal vector. Vector2 Vector2::slide(const Vector2 &p_normal) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(p_normal.is_normalized() == false, Vector2()); + ERR_FAIL_COND_V(!p_normal.is_normalized(), Vector2()); #endif return *this - p_normal * this->dot(p_normal); } @@ -178,7 +178,7 @@ Vector2 Vector2::bounce(const Vector2 &p_normal) const { Vector2 Vector2::reflect(const Vector2 &p_normal) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(p_normal.is_normalized() == false, Vector2()); + ERR_FAIL_COND_V(!p_normal.is_normalized(), Vector2()); #endif return 2.0 * p_normal * this->dot(p_normal) - *this; } diff --git a/core/math/vector2.h b/core/math/vector2.h index df49484aaf..e5e555597d 100644 --- a/core/math/vector2.h +++ b/core/math/vector2.h @@ -230,7 +230,7 @@ Vector2 Vector2::linear_interpolate(const Vector2 &p_b, real_t p_t) const { Vector2 Vector2::slerp(const Vector2 &p_b, real_t p_t) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_normalized() == false, Vector2()); + ERR_FAIL_COND_V(!is_normalized(), Vector2()); #endif real_t theta = angle_to(p_b); return rotated(theta * p_t); diff --git a/core/math/vector3.h b/core/math/vector3.h index 5302832eeb..16feba6a0c 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -218,7 +218,7 @@ Vector3 Vector3::linear_interpolate(const Vector3 &p_b, real_t p_t) const { Vector3 Vector3::slerp(const Vector3 &p_b, real_t p_t) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_normalized() == false, Vector3()); + ERR_FAIL_COND_V(!is_normalized(), Vector3()); #endif real_t theta = angle_to(p_b); @@ -430,7 +430,7 @@ void Vector3::zero() { // slide returns the component of the vector along the given plane, specified by its normal vector. Vector3 Vector3::slide(const Vector3 &p_normal) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(p_normal.is_normalized() == false, Vector3()); + ERR_FAIL_COND_V(!p_normal.is_normalized(), Vector3()); #endif return *this - p_normal * this->dot(p_normal); } @@ -441,7 +441,7 @@ Vector3 Vector3::bounce(const Vector3 &p_normal) const { Vector3 Vector3::reflect(const Vector3 &p_normal) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V(p_normal.is_normalized() == false, Vector3()); + ERR_FAIL_COND_V(!p_normal.is_normalized(), Vector3()); #endif return 2.0 * p_normal * this->dot(p_normal) - *this; } |