Template vector types
parent
f8ce0b1e8c
commit
7254dcb7fc
|
@ -141,7 +141,7 @@ bool can_split(Vector3i node_origin, int node_size, const VoxelAccess &voxels, f
|
|||
}
|
||||
|
||||
inline Vector3f get_center(const OctreeNode *node) {
|
||||
return to_vec3f(node->origin) + 0.5 * Vector3f(node->size, node->size, node->size);
|
||||
return to_vec3f(node->origin) + 0.5f * Vector3f(node->size, node->size, node->size);
|
||||
}
|
||||
|
||||
class OctreeBuilderTopDown {
|
||||
|
|
|
@ -13,15 +13,19 @@ namespace zylann {
|
|||
|
||||
// Explicit conversion methods. Not in respective files because it would cause circular dependencies.
|
||||
|
||||
// Godot => Godot
|
||||
|
||||
// Note, in Godot this is an implicit conversion. But I dont like implicit
|
||||
inline Vector3i to_vec3i(Vector3 v) {
|
||||
return Vector3i(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
inline Vector3i to_vec3i(Vector3f v) {
|
||||
return Vector3i(v.x, v.y, v.z);
|
||||
inline Vector3 to_vec3(const Vector3i v) {
|
||||
return Vector3(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
// Godot => ZN
|
||||
|
||||
inline Vector3f to_vec3f(Vector3i v) {
|
||||
return Vector3f(v.x, v.y, v.z);
|
||||
}
|
||||
|
@ -30,22 +34,29 @@ inline Vector3f to_vec3f(Vector3 v) {
|
|||
return Vector3f(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
inline Vector3 to_vec3(const Vector3f v) {
|
||||
return Vector3(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
inline Vector3 to_vec3(const Vector3i v) {
|
||||
return Vector3(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
inline Vector3d to_vec3d(const Vector3f v) {
|
||||
return Vector3d(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
inline Vector3i16 to_vec3i16(const Vector3i v) {
|
||||
return Vector3i16(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
// ZN => Godot
|
||||
|
||||
template <typename T>
|
||||
inline Vector3i to_vec3i(Vector3T<T> v) {
|
||||
return Vector3i(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Vector3 to_vec3(const Vector3T<T> v) {
|
||||
return Vector3(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
// ZN => ZN
|
||||
|
||||
template <typename T>
|
||||
inline Vector3d to_vec3d(const Vector3T<T> v) {
|
||||
return Vector3d(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
inline bool can_convert_to_i16(Vector3i p) {
|
||||
return p.x >= std::numeric_limits<int16_t>::min() && p.x <= std::numeric_limits<int16_t>::max() &&
|
||||
p.y >= std::numeric_limits<int16_t>::min() && p.y <= std::numeric_limits<int16_t>::max() &&
|
||||
|
|
|
@ -2,78 +2,14 @@
|
|||
#define ZYLANN_VECTOR2F_H
|
||||
|
||||
#include "../errors.h"
|
||||
#include "vector2t.h"
|
||||
|
||||
namespace zylann {
|
||||
|
||||
// 32-bit float precision 2D vector.
|
||||
// Because Godot's `Vector2` uses `real_t`, so when `real_t` is `double` it forces some things to use double-precision
|
||||
// vectors while they dont need that amount of precision.
|
||||
struct Vector2f {
|
||||
static const unsigned int AXIS_X = 0;
|
||||
static const unsigned int AXIS_Y = 1;
|
||||
static const unsigned int AXIS_COUNT = 2;
|
||||
|
||||
union {
|
||||
struct {
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
float coords[2];
|
||||
};
|
||||
|
||||
Vector2f() : x(0), y(0) {}
|
||||
Vector2f(float p_x, float p_y) : x(p_x), y(p_y) {}
|
||||
|
||||
float cross(const Vector2f &p_other) const {
|
||||
return x * p_other.y - y * p_other.x;
|
||||
}
|
||||
|
||||
inline const float &operator[](const unsigned int p_axis) const {
|
||||
#ifdef DEBUG_ENABLED
|
||||
ZN_ASSERT(p_axis < AXIS_COUNT);
|
||||
#endif
|
||||
return coords[p_axis];
|
||||
}
|
||||
|
||||
inline float &operator[](const unsigned int p_axis) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
ZN_ASSERT(p_axis < AXIS_COUNT);
|
||||
#endif
|
||||
return coords[p_axis];
|
||||
}
|
||||
|
||||
inline Vector2f &operator+=(const Vector2f &p_v) {
|
||||
x += p_v.x;
|
||||
y += p_v.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector2f operator+(const Vector2f &p_v) const {
|
||||
return Vector2f(x + p_v.x, y + p_v.y);
|
||||
}
|
||||
|
||||
inline Vector2f operator-(const Vector2f &p_v) const {
|
||||
return Vector2f(x - p_v.x, y - p_v.y);
|
||||
}
|
||||
|
||||
inline Vector2f operator*(const Vector2f &p_v) const {
|
||||
return Vector2f(x * p_v.x, y * p_v.y);
|
||||
}
|
||||
|
||||
inline Vector2f &operator*=(const float p_scalar) {
|
||||
x *= p_scalar;
|
||||
y *= p_scalar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector2f operator*(const float p_scalar) const {
|
||||
return Vector2f(x * p_scalar, y * p_scalar);
|
||||
}
|
||||
};
|
||||
|
||||
inline Vector2f operator*(float p_scalar, const Vector2f &v) {
|
||||
return v * p_scalar;
|
||||
}
|
||||
typedef Vector2T<float> Vector2f;
|
||||
|
||||
namespace math {
|
||||
|
||||
|
@ -83,13 +19,13 @@ inline bool is_point_in_triangle(const Vector2f &s, const Vector2f &a, const Vec
|
|||
const Vector2f bn = b - s;
|
||||
const Vector2f cn = c - s;
|
||||
|
||||
const bool orientation = an.cross(bn) > 0;
|
||||
const bool orientation = cross(an, bn) > 0;
|
||||
|
||||
if ((bn.cross(cn) > 0) != orientation) {
|
||||
if ((cross(bn, cn) > 0) != orientation) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (cn.cross(an) > 0) == orientation;
|
||||
return (cross(cn, an) > 0) == orientation;
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
#ifndef ZN_VECTOR2T_H
|
||||
#define ZN_VECTOR2T_H
|
||||
|
||||
namespace zylann {
|
||||
|
||||
template <typename T>
|
||||
struct Vector2T {
|
||||
static const unsigned int AXIS_X = 0;
|
||||
static const unsigned int AXIS_Y = 1;
|
||||
static const unsigned int AXIS_COUNT = 2;
|
||||
|
||||
union {
|
||||
struct {
|
||||
T x;
|
||||
T y;
|
||||
};
|
||||
T coords[2];
|
||||
};
|
||||
|
||||
Vector2T() : x(0), y(0) {}
|
||||
Vector2T(T p_x, T p_y) : x(p_x), y(p_y) {}
|
||||
|
||||
inline const T &operator[](const unsigned int p_axis) const {
|
||||
#ifdef DEBUG_ENABLED
|
||||
ZN_ASSERT(p_axis < AXIS_COUNT);
|
||||
#endif
|
||||
return coords[p_axis];
|
||||
}
|
||||
|
||||
inline T &operator[](const unsigned int p_axis) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
ZN_ASSERT(p_axis < AXIS_COUNT);
|
||||
#endif
|
||||
return coords[p_axis];
|
||||
}
|
||||
|
||||
inline Vector2T &operator+=(const Vector2T &p_v) {
|
||||
x += p_v.x;
|
||||
y += p_v.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector2T operator+(const Vector2T &p_v) const {
|
||||
return Vector2T(x + p_v.x, y + p_v.y);
|
||||
}
|
||||
|
||||
inline Vector2T operator-(const Vector2T &p_v) const {
|
||||
return Vector2T(x - p_v.x, y - p_v.y);
|
||||
}
|
||||
|
||||
inline Vector2T operator*(const Vector2T &p_v) const {
|
||||
return Vector2T(x * p_v.x, y * p_v.y);
|
||||
}
|
||||
|
||||
inline Vector2T &operator*=(const T p_scalar) {
|
||||
x *= p_scalar;
|
||||
y *= p_scalar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector2T operator*(const T p_scalar) const {
|
||||
return Vector2T(x * p_scalar, y * p_scalar);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline Vector2T<T> operator*(T p_scalar, const Vector2T<T> &v) {
|
||||
return v * p_scalar;
|
||||
}
|
||||
|
||||
namespace math {
|
||||
|
||||
template <typename T>
|
||||
T cross(const Vector2T<T> &a, const Vector2T<T> &b) {
|
||||
return a.x * b.y - a.y * b.x;
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace zylann
|
||||
|
||||
#endif // ZN_VECTOR2T_H
|
|
@ -4,6 +4,9 @@
|
|||
#include "funcs.h"
|
||||
#include <core/math/vector3.h>
|
||||
|
||||
// 3-dimensional vector which components are either 32-bit float or 64-bit float depending on how Godot was compiled.
|
||||
// This is the type to use for interoperating with Godot.
|
||||
|
||||
namespace zylann::math {
|
||||
|
||||
inline Vector3 fract(const Vector3 &p) {
|
||||
|
|
|
@ -1,117 +1,13 @@
|
|||
#ifndef ZN_VECTOR3D_H
|
||||
#define ZN_VECTOR3D_H
|
||||
|
||||
#include "vector3t.h"
|
||||
|
||||
namespace zylann {
|
||||
|
||||
struct Vector3d {
|
||||
static const unsigned int AXIS_X = 0;
|
||||
static const unsigned int AXIS_Y = 1;
|
||||
static const unsigned int AXIS_Z = 2;
|
||||
static const unsigned int AXIS_COUNT = 3;
|
||||
// 3-dimensional vector using 64-bit floats, regardless on compiling options
|
||||
typedef Vector3T<double> Vector3d;
|
||||
|
||||
union {
|
||||
struct {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
double coords[3];
|
||||
};
|
||||
|
||||
Vector3d() : x(0), y(0), z(0) {}
|
||||
|
||||
// It is recommended to use `explicit` because otherwise it would open the door to plenty of implicit conversions
|
||||
// which would make many cases ambiguous.
|
||||
explicit Vector3d(double p_v) : x(p_v), y(p_v), z(p_v) {}
|
||||
|
||||
Vector3d(double p_x, double p_y, double p_z) : x(p_x), y(p_y), z(p_z) {}
|
||||
|
||||
inline Vector3d &operator+=(const Vector3d &p_v) {
|
||||
x += p_v.x;
|
||||
y += p_v.y;
|
||||
z += p_v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector3d operator+(const Vector3d &p_v) const {
|
||||
return Vector3d(x + p_v.x, y + p_v.y, z + p_v.z);
|
||||
}
|
||||
|
||||
inline Vector3d &operator-=(const Vector3d &p_v) {
|
||||
x -= p_v.x;
|
||||
y -= p_v.y;
|
||||
z -= p_v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector3d operator-(const Vector3d &p_v) const {
|
||||
return Vector3d(x - p_v.x, y - p_v.y, z - p_v.z);
|
||||
}
|
||||
|
||||
inline Vector3d &operator*=(const Vector3d &p_v) {
|
||||
x *= p_v.x;
|
||||
y *= p_v.y;
|
||||
z *= p_v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector3d operator*(const Vector3d &p_v) const {
|
||||
return Vector3d(x * p_v.x, y * p_v.y, z * p_v.z);
|
||||
}
|
||||
|
||||
inline Vector3d &operator/=(const Vector3d &p_v) {
|
||||
x /= p_v.x;
|
||||
y /= p_v.y;
|
||||
z /= p_v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector3d operator/(const Vector3d &p_v) const {
|
||||
return Vector3d(x / p_v.x, y / p_v.y, z / p_v.z);
|
||||
}
|
||||
|
||||
inline Vector3d &operator*=(const double p_scalar) {
|
||||
x *= p_scalar;
|
||||
y *= p_scalar;
|
||||
z *= p_scalar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector3d operator*(const double p_scalar) const {
|
||||
return Vector3d(x * p_scalar, y * p_scalar, z * p_scalar);
|
||||
}
|
||||
|
||||
inline Vector3d &operator/=(const double p_scalar) {
|
||||
x /= p_scalar;
|
||||
y /= p_scalar;
|
||||
z /= p_scalar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector3d operator/(const double p_scalar) const {
|
||||
return Vector3d(x / p_scalar, y / p_scalar, z / p_scalar);
|
||||
}
|
||||
|
||||
inline Vector3d operator-() const {
|
||||
return Vector3d(-x, -y, -z);
|
||||
}
|
||||
};
|
||||
|
||||
namespace math {
|
||||
|
||||
inline Vector3d cross(const Vector3d &a, const Vector3d &b) {
|
||||
const Vector3d ret( //
|
||||
(a.y * b.z) - (a.z * b.y), //
|
||||
(a.z * b.x) - (a.x * b.z), //
|
||||
(a.x * b.y) - (a.y * b.x));
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline double dot(const Vector3d &a, const Vector3d &b) {
|
||||
return a.x * b.x + a.y * b.y + a.z * b.z;
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace zylann
|
||||
|
||||
#endif // ZN_VECTOR3D_H
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define ZYLANN_VECTOR3F_H
|
||||
|
||||
#include "../errors.h"
|
||||
#include "funcs.h"
|
||||
#include "vector3t.h"
|
||||
#include <iosfwd>
|
||||
|
||||
namespace zylann {
|
||||
|
@ -11,146 +11,10 @@ namespace zylann {
|
|||
// Because Godot's `Vector3` uses `real_t`, so when `real_t` is `double` it forces some things to use double-precision
|
||||
// vectors while they dont need that amount of precision. This is also a problem for some third-party libraries
|
||||
// that do not support `double` as a result.
|
||||
struct Vector3f {
|
||||
static const unsigned int AXIS_X = 0;
|
||||
static const unsigned int AXIS_Y = 1;
|
||||
static const unsigned int AXIS_Z = 2;
|
||||
static const unsigned int AXIS_COUNT = 3;
|
||||
|
||||
union {
|
||||
struct {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
float coords[3];
|
||||
};
|
||||
|
||||
Vector3f() : x(0), y(0), z(0) {}
|
||||
|
||||
// It is recommended to use `explicit` because otherwise it would open the door to plenty of implicit conversions
|
||||
// which would make many cases ambiguous.
|
||||
explicit Vector3f(float p_v) : x(p_v), y(p_v), z(p_v) {}
|
||||
|
||||
Vector3f(float p_x, float p_y, float p_z) : x(p_x), y(p_y), z(p_z) {}
|
||||
|
||||
inline const float &operator[](const unsigned int p_axis) const {
|
||||
#ifdef DEBUG_ENABLED
|
||||
ZN_ASSERT(p_axis < AXIS_COUNT);
|
||||
#endif
|
||||
return coords[p_axis];
|
||||
}
|
||||
|
||||
inline float &operator[](const unsigned int p_axis) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
ZN_ASSERT(p_axis < AXIS_COUNT);
|
||||
#endif
|
||||
return coords[p_axis];
|
||||
}
|
||||
|
||||
inline Vector3f &operator+=(const Vector3f &p_v) {
|
||||
x += p_v.x;
|
||||
y += p_v.y;
|
||||
z += p_v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector3f operator+(const Vector3f &p_v) const {
|
||||
return Vector3f(x + p_v.x, y + p_v.y, z + p_v.z);
|
||||
}
|
||||
|
||||
inline Vector3f &operator-=(const Vector3f &p_v) {
|
||||
x -= p_v.x;
|
||||
y -= p_v.y;
|
||||
z -= p_v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector3f operator-(const Vector3f &p_v) const {
|
||||
return Vector3f(x - p_v.x, y - p_v.y, z - p_v.z);
|
||||
}
|
||||
|
||||
inline Vector3f &operator*=(const Vector3f &p_v) {
|
||||
x *= p_v.x;
|
||||
y *= p_v.y;
|
||||
z *= p_v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector3f operator*(const Vector3f &p_v) const {
|
||||
return Vector3f(x * p_v.x, y * p_v.y, z * p_v.z);
|
||||
}
|
||||
|
||||
inline Vector3f &operator/=(const Vector3f &p_v) {
|
||||
x /= p_v.x;
|
||||
y /= p_v.y;
|
||||
z /= p_v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector3f operator/(const Vector3f &p_v) const {
|
||||
return Vector3f(x / p_v.x, y / p_v.y, z / p_v.z);
|
||||
}
|
||||
|
||||
inline Vector3f &operator*=(const float p_scalar) {
|
||||
x *= p_scalar;
|
||||
y *= p_scalar;
|
||||
z *= p_scalar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector3f operator*(const float p_scalar) const {
|
||||
return Vector3f(x * p_scalar, y * p_scalar, z * p_scalar);
|
||||
}
|
||||
|
||||
inline Vector3f &operator/=(const float p_scalar) {
|
||||
x /= p_scalar;
|
||||
y /= p_scalar;
|
||||
z /= p_scalar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector3f operator/(const float p_scalar) const {
|
||||
return Vector3f(x / p_scalar, y / p_scalar, z / p_scalar);
|
||||
}
|
||||
|
||||
inline Vector3f operator-() const {
|
||||
return Vector3f(-x, -y, -z);
|
||||
}
|
||||
|
||||
inline bool operator==(const Vector3f &p_v) const {
|
||||
return x == p_v.x && y == p_v.y && z == p_v.z;
|
||||
}
|
||||
|
||||
inline bool operator!=(const Vector3f &p_v) const {
|
||||
return x != p_v.x || y != p_v.y || z != p_v.z;
|
||||
}
|
||||
|
||||
inline bool operator<(const Vector3f &p_v) const {
|
||||
if (x == p_v.x) {
|
||||
if (y == p_v.y) {
|
||||
return z < p_v.z;
|
||||
}
|
||||
return y < p_v.y;
|
||||
}
|
||||
return x < p_v.x;
|
||||
}
|
||||
};
|
||||
|
||||
inline Vector3f operator*(float p_scalar, const Vector3f &v) {
|
||||
return v * p_scalar;
|
||||
}
|
||||
typedef Vector3T<float> Vector3f;
|
||||
|
||||
namespace math {
|
||||
|
||||
inline Vector3f min(const Vector3f a, const Vector3f b) {
|
||||
return Vector3f(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
|
||||
}
|
||||
|
||||
inline Vector3f max(const Vector3f a, const Vector3f b) {
|
||||
return Vector3f(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
|
||||
}
|
||||
|
||||
inline Vector3f floor(const Vector3f a) {
|
||||
return Vector3f(Math::floor(a.x), Math::floor(a.y), Math::floor(a.z));
|
||||
}
|
||||
|
@ -167,30 +31,6 @@ inline bool has_nan(const Vector3f &v) {
|
|||
return Math::is_nan(v.x) || Math::is_nan(v.y) || Math::is_nan(v.z);
|
||||
}
|
||||
|
||||
inline float length_squared(const Vector3f v) {
|
||||
return v.x * v.x + v.y * v.y + v.z * v.z;
|
||||
}
|
||||
|
||||
inline float length(const Vector3f &v) {
|
||||
return Math::sqrt(length_squared(v));
|
||||
}
|
||||
|
||||
inline float distance_squared(const Vector3f &a, const Vector3f &b) {
|
||||
return length_squared(b - a);
|
||||
}
|
||||
|
||||
inline Vector3f cross(const Vector3f &a, const Vector3f &b) {
|
||||
const Vector3f ret( //
|
||||
(a.y * b.z) - (a.z * b.y), //
|
||||
(a.z * b.x) - (a.x * b.z), //
|
||||
(a.x * b.y) - (a.y * b.x));
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline float dot(const Vector3f &a, const Vector3f &b) {
|
||||
return a.x * b.x + a.y * b.y + a.z * b.z;
|
||||
}
|
||||
|
||||
inline Vector3f normalized(const Vector3f &v) {
|
||||
const float lengthsq = length_squared(v);
|
||||
if (lengthsq == 0) {
|
||||
|
@ -206,10 +46,6 @@ inline bool is_normalized(const Vector3f &v) {
|
|||
return Math::is_equal_approx(length_squared(v), 1, float(UNIT_EPSILON));
|
||||
}
|
||||
|
||||
inline float distance(const Vector3f &a, const Vector3f &b) {
|
||||
return Math::sqrt(distance_squared(a, b));
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
|
||||
std::stringstream &operator<<(std::stringstream &ss, const Vector3f &v);
|
||||
|
|
|
@ -1,27 +1,13 @@
|
|||
#ifndef ZN_VECTOR3I16_H
|
||||
#define ZN_VECTOR3I16_H
|
||||
|
||||
#include "vector3t.h"
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
|
||||
namespace zylann {
|
||||
|
||||
struct Vector3i16 {
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
int16_t z;
|
||||
|
||||
Vector3i16() : x(0), y(0), z(0) {}
|
||||
Vector3i16(int16_t p_x, int16_t p_y, int16_t p_z) : x(p_x), y(p_y), z(p_z) {}
|
||||
|
||||
inline bool operator==(const Vector3i16 p_v) const {
|
||||
return x == p_v.x && y == p_v.y && z == p_v.z;
|
||||
}
|
||||
|
||||
inline bool operator!=(const Vector3i16 p_v) const {
|
||||
return x != p_v.x || y != p_v.y || z != p_v.z;
|
||||
}
|
||||
};
|
||||
typedef Vector3T<int16_t> Vector3i16;
|
||||
|
||||
inline size_t get_hash_st(const zylann::Vector3i16 &v) {
|
||||
// TODO Optimization: benchmark this hash, I just wanted one that works
|
||||
|
|
|
@ -0,0 +1,193 @@
|
|||
#ifndef ZYLANN_VECTOR3T_H
|
||||
#define ZYLANN_VECTOR3T_H
|
||||
|
||||
#include "../errors.h"
|
||||
#include "funcs.h"
|
||||
|
||||
namespace zylann {
|
||||
|
||||
// Template 3-dimensional vector. Only fields and standard operators.
|
||||
// Math functions are separate to allow more unified overloading, and similarity with other math libraries such as
|
||||
// shaders.
|
||||
template <typename T>
|
||||
struct Vector3T {
|
||||
static const unsigned int AXIS_X = 0;
|
||||
static const unsigned int AXIS_Y = 1;
|
||||
static const unsigned int AXIS_Z = 2;
|
||||
static const unsigned int AXIS_COUNT = 3;
|
||||
|
||||
union {
|
||||
struct {
|
||||
T x;
|
||||
T y;
|
||||
T z;
|
||||
};
|
||||
T coords[3];
|
||||
};
|
||||
|
||||
Vector3T() : x(0), y(0), z(0) {}
|
||||
|
||||
// It is recommended to use `explicit` because otherwise it would open the door to plenty of implicit conversions
|
||||
// which would make many cases ambiguous.
|
||||
explicit Vector3T(T p_v) : x(p_v), y(p_v), z(p_v) {}
|
||||
|
||||
Vector3T(T p_x, T p_y, T p_z) : x(p_x), y(p_y), z(p_z) {}
|
||||
|
||||
inline const T &operator[](const unsigned int p_axis) const {
|
||||
#ifdef DEBUG_ENABLED
|
||||
ZN_ASSERT(p_axis < AXIS_COUNT);
|
||||
#endif
|
||||
return coords[p_axis];
|
||||
}
|
||||
|
||||
inline T &operator[](const unsigned int p_axis) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
ZN_ASSERT(p_axis < AXIS_COUNT);
|
||||
#endif
|
||||
return coords[p_axis];
|
||||
}
|
||||
|
||||
inline Vector3T &operator+=(const Vector3T &p_v) {
|
||||
x += p_v.x;
|
||||
y += p_v.y;
|
||||
z += p_v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector3T operator+(const Vector3T &p_v) const {
|
||||
return Vector3T(x + p_v.x, y + p_v.y, z + p_v.z);
|
||||
}
|
||||
|
||||
inline Vector3T &operator-=(const Vector3T &p_v) {
|
||||
x -= p_v.x;
|
||||
y -= p_v.y;
|
||||
z -= p_v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector3T operator-(const Vector3T &p_v) const {
|
||||
return Vector3T(x - p_v.x, y - p_v.y, z - p_v.z);
|
||||
}
|
||||
|
||||
inline Vector3T &operator*=(const Vector3T &p_v) {
|
||||
x *= p_v.x;
|
||||
y *= p_v.y;
|
||||
z *= p_v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector3T operator*(const Vector3T &p_v) const {
|
||||
return Vector3T(x * p_v.x, y * p_v.y, z * p_v.z);
|
||||
}
|
||||
|
||||
inline Vector3T &operator/=(const Vector3T &p_v) {
|
||||
x /= p_v.x;
|
||||
y /= p_v.y;
|
||||
z /= p_v.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector3T operator/(const Vector3T &p_v) const {
|
||||
return Vector3T(x / p_v.x, y / p_v.y, z / p_v.z);
|
||||
}
|
||||
|
||||
inline Vector3T &operator*=(const T p_scalar) {
|
||||
x *= p_scalar;
|
||||
y *= p_scalar;
|
||||
z *= p_scalar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector3T operator*(const T p_scalar) const {
|
||||
return Vector3T(x * p_scalar, y * p_scalar, z * p_scalar);
|
||||
}
|
||||
|
||||
inline Vector3T &operator/=(const T p_scalar) {
|
||||
x /= p_scalar;
|
||||
y /= p_scalar;
|
||||
z /= p_scalar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector3T operator/(const T p_scalar) const {
|
||||
return Vector3T(x / p_scalar, y / p_scalar, z / p_scalar);
|
||||
}
|
||||
|
||||
inline Vector3T operator-() const {
|
||||
return Vector3T(-x, -y, -z);
|
||||
}
|
||||
|
||||
inline bool operator==(const Vector3T &p_v) const {
|
||||
return x == p_v.x && y == p_v.y && z == p_v.z;
|
||||
}
|
||||
|
||||
inline bool operator!=(const Vector3T &p_v) const {
|
||||
return x != p_v.x || y != p_v.y || z != p_v.z;
|
||||
}
|
||||
|
||||
inline bool operator<(const Vector3T &p_v) const {
|
||||
if (x == p_v.x) {
|
||||
if (y == p_v.y) {
|
||||
return z < p_v.z;
|
||||
}
|
||||
return y < p_v.y;
|
||||
}
|
||||
return x < p_v.x;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline Vector3T<T> operator*(T p_scalar, const Vector3T<T> &v) {
|
||||
return v * p_scalar;
|
||||
}
|
||||
|
||||
namespace math {
|
||||
|
||||
template <typename T>
|
||||
inline Vector3T<T> min(const Vector3T<T> a, const Vector3T<T> b) {
|
||||
return Vector3f(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Vector3T<T> max(const Vector3T<T> a, const Vector3T<T> b) {
|
||||
return Vector3f(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T length_squared(const Vector3T<T> v) {
|
||||
return v.x * v.x + v.y * v.y + v.z * v.z;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T length(const Vector3T<T> &v) {
|
||||
return Math::sqrt(length_squared(v));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T distance_squared(const Vector3T<T> &a, const Vector3T<T> &b) {
|
||||
return length_squared(b - a);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T distance(const Vector3T<T> &a, const Vector3T<T> &b) {
|
||||
return Math::sqrt(distance_squared(a, b));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Vector3T<T> cross(const Vector3T<T> &a, const Vector3T<T> &b) {
|
||||
const Vector3T<T> ret( //
|
||||
(a.y * b.z) - (a.z * b.y), //
|
||||
(a.z * b.x) - (a.x * b.z), //
|
||||
(a.x * b.y) - (a.y * b.x));
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T dot(const Vector3T<T> &a, const Vector3T<T> &b) {
|
||||
return a.x * b.x + a.y * b.y + a.z * b.z;
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace zylann
|
||||
|
||||
#endif // ZYLANN_VECTOR3F_H
|
Loading…
Reference in New Issue