13#define VECTOR_Up Vector3D(0, 1, 0)
14#define VECTOR_Down Vector3D(0, -1, 0)
15#define VECTOR_Right Vector3D(1, 0, 0)
16#define VECTOR_Left Vector3D(-1, 0, 0)
17#define VECTOR_Forward Vector3D(0, 0, 1)
18#define VECTOR_Backward Vector3D(0, 0, -1)
29 template <
typename T,
size_t N>
33 constexpr Vector() noexcept { data.fill(
static_cast<T
>(0)); }
35 constexpr Vector(std::initializer_list<T> list) {
36 if (list.size() != N) {
37 throw std::invalid_argument(
38 "Initializer list size does not match vector "
41 std::copy_n(list.begin(), N, data.begin());
46 assert(index < N &&
"Vector index out of range");
52 assert(index < N &&
"Vector index out of range");
59 std::transform(data.begin(), data.end(), other.data.begin(),
60 result.data.begin(), std::plus<T>());
66 std::transform(data.begin(), data.end(), other.data.begin(),
67 result.data.begin(), std::minus<T>());
72 std::transform(data.begin(), data.end(), other.data.begin(),
73 data.begin(), std::plus<T>());
78 std::transform(data.begin(), data.end(), other.data.begin(),
79 data.begin(), std::minus<T>());
86 data.begin(), data.end(), result.data.begin(),
87 [scalar](
const T& val) { return val * scalar; });
93 throw std::invalid_argument(
"Division by zero");
96 for (
size_t i = 0; i < N; ++i) {
97 result[i] = data[i] / scalar;
105 for (
size_t i = 0; i < N; ++i) {
106 result += data[i] * other[i];
112 template <
size_t M = N>
113 typename std::enable_if<M == 3, Vector<T, N>>::type
115 static_assert(N == 3,
"Cross product is only defined for 3D vectors");
117 data[1] * other[2] - data[2] * other[1],
118 data[2] * other[0] - data[0] * other[2],
119 data[0] * other[1] - data[1] * other[0]
126 for (
size_t i = 0; i < N; ++i) {
127 sum += data[i] * data[i];
129 return std::sqrt(sum);
136 data[0] = 0.0f; data[1] = 0.0f; data[2] = 0.0f;
152 for (
size_t i = 0; i < N; ++i) {
153 if (std::abs(data[i] - other[i]) >=
EPSILON) {
162 return !(*
this == other);
167 std::ostringstream ss;
168 ss <<
"Vector<" << N <<
">(";
169 for (
size_t i = 0; i < N; ++i) {
171 if (i < N - 1) ss <<
", ";
189 std::array<T, N> data;
216 float GetX()
const {
return vec[0]; }
217 float GetY()
const {
return vec[1]; }
220 void SetX(
float val) { vec[0] = val; }
221 void SetY(
float val) { vec[1] = val; }
222 void Set(
float x,
float y) { vec[0] = x; vec[1] = y; }
224 void AddX(
float val) { vec[0] += val; }
225 void AddY(
float val) { vec[1] += val; }
226 void Add(
float x,
float y) { vec[0] += x; vec[1] += y; }
230 return Vector2D(vec[0] + other.vec[0], vec[1] + other.vec[1]);
234 return Vector2D(vec[0] - other.vec[0], vec[1] - other.vec[1]);
238 vec[0] += other.vec[0];
239 vec[1] += other.vec[1];
244 vec[0] -= other.vec[0];
245 vec[1] -= other.vec[1];
251 return Vector2D(vec[0] * scalar, vec[1] * scalar);
255 if (scalar == 0)
throw std::invalid_argument(
"Division by zero");
256 return Vector2D(vec[0] / scalar, vec[1] / scalar);
261 return vec[0] * other.vec[0] + vec[1] * other.vec[1];
265 return vec[0] * other.vec[1] - vec[1] * other.vec[0];
270 return std::hypot(vec[0], vec[1]);
275 if (mag == 0)
throw std::runtime_error(
"Cannot normalize a zero vector");
288 return std::abs(vec[0] - other.vec[0]) <
EPSILON &&
289 std::abs(vec[1] - other.vec[1]) <
EPSILON;
293 return !(*
this == other);
297 os << vec.ToString();
306 std::ostringstream ss;
307 ss << std::fixed << std::setprecision(precision);
308 ss <<
"Vector2D(" << vec[0] <<
", " << vec[1] <<
")";
313 return vec.ToRawArray();
357 Vector3D(
float x,
float y,
float z) : vec({x, y, z}) {}
360 float GetX()
const {
return vec[0]; }
361 float GetY()
const {
return vec[1]; }
362 float GetZ()
const {
return vec[2]; }
365 void SetX(
float val) { vec[0] = val; }
366 void SetY(
float val) { vec[1] = val; }
367 void SetZ(
float val) { vec[2] = val; }
368 void Set(
float x,
float y,
float z) {
369 vec[0] = x; vec[1] = y; vec[2] = z;
372 void AddX(
float val) { vec[0] += val; }
373 void AddY(
float val) { vec[1] += val; }
374 void AddZ(
float val) { vec[2] += val; }
375 void Add(
float x,
float y,
float z) {
376 vec[0] += x; vec[1] += y; vec[2] += z;
381 return Vector3D(vec[0] + other.vec[0], vec[1] + other.vec[1], vec[2] + other.vec[2]);
385 return Vector3D(vec[0] - other.vec[0], vec[1] - other.vec[1], vec[2] - other.vec[2]);
389 vec[0] += other.vec[0];
390 vec[1] += other.vec[1];
391 vec[2] += other.vec[2];
396 vec[0] -= other.vec[0];
397 vec[1] -= other.vec[1];
398 vec[2] -= other.vec[2];
404 return Vector3D(vec[0] * scalar, vec[1] * scalar, vec[2] * scalar);
412 if (scalar == 0)
throw std::invalid_argument(
"Division by zero");
413 return Vector3D(vec[0] / scalar, vec[1] / scalar, vec[2] / scalar);
418 return vec[0] * other.vec[0] + vec[1] * other.vec[1] + vec[2] * other.vec[2];
423 vec[1] * other.vec[2] - vec[2] * other.vec[1],
424 vec[2] * other.vec[0] - vec[0] * other.vec[2],
425 vec[0] * other.vec[1] - vec[1] * other.vec[0]
431 return std::sqrt(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]);
462 return std::abs(vec[0] - other.vec[0]) <
EPSILON &&
463 std::abs(vec[1] - other.vec[1]) <
EPSILON &&
464 std::abs(vec[2] - other.vec[2]) <
EPSILON;
468 return !(*
this == other);
472 os << vec.ToString();
485 std::ostringstream ss;
486 ss << std::fixed << std::setprecision(precision);
487 ss <<
"Vector3D(" << vec[0] <<
", " << vec[1] <<
", " << vec[2] <<
")";
492 return vec.ToRawArray();
533 Vector4D(
float x,
float y,
float z,
float w) : vec({x, y, z, w}) {}
536 float GetX()
const {
return vec[0]; }
537 float GetY()
const {
return vec[1]; }
538 float GetZ()
const {
return vec[2]; }
539 float GetW()
const {
return vec[3]; }
542 void SetX(
float val) { vec[0] = val; }
543 void SetY(
float val) { vec[1] = val; }
544 void SetZ(
float val) { vec[2] = val; }
545 void SetW(
float val) { vec[3] = val; }
546 void Set(
float x,
float y,
float z,
float w) {
547 vec[0] = x; vec[1] = y; vec[2] = z; vec[3] = w;
552 return Vector4D(vec[0] + other.vec[0], vec[1] + other.vec[1], vec[2] + other.vec[2], vec[3] + other.vec[3]);
556 return Vector4D(vec[0] - other.vec[0], vec[1] - other.vec[1], vec[2] - other.vec[2], vec[3] - other.vec[3]);
560 vec[0] += other.vec[0];
561 vec[1] += other.vec[1];
562 vec[2] += other.vec[2];
563 vec[3] += other.vec[3];
568 vec[0] -= other.vec[0];
569 vec[1] -= other.vec[1];
570 vec[2] -= other.vec[2];
571 vec[3] -= other.vec[3];
577 return Vector4D(vec[0] * scalar, vec[1] * scalar, vec[2] * scalar, vec[3] * scalar);
581 if (scalar == 0)
throw std::invalid_argument(
"Division by zero");
582 return Vector4D(vec[0] / scalar, vec[1] / scalar, vec[2] / scalar, vec[3] / scalar);
587 return vec[0] * other.vec[0] + vec[1] * other.vec[1] + vec[2] * other.vec[2] + vec[3] * other.vec[3];
592 return std::sqrt(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2] + vec[3] * vec[3]);
597 if (mag == 0)
throw std::runtime_error(
"Cannot normalize a zero vector");
612 return std::abs(vec[0] - other.vec[0]) <
EPSILON &&
613 std::abs(vec[1] - other.vec[1]) <
EPSILON &&
614 std::abs(vec[2] - other.vec[2]) <
EPSILON &&
615 std::abs(vec[3] - other.vec[3]) <
EPSILON;
619 return !(*
this == other);
623 os << vec.ToString();
632 std::ostringstream ss;
633 ss << std::fixed << std::setprecision(precision);
634 ss <<
"Vector4D(" << vec[0] <<
", " << vec[1] <<
", " << vec[2] <<
", " << vec[3] <<
")";
639 return vec.ToRawArray();
647 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
std::string ToString(uint8_t precision) const
Vector2D & operator+=(const Vector2D &other)
Vector2D(float x, float y)
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.