diff options
author | Daniel Rakos <daniel.rakos@rastergrid.com> | 2019-04-07 16:03:20 +0200 |
---|---|---|
committer | Daniel Rakos <daniel.rakos@rastergrid.com> | 2019-04-08 16:28:41 +0200 |
commit | abccf9a0501edef76bcbde3f98e6b6f52156ffd1 (patch) | |
tree | 8a568c083ad6c2c263566947b5e8e7182f7b7890 /include/core/Vector2.hpp | |
parent | df04c4097fe09204e1906ae76996b80376d84d34 (diff) | |
download | redot-cpp-abccf9a0501edef76bcbde3f98e6b6f52156ffd1.tar.gz |
Make Basis look column-major while retaining a row-major representation
Per https://github.com/godotengine/godot/issues/14553:
Godot stores Basis in row-major layout for more change for efficiently
taking advantage of SIMD instructions, but in scripts Basis looks like and
is accessible in a column-major format.
This change modifies the C++ binding so that from the script's perspective
Basis does look like if it was column-major while retaining a row-major
in-memory representation. This is achieved using a set of helper template
classes which allow accessing individual columns whose components are
non-continues in memory as if it was a Vector3 type. This ensures script
interface compatibility without needing to transpose the Basis every time
it is passed over the script-engine boundary.
Also made most of the Vector2 and Vector3 class interfaces inlined in the
process for increased performance.
While unrelated (but didn't want to file a separate PR for it), this change
adds the necessary flags to have debug symbol information under MSVC.
Fixes #241.
Diffstat (limited to 'include/core/Vector2.hpp')
-rw-r--r-- | include/core/Vector2.hpp | 184 |
1 files changed, 141 insertions, 43 deletions
diff --git a/include/core/Vector2.hpp b/include/core/Vector2.hpp index 190217d..26e9b63 100644 --- a/include/core/Vector2.hpp +++ b/include/core/Vector2.hpp @@ -5,6 +5,8 @@ #include "Defs.hpp" +#include <cmath> + namespace godot { class String; @@ -20,36 +22,75 @@ struct Vector2 { real_t height; }; + inline Vector2(real_t p_x, real_t p_y) { + x = p_x; + y = p_y; + } + + inline Vector2() { + x = 0; + y = 0; + } + inline real_t &operator[](int p_idx) { return p_idx ? y : x; } + inline const real_t &operator[](int p_idx) const { return p_idx ? y : x; } - Vector2 operator+(const Vector2 &p_v) const; + inline Vector2 operator+(const Vector2 &p_v) const { + return Vector2(x + p_v.x, y + p_v.y); + } - void operator+=(const Vector2 &p_v); + inline void operator+=(const Vector2 &p_v) { + x += p_v.x; + y += p_v.y; + } - Vector2 operator-(const Vector2 &p_v) const; + inline Vector2 operator-(const Vector2 &p_v) const { + return Vector2(x - p_v.x, y - p_v.y); + } - void operator-=(const Vector2 &p_v); + inline void operator-=(const Vector2 &p_v) { + x -= p_v.x; + y -= p_v.y; + } - Vector2 operator*(const Vector2 &p_v1) const; + inline Vector2 operator*(const Vector2 &p_v1) const { + return Vector2(x * p_v1.x, y * p_v1.y); + } - Vector2 operator*(const real_t &rvalue) const; + inline Vector2 operator*(const real_t &rvalue) const { + return Vector2(x * rvalue, y * rvalue); + } - void operator*=(const real_t &rvalue); + inline void operator*=(const real_t &rvalue) { + x *= rvalue; + y *= rvalue; + } - inline void operator*=(const Vector2 &rvalue) { *this = *this * rvalue; } + inline void operator*=(const Vector2 &rvalue) { + *this = *this * rvalue; + } - Vector2 operator/(const Vector2 &p_v1) const; + inline Vector2 operator/(const Vector2 &p_v1) const { + return Vector2(x / p_v1.x, y / p_v1.y); + } - Vector2 operator/(const real_t &rvalue) const; + inline Vector2 operator/(const real_t &rvalue) const { + return Vector2(x / rvalue, y / rvalue); + } - void operator/=(const real_t &rvalue); + inline void operator/=(const real_t &rvalue) { + x /= rvalue; + y /= rvalue; + } - Vector2 operator-() const; + inline Vector2 operator-() const { + return Vector2(-x, -y); + } bool operator==(const Vector2 &p_vec2) const; @@ -58,23 +99,56 @@ struct Vector2 { inline bool operator<(const Vector2 &p_vec2) const { return (x == p_vec2.x) ? (y < p_vec2.y) : (x < p_vec2.x); } inline bool operator<=(const Vector2 &p_vec2) const { return (x == p_vec2.x) ? (y <= p_vec2.y) : (x <= p_vec2.x); } - void normalize(); + inline void normalize() { + real_t l = x * x + y * y; + if (l != 0) { + l = sqrt(l); + x /= l; + y /= l; + } + } - Vector2 normalized() const; + inline Vector2 normalized() const { + Vector2 v = *this; + v.normalize(); + return v; + } - real_t length() const; - real_t length_squared() const; + inline real_t length() const { + return sqrt(x * x + y * y); + } - real_t distance_to(const Vector2 &p_vector2) const; - real_t distance_squared_to(const Vector2 &p_vector2) const; + inline real_t length_squared() const { + return x * x + y * y; + } - real_t angle_to(const Vector2 &p_vector2) const; - real_t angle_to_point(const Vector2 &p_vector2) const; + inline real_t distance_to(const Vector2 &p_vector2) const { + return sqrt((x - p_vector2.x) * (x - p_vector2.x) + (y - p_vector2.y) * (y - p_vector2.y)); + } - real_t dot(const Vector2 &p_other) const; + inline real_t distance_squared_to(const Vector2 &p_vector2) const { + return (x - p_vector2.x) * (x - p_vector2.x) + (y - p_vector2.y) * (y - p_vector2.y); + } - real_t cross(const Vector2 &p_other) const; - Vector2 cross(real_t p_other) const; + inline real_t angle_to(const Vector2 &p_vector2) const { + return atan2(cross(p_vector2), dot(p_vector2)); + } + + inline real_t angle_to_point(const Vector2 &p_vector2) const { + return atan2(y - p_vector2.y, x - p_vector2.x); + } + + inline real_t dot(const Vector2 &p_other) const { + return x * p_other.x + y * p_other.y; + } + + inline real_t cross(const Vector2 &p_other) const { + return x * p_other.y - y * p_other.x; + } + + inline Vector2 cross(real_t p_other) const { + return Vector2(p_other * y, -p_other * x); + } Vector2 project(const Vector2 &p_vec) const; @@ -82,39 +156,63 @@ struct Vector2 { Vector2 clamped(real_t p_len) const; - static Vector2 linear_interpolate(const Vector2 &p_a, const Vector2 &p_b, real_t p_t); + static inline Vector2 linear_interpolate(const Vector2 &p_a, const Vector2 &p_b, real_t p_t) { + Vector2 res = p_a; + res.x += (p_t * (p_b.x - p_a.x)); + res.y += (p_t * (p_b.y - p_a.y)); + return res; + } + + inline Vector2 linear_interpolate(const Vector2 &p_b, real_t p_t) const { + Vector2 res = *this; + res.x += (p_t * (p_b.x - x)); + res.y += (p_t * (p_b.y - y)); + return res; + } - Vector2 linear_interpolate(const Vector2 &p_b, real_t p_t) const; Vector2 cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_t) const; - Vector2 slide(const Vector2 &p_vec) const; + inline Vector2 slide(const Vector2 &p_vec) const { + return p_vec - *this * this->dot(p_vec); + } + + inline Vector2 reflect(const Vector2 &p_vec) const { + return p_vec - *this * this->dot(p_vec) * 2.0; + } + + inline real_t angle() const { + return atan2(y, x); + } - Vector2 reflect(const Vector2 &p_vec) const; + inline void set_rotation(real_t p_radians) { + x = cosf(p_radians); + y = sinf(p_radians); + } - real_t angle() const; + inline Vector2 abs() const { + return Vector2(fabs(x), fabs(y)); + } - void set_rotation(real_t p_radians); + inline Vector2 rotated(real_t p_by) const { + Vector2 v; + v.set_rotation(angle() + p_by); + v *= length(); + return v; + } - Vector2 abs() const; - Vector2 rotated(real_t p_by) const; + inline Vector2 tangent() const { + return Vector2(y, -x); + } - Vector2 tangent() const; + inline Vector2 floor() const { + return Vector2(::floor(x), ::floor(y)); + } - Vector2 floor() const; + inline Vector2 snapped(const Vector2 &p_by) const; - Vector2 snapped(const Vector2 &p_by) const; inline real_t aspect() const { return width / height; } operator String() const; - - inline Vector2(real_t p_x, real_t p_y) { - x = p_x; - y = p_y; - } - inline Vector2() { - x = 0; - y = 0; - } }; inline Vector2 operator*(real_t p_scalar, const Vector2 &p_vec) { |