14#define VECTOR_Up Vector3D(0, 1, 0)
15#define VECTOR_Down Vector3D(0, -1, 0)
16#define VECTOR_Right Vector3D(1, 0, 0)
17#define VECTOR_Left Vector3D(-1, 0, 0)
18#define VECTOR_Forward Vector3D(0, 0, 1)
19#define VECTOR_Backward Vector3D(0, 0, -1)
30 template <
typename T,
size_t N>
34 constexpr Vector() noexcept { data.fill(
static_cast<T
>(0)); }
36 constexpr Vector(std::initializer_list<T> list) {
37 if (list.size() != N) {
38 throw std::invalid_argument(
39 "Initializer list size does not match vector "
42 std::copy_n(list.begin(), N, data.begin());
47 assert(index < N &&
"Vector index out of range");
53 assert(index < N &&
"Vector index out of range");
60 std::transform(data.begin(), data.end(), other.data.begin(),
61 result.data.begin(), std::plus<T>());
67 std::transform(data.begin(), data.end(), other.data.begin(),
68 result.data.begin(), std::minus<T>());
73 std::transform(data.begin(), data.end(), other.data.begin(),
74 data.begin(), std::plus<T>());
79 std::transform(data.begin(), data.end(), other.data.begin(),
80 data.begin(), std::minus<T>());
87 data.begin(), data.end(), result.data.begin(),
88 [scalar](
const T& val) { return val * scalar; });
94 throw std::invalid_argument(
"Division by zero");
97 for (
size_t i = 0; i < N; ++i) {
98 result[i] = data[i] / scalar;
106 for (
size_t i = 0; i < N; ++i) {
107 result += data[i] * other[i];
113 template <
size_t M = N>
114 typename std::enable_if<M == 3, Vector<T, N>>::type
116 static_assert(N == 3,
"Cross product is only defined for 3D vectors");
118 data[1] * other[2] - data[2] * other[1],
119 data[2] * other[0] - data[0] * other[2],
120 data[0] * other[1] - data[1] * other[0]
127 for (
size_t i = 0; i < N; ++i) {
128 sum += data[i] * data[i];
130 return std::sqrt(sum);
137 data[0] = 0.0f; data[1] = 0.0f; data[2] = 0.0f;
153 for (
size_t i = 0; i < N; ++i) {
154 if (std::abs(data[i] - other[i]) >=
EPSILON) {
163 return !(*
this == other);
168 std::ostringstream ss;
169 ss <<
"Vector<" << N <<
">(";
170 for (
size_t i = 0; i < N; ++i) {
172 if (i < N - 1) ss <<
", ";
190 std::array<T, N> data;
214 constexpr Vector2D(
float x,
float y) : vec({x, y}) {}
217 constexpr float GetX()
const {
return vec[0]; }
218 constexpr float GetY()
const {
return vec[1]; }
221 void SetX(
float val) { vec[0] = val; }
222 void SetY(
float val) { vec[1] = val; }
223 void Set(
float x,
float y) { vec[0] = x; vec[1] = y; }
225 void AddX(
float val) { vec[0] += val; }
226 void AddY(
float val) { vec[1] += val; }
227 void Add(
float x,
float y) { vec[0] += x; vec[1] += y; }
231 return Vector2D(vec[0] + other.vec[0], vec[1] + other.vec[1]);
235 return Vector2D(vec[0] - other.vec[0], vec[1] - other.vec[1]);
239 vec[0] += other.vec[0];
240 vec[1] += other.vec[1];
245 vec[0] -= other.vec[0];
246 vec[1] -= other.vec[1];
252 return Vector2D(vec[0] * scalar, vec[1] * scalar);
256 if (scalar == 0)
throw std::invalid_argument(
"Division by zero");
257 return Vector2D(vec[0] / scalar, vec[1] / scalar);
262 return vec[0] * other.vec[0] + vec[1] * other.vec[1];
266 return vec[0] * other.vec[1] - vec[1] * other.vec[0];
271 return std::hypot(vec[0], vec[1]);
276 if (mag == 0)
throw std::runtime_error(
"Cannot normalize a zero vector");
289 return std::abs(vec[0] - other.vec[0]) <
EPSILON &&
290 std::abs(vec[1] - other.vec[1]) <
EPSILON;
294 return !(*
this == other);
298 os << vec.ToString();
307 std::ostringstream ss;
308 ss << std::fixed << std::setprecision(precision);
309 ss <<
"Vector2D(" << vec[0] <<
", " << vec[1] <<
")";
314 return vec.ToRawArray();
358 Vector3D(
float x,
float y,
float z) : vec({x, y, z}) {}
361 float GetX()
const {
return vec[0]; }
362 float GetY()
const {
return vec[1]; }
363 float GetZ()
const {
return vec[2]; }
366 void SetX(
float val) { vec[0] = val; }
367 void SetY(
float val) { vec[1] = val; }
368 void SetZ(
float val) { vec[2] = val; }
369 void Set(
float x,
float y,
float z) {
370 vec[0] = x; vec[1] = y; vec[2] = z;
373 void AddX(
float val) { vec[0] += val; }
374 void AddY(
float val) { vec[1] += val; }
375 void AddZ(
float val) { vec[2] += val; }
376 void Add(
float x,
float y,
float z) {
377 vec[0] += x; vec[1] += y; vec[2] += z;
382 return Vector3D(vec[0] + other.vec[0], vec[1] + other.vec[1], vec[2] + other.vec[2]);
386 return Vector3D(vec[0] - other.vec[0], vec[1] - other.vec[1], vec[2] - other.vec[2]);
390 vec[0] += other.vec[0];
391 vec[1] += other.vec[1];
392 vec[2] += other.vec[2];
397 vec[0] -= other.vec[0];
398 vec[1] -= other.vec[1];
399 vec[2] -= other.vec[2];
405 return Vector3D(vec[0] * scalar, vec[1] * scalar, vec[2] * scalar);
413 if (scalar == 0)
throw std::invalid_argument(
"Division by zero");
414 return Vector3D(vec[0] / scalar, vec[1] / scalar, vec[2] / scalar);
419 return vec[0] * other.vec[0] + vec[1] * other.vec[1] + vec[2] * other.vec[2];
424 vec[1] * other.vec[2] - vec[2] * other.vec[1],
425 vec[2] * other.vec[0] - vec[0] * other.vec[2],
426 vec[0] * other.vec[1] - vec[1] * other.vec[0]
432 return std::sqrt(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]);
463 return std::abs(vec[0] - other.vec[0]) <
EPSILON &&
464 std::abs(vec[1] - other.vec[1]) <
EPSILON &&
465 std::abs(vec[2] - other.vec[2]) <
EPSILON;
469 return !(*
this == other);
473 os << vec.ToString();
486 std::ostringstream ss;
487 ss << std::fixed << std::setprecision(precision);
488 ss <<
"Vector3D(" << vec[0] <<
", " << vec[1] <<
", " << vec[2] <<
")";
493 return vec.ToRawArray();
534 Vector4D(
float x,
float y,
float z,
float w) : vec({x, y, z, w}) {}
537 float GetX()
const {
return vec[0]; }
538 float GetY()
const {
return vec[1]; }
539 float GetZ()
const {
return vec[2]; }
540 float GetW()
const {
return vec[3]; }
543 void SetX(
float val) { vec[0] = val; }
544 void SetY(
float val) { vec[1] = val; }
545 void SetZ(
float val) { vec[2] = val; }
546 void SetW(
float val) { vec[3] = val; }
547 void Set(
float x,
float y,
float z,
float w) {
548 vec[0] = x; vec[1] = y; vec[2] = z; vec[3] = w;
553 return Vector4D(vec[0] + other.vec[0], vec[1] + other.vec[1], vec[2] + other.vec[2], vec[3] + other.vec[3]);
557 return Vector4D(vec[0] - other.vec[0], vec[1] - other.vec[1], vec[2] - other.vec[2], vec[3] - other.vec[3]);
561 vec[0] += other.vec[0];
562 vec[1] += other.vec[1];
563 vec[2] += other.vec[2];
564 vec[3] += other.vec[3];
569 vec[0] -= other.vec[0];
570 vec[1] -= other.vec[1];
571 vec[2] -= other.vec[2];
572 vec[3] -= other.vec[3];
578 return Vector4D(vec[0] * scalar, vec[1] * scalar, vec[2] * scalar, vec[3] * scalar);
582 if (scalar == 0)
throw std::invalid_argument(
"Division by zero");
583 return Vector4D(vec[0] / scalar, vec[1] / scalar, vec[2] / scalar, vec[3] / scalar);
588 return vec[0] * other.vec[0] + vec[1] * other.vec[1] + vec[2] * other.vec[2] + vec[3] * other.vec[3];
593 return std::sqrt(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2] + vec[3] * vec[3]);
598 if (mag == 0)
throw std::runtime_error(
"Cannot normalize a zero vector");
613 return std::abs(vec[0] - other.vec[0]) <
EPSILON &&
614 std::abs(vec[1] - other.vec[1]) <
EPSILON &&
615 std::abs(vec[2] - other.vec[2]) <
EPSILON &&
616 std::abs(vec[3] - other.vec[3]) <
EPSILON;
620 return !(*
this == other);
624 os << vec.ToString();
633 std::ostringstream ss;
634 ss << std::fixed << std::setprecision(precision);
635 ss <<
"Vector4D(" << vec[0] <<
", " << vec[1] <<
", " << vec[2] <<
", " << vec[3] <<
")";
640 return vec.ToRawArray();
648 template <
typename T,
size_t N>
std::string ToString() const
bool operator!=(const Vector2D &other) const
Vector2D operator*(float scalar) const
void Set(float x, float y)
friend std::ostream & operator<<(std::ostream &os, const Vector2D &vec)
Vector2D Normalized() const
void Add(float x, float y)
float Cross(const Vector2D &other) const
Vector2D operator+(const Vector2D &other) const
bool operator==(const Vector2D &other) const
Vector2D operator/(float scalar) const
constexpr float GetY() const
std::string ToString(uint8_t precision) const
Vector2D & operator+=(const Vector2D &other)
constexpr Vector2D(float x, float y)
constexpr float GetX() const
Vector2D & operator-=(const Vector2D &other)
float Dot(const Vector2D &other) const
Vector2D operator-(const Vector2D &other) const
Vector3D & operator-=(const Vector3D &other)
bool operator!=(const Vector3D &other) const
void Add(float x, float y, float z)
void Set(float x, float y, float z)
float Dot(const Vector3D &other) const
Vector3D(float x, float y, float z)
Vector3D operator-(const Vector3D &other) const
Vector3D & operator+=(const Vector3D &other)
static Vector3D Backward()
Vector3D Normalized() const
std::string ToString(uint8_t precision) const
static Vector3D Identity()
static Vector3D Forward()
Vector3D operator+(const Vector3D &other) const
bool operator==(const Vector3D &other) const
Vector3D Cross(const Vector3D &other) const
Vector3D operator*(const Vector3D &other) const
Vector3D operator/(float scalar) const
friend std::ostream & operator<<(std::ostream &os, const Vector3D &vec)
Vector< float, 3 > BaseVector()
std::string ToString() const
Vector3D operator*(float scalar) const
Vector4D(float x, float y, float z, float w)
Vector4D & operator+=(const Vector4D &other)
bool operator==(const Vector4D &other) const
Vector4D operator+(const Vector4D &other) const
void Set(float x, float y, float z, float w)
Vector4D & operator-=(const Vector4D &other)
Vector4D operator/(float scalar) const
Vector4D operator*(float scalar) const
friend std::ostream & operator<<(std::ostream &os, const Vector4D &vec)
Vector4D Normalized() const
float Dot(const Vector4D &other) const
std::string ToString(uint8_t precision) const
std::string ToString() const
Vector4D operator-(const Vector4D &other) const
bool operator!=(const Vector4D &other) const
T Dot(const Vector< T, N > &other) const
Vector< T, N > operator+(const Vector< T, N > &other) const
bool operator==(const Vector< T, N > &other) const
Vector< T, N > operator/(T scalar) const
Vector< T, N > operator-(const Vector< T, N > &other) const
T * ToRawArray()
Raw pointer to the backing N-element array.
std::enable_if< M==3, Vector< T, N > >::type Cross(const Vector< T, N > &other) const
Vector< T, N > & operator-=(const Vector< T, N > &other)
Vector< T, N > & operator+=(const Vector< T, N > &other)
constexpr Vector(std::initializer_list< T > list)
Vector< T, N > operator*(T scalar) const
const T & operator[](size_t index) const
bool operator!=(const Vector< T, N > &other) const
T & operator[](size_t index)
constexpr Vector() noexcept
std::string ToString() const
friend std::ostream & operator<<(std::ostream &os, const Vector< T, N > &v)
Vector< T, N > Normalized() const
Vector3D operator*(const Quaternion &quat, const Vector3D &vec)
Root namespace for everything the engine exposes.