omath::Vector3 — 3D vector (C++20/23)
Header: your project’s
vector3.hppNamespace:omathTemplate:template<class Type> requires std::is_arithmetic_v<Type>Depends on:omath::Vector2<Type>(base class),omath::Angle(forangle_between) C++: usesstd::expected⇒ C++23 recommended (or a backport)
Vector3<Type> extends Vector2<Type> with a z component and 3D operations: arithmetic, geometry (dot, cross, distance), normalization, angle-between with robust error signaling, hashing (for float) and std::formatter support.
Quick start
#include "vector3.hpp"
using omath::Vector3;
using Vec3f = Vector3<float>;
Vec3f a{3, 4, 0};
Vec3f b{1, 2, 2};
auto d = a.distance_to(b); // Euclidean distance
auto dot = a.dot(b); // 3*1 + 4*2 + 0*2 = 11
auto cr = a.cross(b); // (8, -6, 2)
auto len = a.length(); // hypot(x,y,z)
auto unit = a.normalized(); // safe normalize (returns a if length==0)
if (auto ang = a.angle_between(b)) {
float deg = ang->as_degrees(); // [0, 180], clamped
} else {
// vectors have zero length -> no defined angle
}
Data members
Type x{0}; // inherited from Vector2<Type>
Type y{0}; // inherited from Vector2<Type>
Type z{0};
Constructors
constexpr Vector3() noexcept;
constexpr Vector3(const Type& x, const Type& y, const Type& z) noexcept;
Equality & ordering
constexpr bool operator==(const Vector3&) const noexcept; // component-wise
constexpr bool operator!=(const Vector3&) const noexcept;
bool operator< (const Vector3&) const noexcept; // compare by length()
bool operator> (const Vector3&) const noexcept;
bool operator<=(const Vector3&) const noexcept;
bool operator>=(const Vector3&) const noexcept;
Note: Ordering uses magnitude, not lexicographic order.
Arithmetic (mutating)
Component-wise with another vector:
Vector3& operator+=(const Vector3&) noexcept;
Vector3& operator-=(const Vector3&) noexcept;
Vector3& operator*=(const Vector3&) noexcept; // Hadamard product
Vector3& operator/=(const Vector3&) noexcept;
With a scalar:
Vector3& operator*=(const Type& v) noexcept;
Vector3& operator/=(const Type& v) noexcept;
Vector3& operator+=(const Type& v) noexcept;
Vector3& operator-=(const Type& v) noexcept;
Arithmetic (non-mutating)
constexpr Vector3 operator-() const noexcept;
constexpr Vector3 operator+(const Vector3&) const noexcept;
constexpr Vector3 operator-(const Vector3&) const noexcept;
constexpr Vector3 operator*(const Vector3&) const noexcept; // Hadamard
constexpr Vector3 operator/(const Vector3&) const noexcept; // Hadamard
constexpr Vector3 operator*(const Type& scalar) const noexcept;
constexpr Vector3 operator/(const Type& scalar) const noexcept;
Geometry & helpers
// Distances & lengths
Type distance_to(const Vector3&) const; // sqrt of squared distance
constexpr Type distance_to_sqr(const Vector3&) const noexcept;
#ifndef _MSC_VER
constexpr Type length() const; // hypot(x,y,z)
constexpr Type length_2d() const; // 2D length from base
constexpr Vector3 normalized() const; // returns *this if length==0
#else
Type length() const noexcept;
Type length_2d() const noexcept;
Vector3 normalized() const noexcept;
#endif
constexpr Type length_sqr() const noexcept;
// Products
constexpr Type dot(const Vector3&) const noexcept;
constexpr Vector3 cross(const Vector3&) const noexcept; // right-handed
// Sums & tuples
constexpr Type sum() const noexcept; // x + y + z
constexpr Type sum_2d() const noexcept; // x + y
constexpr auto as_tuple() const noexcept -> std::tuple<Type,Type,Type>;
// Utilities
Vector3& abs() noexcept; // component-wise absolute
Angles & orthogonality
enum class Vector3Error { IMPOSSIBLE_BETWEEN_ANGLE };
// Angle in degrees, clamped to [0,180]. Error if any vector has zero length.
std::expected<
omath::Angle<float, 0.f, 180.f, AngleFlags::Clamped>,
Vector3Error
> angle_between(const Vector3& other) const noexcept;
bool is_perpendicular(const Vector3& other) const noexcept; // true if angle == 90°
Hashing & formatting
- Hash (for
Vector3<float>)
cpp
template<> struct std::hash<omath::Vector3<float>> {
std::size_t operator()(const omath::Vector3<float>&) const noexcept;
};
Example:
cpp
std::unordered_map<omath::Vector3<float>, int> counts;
counts[{1.f, 2.f, 3.f}] = 7;
std::formatter(all character types)
cpp
template<class Type>
struct std::formatter<omath::Vector3<Type>>; // prints "[x, y, z]"
Error handling
angle_between()returnsstd::unexpected(Vector3Error::IMPOSSIBLE_BETWEEN_ANGLE)if either vector length is zero.- Other operations are total for arithmetic
Type(no throwing behavior in this class).
Examples
Cross product & perpendicular check
omath::Vector3<float> x{1,0,0}, y{0,1,0};
auto z = x.cross(y); // (0,0,1)
bool perp = x.is_perpendicular(y); // true
Safe normalization and angle
omath::Vector3<float> u{0,0,0}, v{1,1,0};
auto nu = u.normalized(); // returns {0,0,0}
if (auto ang = u.angle_between(v)) {
// won't happen: u has zero length → error
} else {
// handle degenerate case
}
Hadamard vs scalar multiply
omath::Vector3<float> a{2,3,4}, b{5,6,7};
auto h = a * b; // (10, 18, 28) component-wise
auto s = a * 2.f; // (4, 6, 8) scalar
API summary (signatures)
// Ctors
constexpr Vector3() noexcept;
constexpr Vector3(const Type& x, const Type& y, const Type& z) noexcept;
// Equality & ordering
constexpr bool operator==(const Vector3&) const noexcept;
constexpr bool operator!=(const Vector3&) const noexcept;
bool operator< (const Vector3&) const noexcept;
bool operator> (const Vector3&) const noexcept;
bool operator<=(const Vector3&) const noexcept;
bool operator>=(const Vector3&) const noexcept;
// Mutating arithmetic
Vector3& operator+=(const Vector3&) noexcept;
Vector3& operator-=(const Vector3&) noexcept;
Vector3& operator*=(const Vector3&) noexcept;
Vector3& operator/=(const Vector3&) noexcept;
Vector3& operator*=(const Type&) noexcept;
Vector3& operator/=(const Type&) noexcept;
Vector3& operator+=(const Type&) noexcept;
Vector3& operator-=(const Type&) noexcept;
// Non-mutating arithmetic
constexpr Vector3 operator-() const noexcept;
constexpr Vector3 operator+(const Vector3&) const noexcept;
constexpr Vector3 operator-(const Vector3&) const noexcept;
constexpr Vector3 operator*(const Vector3&) const noexcept;
constexpr Vector3 operator/(const Vector3&) const noexcept;
constexpr Vector3 operator*(const Type&) const noexcept;
constexpr Vector3 operator/(const Type&) const noexcept;
// Geometry
Type distance_to(const Vector3&) const;
constexpr Type distance_to_sqr(const Vector3&) const noexcept;
#ifndef _MSC_VER
constexpr Type length() const;
constexpr Type length_2d() const;
constexpr Vector3 normalized() const;
#else
Type length() const noexcept;
Type length_2d() const noexcept;
Vector3 normalized() const noexcept;
#endif
constexpr Type length_sqr() const noexcept;
constexpr Type dot(const Vector3&) const noexcept;
constexpr Vector3 cross(const Vector3&) const noexcept;
Vector3& abs() noexcept;
constexpr Type sum() const noexcept;
constexpr Type sum_2d() const noexcept;
constexpr auto as_tuple() const noexcept -> std::tuple<Type,Type,Type>;
// Angles
std::expected<omath::Angle<float,0.f,180.f,AngleFlags::Clamped>, omath::Vector3Error>
angle_between(const Vector3&) const noexcept;
bool is_perpendicular(const Vector3&) const noexcept;
// Hash (float) and formatter specializations provided below the class
Notes
- Inherits all public API of
Vector2<Type>(includingx,y, many operators, and helpers used internally). normalized()returns the original vector if its length is zero (no NaNs).cross()uses the standard right-handed definition.length()/normalized()areconstexpron non-MSVC; MSVC builds providenoexceptruntime versions.
See Also
- Vector2 Documentation - 2D vector operations
- Vector4 Documentation - 4D vector operations
- Angle Documentation - Working with angles
- Getting Started Guide - Quick start with OMath
- Tutorials - Practical examples including vector math
Last updated: 1 Nov 2025