32#include <glm/exponential.hpp>
33#include <glm/geometric.hpp>
34#include <glm/vector_relational.hpp>
36#include <glm/vec2.hpp>
37#include <glm/vec3.hpp>
38#include <glm/vec4.hpp>
47namespace utility::math
53 using glm::faceforward;
61 using glm::inversesqrt;
71 template<
typename Type>
73 std::is_floating_point_v<Type> || std::is_integral_v<Type>;
81 std::size_t VectorDimension>
82 class Vector:
public glm::vec<VectorDimension, VectorComponentType>
89 : glm::vec<VectorDimension, VectorComponentType>(0)
97 explicit Vector(
const glm::vec<VectorDimension, VectorComponentType> &v)
98 : glm::vec<VectorDimension, VectorComponentType>(v)
108 Vector(std::initializer_list<VectorComponentType> values)
110 if (values.size() != VectorDimension) {
111 throw std::invalid_argument(
"Vector requires exactly "
112 + std::to_string(VectorDimension)
115 const auto it = values.begin();
116 for (std::size_t i = 0; i < VectorDimension; ++i) {
117 (*this)[i] = *(it + i);
125 explicit Vector(VectorComponentType value)
126 : glm::vec<VectorDimension, VectorComponentType>(value)
169 static_cast<const glm::vec<VectorDimension, VectorComponentType>
172 const glm::vec<VectorDimension, VectorComponentType> &
>(
183 *
static_cast<glm::vec<VectorDimension, VectorComponentType> *
>(
186 const glm::vec<VectorDimension, VectorComponentType> &
>(
199 static_cast<const glm::vec<VectorDimension, VectorComponentType>
202 const glm::vec<VectorDimension, VectorComponentType> &
>(
213 *
static_cast<glm::vec<VectorDimension, VectorComponentType> *
>(
216 const glm::vec<VectorDimension, VectorComponentType> &
>(
229 static_cast<const glm::vec<VectorDimension, VectorComponentType>
241 *
static_cast<glm::vec<VectorDimension, VectorComponentType> *
>(
254 if (scalar == VectorComponentType { 0 }) {
255 throw std::invalid_argument(
"Vector division by zero");
258 static_cast<const glm::vec<VectorDimension, VectorComponentType>
271 if (scalar == VectorComponentType { 0 }) {
272 throw std::invalid_argument(
"Vector division by zero");
274 *
static_cast<glm::vec<VectorDimension, VectorComponentType> *
>(
287 static_cast<const glm::vec<VectorDimension, VectorComponentType>
290 const glm::vec<VectorDimension, VectorComponentType> &
>(
301 *
static_cast<glm::vec<VectorDimension, VectorComponentType> *
>(
304 const glm::vec<VectorDimension, VectorComponentType> &
>(
317 for (std::size_t i = 0; i < VectorDimension; ++i) {
318 if (rhs[i] == VectorComponentType { 0 }) {
319 throw std::invalid_argument(
"Vector division by zero");
323 static_cast<const glm::vec<VectorDimension, VectorComponentType>
326 const glm::vec<VectorDimension, VectorComponentType> &
>(
338 for (std::size_t i = 0; i < VectorDimension; ++i) {
339 if (rhs[i] == VectorComponentType { 0 }) {
340 throw std::invalid_argument(
"Vector division by zero");
343 *
static_cast<glm::vec<VectorDimension, VectorComponentType> *
>(
346 const glm::vec<VectorDimension, VectorComponentType> &
>(
362 const glm::vec<VectorDimension, VectorComponentType> &
>(
365 const glm::vec<VectorDimension, VectorComponentType> &
>(
379 VectorComponentType epsilon = VectorComponentType {
382 for (std::size_t i = 0; i < VectorDimension; ++i) {
383 if (std::abs((*
this)[i] - rhs[i]) > epsilon) {
397 return !(*
this == rhs);
408 const glm::vec<VectorDimension, VectorComponentType> &
>(
425 template<CanBeVectorComponent VectorComponentType,
426 std::size_t VectorDimension>
428 dot(
const Vector<VectorComponentType, VectorDimension> &lhs,
429 const Vector<VectorComponentType, VectorDimension> &rhs)
432 static_cast<const glm::vec<VectorDimension, VectorComponentType> &
>(
434 static_cast<const glm::vec<VectorDimension, VectorComponentType> &
>(
438 template<CanBeVectorComponent VectorComponentType>
439 Vector<VectorComponentType, 3>
440 cross(
const Vector<VectorComponentType, 3> &lhs,
441 const Vector<VectorComponentType, 3> &rhs)
443 return Vector<VectorComponentType, 3>(glm::cross(
444 static_cast<const glm::vec<3, VectorComponentType> &
>(lhs),
445 static_cast<const glm::vec<3, VectorComponentType> &
>(rhs)));
448 template<CanBeVectorComponent VectorComponentType,
449 std::size_t VectorDimension>
450 Vector<VectorComponentType, VectorDimension>
451 normalize(
const Vector<VectorComponentType, VectorDimension> &vector)
453 return Vector<VectorComponentType, VectorDimension>(glm::normalize(
454 static_cast<const glm::vec<VectorDimension, VectorComponentType> &
>(
461 using Vector2F = Vector<float, 2>;
466 using Vector2D = Vector<double, 2>;
471 using Vector2I = Vector<int, 2>;
476 using Vector2UI = Vector<unsigned int, 2>;
481 using Vector3F = Vector<float, 3>;
486 using Vector3D = Vector<double, 3>;
491 using Vector3I = Vector<int, 3>;
496 using Vector3UI = Vector<unsigned int, 3>;
501 using Vector4F = Vector<float, 4>;
506 using Vector4D = Vector<double, 4>;
511 using Vector4I = Vector<int, 4>;
516 using Vector4UI = Vector<unsigned int, 4>;
524 std::ostream &operator<<(std::ostream &stream,
const Vector2F &vector);
532 std::ostream &operator<<(std::ostream &stream,
const Vector2D &vector);
540 std::ostream &operator<<(std::ostream &stream,
const Vector2I &vector);
548 std::ostream &operator<<(std::ostream &stream,
const Vector2UI &vector);
556 std::ostream &operator<<(std::ostream &stream,
const Vector3F &vector);
564 std::ostream &operator<<(std::ostream &stream,
const Vector3D &vector);
572 std::ostream &operator<<(std::ostream &stream,
const Vector3I &vector);
580 std::ostream &operator<<(std::ostream &stream,
const Vector3UI &vector);
588 std::ostream &operator<<(std::ostream &stream,
const Vector4F &vector);
596 std::ostream &operator<<(std::ostream &stream,
const Vector4D &vector);
604 std::ostream &operator<<(std::ostream &stream,
const Vector4I &vector);
612 std::ostream &operator<<(std::ostream &stream,
const Vector4UI &vector);
3D vector class inheriting from glm::vec3.
Vector(std::initializer_list< VectorComponentType > values)
Construct from initializer list of float values.
Vector & operator*=(VectorComponentType scalar) noexcept
Scalar multiplication assignment.
bool operator==(const Vector &rhs) const noexcept
Equality comparison.
Vector(VectorComponentType value)
Construct by filling all components with the same float value.
~Vector(void)=default
Default destructor for Vector.
Vector(Vector &&other) noexcept=default
Move constructor.
Vector operator-(const Vector &rhs) const noexcept
Vector subtraction.
Vector & operator=(Vector &&other) noexcept=default
Move assignment operator.
Vector operator/(VectorComponentType scalar) const
Scalar division.
Vector(const glm::vec< VectorDimension, VectorComponentType > &v)
Construct from a GLM vector.
Vector & operator+=(const Vector &rhs) noexcept
Vector addition assignment.
Vector operator*(VectorComponentType scalar) const noexcept
Scalar multiplication.
bool operator!=(const Vector &rhs) const noexcept
Inequality comparison.
Vector(void)
Default constructor initializing vector values to zero.
Vector operator*(const Vector &rhs) const noexcept
Element-wise multiplication.
bool equalsEpsilon(const Vector &rhs, VectorComponentType epsilon=VectorComponentType { 1e-5 }) const
Approximate equality using an epsilon threshold.
Vector operator-() const noexcept
Unary negation.
Vector & operator*=(const Vector &rhs) noexcept
Element-wise multiplication assignment.
Vector & operator=(const Vector &other)=default
Copy assignment operator.
Vector operator/(const Vector &rhs) const
Element-wise division.
Vector & operator-=(const Vector &rhs) noexcept
Vector subtraction assignment.
Vector(const Vector &other)=default
Copy constructor.
Vector & operator/=(VectorComponentType scalar)
Scalar division assignment.
friend Vector operator*(VectorComponentType scalar, const Vector &vec)
Friend function for scalar multiplication with scalar on the left.
Vector & operator/=(const Vector &rhs)
Element-wise division assignment.
Vector operator+(const Vector &rhs) const noexcept
Vector addition.
Concept to constrain vector component type.