mirror of
https://github.com/orange-cpp/omath.git
synced 2026-02-13 07:03:25 +00:00
Adds documentation for Vector4 and incorporates ImGui integration
Adds comprehensive documentation for the `Vector4` class, outlining constructors, operators, and utility functions. Includes detailed notes on `clamp` functionality and potential ImGui integration caveats. Incorporates optional ImGui integration with explanations for correct usage and potential improvements.
This commit is contained in:
173
docs/linear_algebra/triangle.md
Normal file
173
docs/linear_algebra/triangle.md
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
# `omath::Triangle` — Simple 3D triangle utility
|
||||||
|
|
||||||
|
> Header: your project’s `triangle.hpp`
|
||||||
|
> Namespace: `omath`
|
||||||
|
> Depends on: `omath::Vector3<float>` (from `vector3.hpp`)
|
||||||
|
|
||||||
|
A tiny helper around three `Vector3<float>` vertices with convenience methods for normals, edge vectors/lengths, a right-angle test (at **`v2`**), and the triangle centroid.
|
||||||
|
|
||||||
|
> **Note on the template parameter**
|
||||||
|
>
|
||||||
|
> The class is declared as `template<class Vector> class Triangle`, but the stored vertices are concretely `Vector3<float>`. In practice this type is currently **fixed to `Vector3<float>`**. You can ignore the template parameter or refactor to store `Vector` if you intend true genericity.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Vertex layout & naming
|
||||||
|
|
||||||
|
```
|
||||||
|
v1
|
||||||
|
|\
|
||||||
|
| \
|
||||||
|
a | \ hypot = |v1 - v3|
|
||||||
|
| \
|
||||||
|
v2 -- v3
|
||||||
|
b
|
||||||
|
|
||||||
|
a = |v1 - v2| (side_a_length)
|
||||||
|
b = |v3 - v2| (side_b_length)
|
||||||
|
```
|
||||||
|
|
||||||
|
* **`side_a_vector()`** = `v1 - v2` (points from v2 → v1)
|
||||||
|
* **`side_b_vector()`** = `v3 - v2` (points from v2 → v3)
|
||||||
|
* **Right-angle check** uses `a² + b² ≈ hypot²` with an epsilon of `1e-4`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "triangle.hpp"
|
||||||
|
using omath::Vector3;
|
||||||
|
using omath::Triangle;
|
||||||
|
|
||||||
|
Triangle<void> tri( // template arg unused; any placeholder ok
|
||||||
|
Vector3<float>{0,0,0}, // v1
|
||||||
|
Vector3<float>{0,0,1}, // v2 (right angle is tested at v2)
|
||||||
|
Vector3<float>{1,0,1} // v3
|
||||||
|
);
|
||||||
|
|
||||||
|
auto n = tri.calculate_normal(); // unit normal (right-handed: (v3-v2) × (v1-v2))
|
||||||
|
float a = tri.side_a_length(); // |v1 - v2|
|
||||||
|
float b = tri.side_b_length(); // |v3 - v2|
|
||||||
|
float hyp = tri.hypot(); // |v1 - v3|
|
||||||
|
bool rect = tri.is_rectangular(); // true if ~right triangle at v2
|
||||||
|
auto C = tri.mid_point(); // centroid (average of v1,v2,v3)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Data members
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Vector3<float> m_vertex1; // v1
|
||||||
|
Vector3<float> m_vertex2; // v2 (the corner tested by is_rectangular)
|
||||||
|
Vector3<float> m_vertex3; // v3
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Constructors
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr Triangle() = default;
|
||||||
|
constexpr Triangle(const Vector3<float>& v1,
|
||||||
|
const Vector3<float>& v2,
|
||||||
|
const Vector3<float>& v3);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Normal (unit) using right-handed cross product:
|
||||||
|
// n = (v3 - v2) × (v1 - v2), then normalized()
|
||||||
|
[[nodiscard]] constexpr Vector3<float> calculate_normal() const;
|
||||||
|
|
||||||
|
// Edge lengths with the naming from the diagram
|
||||||
|
[[nodiscard]] float side_a_length() const; // |v1 - v2|
|
||||||
|
[[nodiscard]] float side_b_length() const; // |v3 - v2|
|
||||||
|
|
||||||
|
// Edge vectors (from v2 to the other vertex)
|
||||||
|
[[nodiscard]] constexpr Vector3<float> side_a_vector() const; // v1 - v2
|
||||||
|
[[nodiscard]] constexpr Vector3<float> side_b_vector() const; // v3 - v2
|
||||||
|
|
||||||
|
// Hypotenuse length between v1 and v3
|
||||||
|
[[nodiscard]] constexpr float hypot() const; // |v1 - v3|
|
||||||
|
|
||||||
|
// Right-triangle check at vertex v2 (Pythagoras with epsilon 1e-4)
|
||||||
|
[[nodiscard]] constexpr bool is_rectangular() const;
|
||||||
|
|
||||||
|
// Centroid of the triangle (average of the 3 vertices)
|
||||||
|
[[nodiscard]] constexpr Vector3<float> mid_point() const; // actually the centroid
|
||||||
|
```
|
||||||
|
|
||||||
|
### Notes & edge cases
|
||||||
|
|
||||||
|
* **Normal direction** follows the right-hand rule for the ordered vertices `{v2 → v3} × {v2 → v1}`.
|
||||||
|
Swap vertex order to flip the normal.
|
||||||
|
* **Degenerate triangles** (collinear or overlapping vertices) yield a **zero vector** normal (since `normalized()` of the zero vector returns the zero vector in your math types).
|
||||||
|
* **`mid_point()` is the centroid**, not the midpoint of any single edge. If you need the midpoint of edge `v1–v2`, use `(m_vertex1 + m_vertex2) * 0.5f`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Area and plane from existing API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
const auto a = tri.side_a_vector();
|
||||||
|
const auto b = tri.side_b_vector();
|
||||||
|
const auto n = b.cross(a); // unnormalized normal
|
||||||
|
float area = 0.5f * n.length(); // triangle area
|
||||||
|
|
||||||
|
// Plane equation n̂·(x - v2) = 0
|
||||||
|
auto nhat = n.length() > 0 ? n / n.length() : n;
|
||||||
|
float d = -nhat.dot(tri.m_vertex2);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Project a point onto the triangle’s plane
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Vector3<float> p{0.3f, 1.0f, 0.7f};
|
||||||
|
auto n = tri.calculate_normal();
|
||||||
|
float t = n.dot(tri.m_vertex2 - p); // signed distance along normal
|
||||||
|
auto projected = p + n * t; // on-plane projection
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API summary (signatures)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Triangle final {
|
||||||
|
public:
|
||||||
|
constexpr Triangle();
|
||||||
|
constexpr Triangle(const Vector3<float>& v1,
|
||||||
|
const Vector3<float>& v2,
|
||||||
|
const Vector3<float>& v3);
|
||||||
|
|
||||||
|
Vector3<float> m_vertex1, m_vertex2, m_vertex3;
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr Vector3<float> calculate_normal() const;
|
||||||
|
[[nodiscard]] float side_a_length() const;
|
||||||
|
[[nodiscard]] float side_b_length() const;
|
||||||
|
[[nodiscard]] constexpr Vector3<float> side_a_vector() const;
|
||||||
|
[[nodiscard]] constexpr Vector3<float> side_b_vector() const;
|
||||||
|
[[nodiscard]] constexpr float hypot() const;
|
||||||
|
[[nodiscard]] constexpr bool is_rectangular() const;
|
||||||
|
[[nodiscard]] constexpr Vector3<float> mid_point() const;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Suggestions (optional improvements)
|
||||||
|
|
||||||
|
* If generic vectors are intended, store `Vector m_vertex*;` and constrain `Vector` to the required ops (`-`, `cross`, `normalized`, `distance_to`, `+`, `/`).
|
||||||
|
* Consider renaming `mid_point()` → `centroid()` to avoid ambiguity.
|
||||||
|
* Expose an `area()` helper and (optionally) a barycentric coordinate routine if you plan to use this in rasterization or intersection tests.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 31 Oct 2025*
|
||||||
291
docs/linear_algebra/vector2.md
Normal file
291
docs/linear_algebra/vector2.md
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
# `omath::Vector2` — 2D vector (C++20/23)
|
||||||
|
|
||||||
|
> Header: your project’s `vector2.hpp`
|
||||||
|
> Namespace: `omath`
|
||||||
|
> Template: `template<class Type> requires std::is_arithmetic_v<Type>`
|
||||||
|
|
||||||
|
`Vector2<Type>` is a lightweight, POD-like 2D math type with arithmetic, geometry helpers, comparisons, hashing (for `float`), optional ImGui interop, and `std::formatter` support.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "vector2.hpp"
|
||||||
|
using omath::Vector2;
|
||||||
|
|
||||||
|
using Vec2f = Vector2<float>;
|
||||||
|
|
||||||
|
Vec2f a{3.f, 4.f};
|
||||||
|
Vec2f b{1.f, 2.f};
|
||||||
|
|
||||||
|
auto d = a.distance_to(b); // ≈ 3.1623
|
||||||
|
auto dot = a.dot(b); // 11
|
||||||
|
auto len = a.length(); // 5
|
||||||
|
auto unit_a = a.normalized(); // (0.6, 0.8)
|
||||||
|
|
||||||
|
// Component-wise mutate
|
||||||
|
Vec2f c{2, 3};
|
||||||
|
c *= b; // c -> (2*1, 3*2) = (2, 6)
|
||||||
|
|
||||||
|
// Scalar ops (non-mutating + mutating)
|
||||||
|
auto scaled = a * 0.5f; // (1.5, 2)
|
||||||
|
a *= 2.f; // (6, 8)
|
||||||
|
|
||||||
|
// Ordering by length()
|
||||||
|
bool shorter = (b < a);
|
||||||
|
|
||||||
|
// Formatted printing
|
||||||
|
std::string s = std::format("a = {}", a); // "a = [6, 8]"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Members
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Type x{0};
|
||||||
|
Type y{0};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Constructors
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr Vector2(); // (0,0)
|
||||||
|
constexpr Vector2(const Type& x, const Type& y) noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Equality & ordering
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr bool operator==(const Vector2&) const noexcept; // component-wise equality
|
||||||
|
constexpr bool operator!=(const Vector2&) const noexcept;
|
||||||
|
|
||||||
|
bool operator< (const Vector2&) const noexcept; // compares by length()
|
||||||
|
bool operator> (const Vector2&) const noexcept;
|
||||||
|
bool operator<=(const Vector2&) const noexcept;
|
||||||
|
bool operator>=(const Vector2&) const noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note:** `<`, `>`, `<=`, `>=` order vectors by **magnitude** (not lexicographically).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Arithmetic
|
||||||
|
|
||||||
|
### With another vector (component-wise, **mutating**)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Vector2& operator+=(const Vector2&) noexcept;
|
||||||
|
Vector2& operator-=(const Vector2&) noexcept;
|
||||||
|
Vector2& operator*=(const Vector2&) noexcept; // Hadamard product (x*=x, y*=y)
|
||||||
|
Vector2& operator/=(const Vector2&) noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
> Non-mutating `v * u` / `v / u` (vector × vector) are **not** provided.
|
||||||
|
> Use `v *= u` (mutating) or build a new vector explicitly.
|
||||||
|
|
||||||
|
### With a scalar
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Vector2& operator*=(const Type& v) noexcept;
|
||||||
|
Vector2& operator/=(const Type& v) noexcept;
|
||||||
|
Vector2& operator+=(const Type& v) noexcept;
|
||||||
|
Vector2& operator-=(const Type& v) noexcept;
|
||||||
|
|
||||||
|
constexpr Vector2 operator*(const Type& v) const noexcept;
|
||||||
|
constexpr Vector2 operator/(const Type& v) const noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Binary (+/−) with another vector (non-mutating)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr Vector2 operator+(const Vector2&) const noexcept;
|
||||||
|
constexpr Vector2 operator-(const Vector2&) const noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Unary
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr Vector2 operator-() const noexcept; // negation
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Geometry & helpers
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Type distance_to (const Vector2&) const noexcept; // sqrt of squared distance
|
||||||
|
constexpr Type distance_to_sqr(const Vector2&) const noexcept;
|
||||||
|
|
||||||
|
constexpr Type dot(const Vector2&) const noexcept;
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
constexpr Type length() const noexcept; // uses std::hypot; constexpr on non-MSVC
|
||||||
|
constexpr Vector2 normalized() const noexcept; // returns *this if length==0
|
||||||
|
#else
|
||||||
|
Type length() const noexcept;
|
||||||
|
Vector2 normalized() const noexcept;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
constexpr Type length_sqr() const noexcept; // x*x + y*y
|
||||||
|
Vector2& abs() noexcept; // component-wise absolute (constexpr-friendly impl)
|
||||||
|
|
||||||
|
constexpr Type sum() const noexcept; // x + y
|
||||||
|
constexpr std::tuple<Type, Type> as_tuple() const noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ImGui integration (optional)
|
||||||
|
|
||||||
|
Define `OMATH_IMGUI_INTEGRATION` **before** including the header.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#ifdef OMATH_IMGUI_INTEGRATION
|
||||||
|
constexpr ImVec2 to_im_vec2() const noexcept; // {float(x), float(y)}
|
||||||
|
static Vector2 from_im_vec2(const ImVec2&) noexcept;
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Hashing & formatting
|
||||||
|
|
||||||
|
* **Hash (for `Vector2<float>`)**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<> struct std::hash<omath::Vector2<float>> {
|
||||||
|
std::size_t operator()(const omath::Vector2<float>&) const noexcept;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
std::unordered_set<omath::Vector2<float>> set;
|
||||||
|
set.insert({1.f, 2.f});
|
||||||
|
```
|
||||||
|
|
||||||
|
* **`std::formatter`** (for any `Type`)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// prints "[x, y]" for char / wchar_t / char8_t
|
||||||
|
template<class Type>
|
||||||
|
struct std::formatter<omath::Vector2<Type>>;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes & invariants
|
||||||
|
|
||||||
|
* `Type` must be arithmetic (e.g., `float`, `double`, `int`, …).
|
||||||
|
* `normalized()` returns the input unchanged if `length() == 0`.
|
||||||
|
* `abs()` uses a constexpr-friendly implementation (not `std::abs`) to allow compile-time evaluation.
|
||||||
|
* On MSVC, `length()`/`normalized()` are not `constexpr` due to library constraints; they’re still `noexcept`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Component-wise operations and scalar scaling
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
omath::Vector2<float> u{2, 3}, v{4, 5};
|
||||||
|
|
||||||
|
u += v; // (6, 8)
|
||||||
|
u -= v; // (2, 3)
|
||||||
|
u *= v; // (8, 15) Hadamard product (mutates u)
|
||||||
|
auto w = v * 2.0f; // (8, 10) non-mutating scalar multiply
|
||||||
|
```
|
||||||
|
|
||||||
|
### Geometry helpers
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
omath::Vector2<double> p{0.0, 0.0}, q{3.0, 4.0};
|
||||||
|
|
||||||
|
auto dsq = p.distance_to_sqr(q); // 25
|
||||||
|
auto d = p.distance_to(q); // 5
|
||||||
|
auto dot = p.dot(q); // 0
|
||||||
|
auto uq = q.normalized(); // (0.6, 0.8)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using as a key in unordered containers (`float`)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
std::unordered_map<omath::Vector2<float>, int> counts;
|
||||||
|
counts[{1.f, 2.f}] = 42;
|
||||||
|
```
|
||||||
|
|
||||||
|
### ImGui interop
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#define OMATH_IMGUI_INTEGRATION
|
||||||
|
#include "vector2.hpp"
|
||||||
|
|
||||||
|
omath::Vector2<float> v{10, 20};
|
||||||
|
ImVec2 iv = v.to_im_vec2();
|
||||||
|
v = omath::Vector2<float>::from_im_vec2(iv);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API summary (signatures)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Constructors
|
||||||
|
constexpr Vector2();
|
||||||
|
constexpr Vector2(const Type& x, const Type& y) noexcept;
|
||||||
|
|
||||||
|
// Equality & ordering
|
||||||
|
constexpr bool operator==(const Vector2&) const noexcept;
|
||||||
|
constexpr bool operator!=(const Vector2&) const noexcept;
|
||||||
|
bool operator< (const Vector2&) const noexcept;
|
||||||
|
bool operator> (const Vector2&) const noexcept;
|
||||||
|
bool operator<=(const Vector2&) const noexcept;
|
||||||
|
bool operator>=(const Vector2&) const noexcept;
|
||||||
|
|
||||||
|
// Compound (vector/vector and scalar)
|
||||||
|
Vector2& operator+=(const Vector2&) noexcept;
|
||||||
|
Vector2& operator-=(const Vector2&) noexcept;
|
||||||
|
Vector2& operator*=(const Vector2&) noexcept;
|
||||||
|
Vector2& operator/=(const Vector2&) noexcept;
|
||||||
|
Vector2& operator*=(const Type&) noexcept;
|
||||||
|
Vector2& operator/=(const Type&) noexcept;
|
||||||
|
Vector2& operator+=(const Type&) noexcept;
|
||||||
|
Vector2& operator-=(const Type&) noexcept;
|
||||||
|
|
||||||
|
// Non-mutating arithmetic
|
||||||
|
constexpr Vector2 operator+(const Vector2&) const noexcept;
|
||||||
|
constexpr Vector2 operator-(const Vector2&) const noexcept;
|
||||||
|
constexpr Vector2 operator*(const Type&) const noexcept;
|
||||||
|
constexpr Vector2 operator/(const Type&) const noexcept;
|
||||||
|
constexpr Vector2 operator-() const noexcept;
|
||||||
|
|
||||||
|
// Geometry
|
||||||
|
Type distance_to(const Vector2&) const noexcept;
|
||||||
|
constexpr Type distance_to_sqr(const Vector2&) const noexcept;
|
||||||
|
constexpr Type dot(const Vector2&) const noexcept;
|
||||||
|
Type length() const noexcept; // constexpr on non-MSVC
|
||||||
|
Vector2 normalized() const noexcept; // constexpr on non-MSVC
|
||||||
|
constexpr Type length_sqr() const noexcept;
|
||||||
|
Vector2& abs() noexcept;
|
||||||
|
constexpr Type sum() const noexcept;
|
||||||
|
constexpr std::tuple<Type,Type> as_tuple() const noexcept;
|
||||||
|
|
||||||
|
// ImGui (optional)
|
||||||
|
#ifdef OMATH_IMGUI_INTEGRATION
|
||||||
|
constexpr ImVec2 to_im_vec2() const noexcept;
|
||||||
|
static Vector2 from_im_vec2(const ImVec2&) noexcept;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Hash (float) and formatter are specialized in the header
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 31 Oct 2025*
|
||||||
297
docs/linear_algebra/vector3.md
Normal file
297
docs/linear_algebra/vector3.md
Normal file
@@ -0,0 +1,297 @@
|
|||||||
|
# `omath::Vector3` — 3D vector (C++20/23)
|
||||||
|
|
||||||
|
> Header: your project’s `vector3.hpp`
|
||||||
|
> Namespace: `omath`
|
||||||
|
> Template: `template<class Type> requires std::is_arithmetic_v<Type>`
|
||||||
|
> Depends on: `omath::Vector2<Type>` (base class), `omath::Angle` (for `angle_between`)
|
||||||
|
> C++: uses `std::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
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#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
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Type x{0}; // inherited from Vector2<Type>
|
||||||
|
Type y{0}; // inherited from Vector2<Type>
|
||||||
|
Type z{0};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Constructors
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr Vector3() noexcept;
|
||||||
|
constexpr Vector3(const Type& x, const Type& y, const Type& z) noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Equality & ordering
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
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:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
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:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
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)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
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
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// 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
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
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()` returns `std::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
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
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
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
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
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
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)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// 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>` (including `x`, `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()` are `constexpr` on non-MSVC; MSVC builds provide `noexcept` runtime versions.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 31 Oct 2025*
|
||||||
253
docs/linear_algebra/vector4.md
Normal file
253
docs/linear_algebra/vector4.md
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
# `omath::Vector4` — 4D vector (C++20/23)
|
||||||
|
|
||||||
|
> Header: your project’s `vector4.hpp`
|
||||||
|
> Namespace: `omath`
|
||||||
|
> Template: `template<class Type> requires std::is_arithmetic_v<Type>`
|
||||||
|
> Inherits: `omath::Vector3<Type>` (brings `x`, `y`, `z` and most scalar ops)
|
||||||
|
|
||||||
|
`Vector4<Type>` extends `Vector3<Type>` with a `w` component and 4D operations: component-wise arithmetic, scalar ops, dot/length helpers, clamping, hashing (for `float`) and `std::formatter` support. Optional ImGui interop is available behind a macro.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "vector4.hpp"
|
||||||
|
using omath::Vector4;
|
||||||
|
|
||||||
|
using Vec4f = Vector4<float>;
|
||||||
|
|
||||||
|
Vec4f a{1, 2, 3, 1};
|
||||||
|
Vec4f b{4, 5, 6, 2};
|
||||||
|
|
||||||
|
// Component-wise & scalar ops
|
||||||
|
auto c = a + b; // (5, 7, 9, 3)
|
||||||
|
c *= 0.5f; // (2.5, 3.5, 4.5, 1.5)
|
||||||
|
auto h = a * b; // Hadamard: (4, 10, 18, 2)
|
||||||
|
|
||||||
|
// Dot / length
|
||||||
|
float d = a.dot(b); // 1*4 + 2*5 + 3*6 + 1*2 = 32
|
||||||
|
float L = a.length(); // sqrt(x²+y²+z²+w²)
|
||||||
|
|
||||||
|
// Clamp (x,y,z only; see notes)
|
||||||
|
Vec4f col{1.4f, -0.2f, 0.7f, 42.f};
|
||||||
|
col.clamp(0.f, 1.f); // -> (1, 0, 0.7, w unchanged)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Data members
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Inherited from Vector3<Type>:
|
||||||
|
Type x{0};
|
||||||
|
Type y{0};
|
||||||
|
Type z{0};
|
||||||
|
|
||||||
|
// Added in Vector4:
|
||||||
|
Type w{0};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Constructors
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr Vector4() noexcept; // (0,0,0,0)
|
||||||
|
constexpr Vector4(const Type& x, const Type& y,
|
||||||
|
const Type& z, const Type& w); // value-init
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Equality & ordering
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr bool operator==(const Vector4&) const noexcept; // component-wise
|
||||||
|
constexpr bool operator!=(const Vector4&) const noexcept;
|
||||||
|
|
||||||
|
bool operator< (const Vector4&) const noexcept; // compare by length()
|
||||||
|
bool operator> (const Vector4&) const noexcept;
|
||||||
|
bool operator<=(const Vector4&) const noexcept;
|
||||||
|
bool operator>=(const Vector4&) const noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note:** Ordering uses **magnitude** (Euclidean norm), not lexicographic order.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Arithmetic (mutating)
|
||||||
|
|
||||||
|
With another vector (component-wise):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Vector4& operator+=(const Vector4&) noexcept;
|
||||||
|
Vector4& operator-=(const Vector4&) noexcept;
|
||||||
|
Vector4& operator*=(const Vector4&) noexcept; // Hadamard
|
||||||
|
Vector4& operator/=(const Vector4&) noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
With a scalar:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Vector4& operator*=(const Type& v) noexcept;
|
||||||
|
Vector4& operator/=(const Type& v) noexcept;
|
||||||
|
|
||||||
|
// From base class (inherited):
|
||||||
|
Vector4& operator+=(const Type& v) noexcept; // adds v to x,y,z (and w via base? see notes)
|
||||||
|
Vector4& operator-=(const Type& v) noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Arithmetic (non-mutating)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr Vector4 operator-() const noexcept;
|
||||||
|
constexpr Vector4 operator+(const Vector4&) const noexcept;
|
||||||
|
constexpr Vector4 operator-(const Vector4&) const noexcept;
|
||||||
|
constexpr Vector4 operator*(const Vector4&) const noexcept; // Hadamard
|
||||||
|
constexpr Vector4 operator/(const Vector4&) const noexcept; // Hadamard
|
||||||
|
constexpr Vector4 operator*(const Type& scalar) const noexcept;
|
||||||
|
constexpr Vector4 operator/(const Type& scalar) const noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Geometry & helpers
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr Type length_sqr() const noexcept; // x² + y² + z² + w²
|
||||||
|
Type length() const noexcept; // std::sqrt(length_sqr())
|
||||||
|
constexpr Type dot(const Vector4& rhs) const noexcept;
|
||||||
|
|
||||||
|
Vector4& abs() noexcept; // component-wise absolute
|
||||||
|
Vector4& clamp(const Type& min, const Type& max) noexcept;
|
||||||
|
// clamps x,y,z; leaves w unchanged (see notes)
|
||||||
|
constexpr Type sum() const noexcept; // x + y + z + w
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ImGui integration (optional)
|
||||||
|
|
||||||
|
Guarded by `OMATH_IMGUI_INTEGRATION`:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#ifdef OMATH_IMGUI_INTEGRATION
|
||||||
|
constexpr ImVec4 to_im_vec4() const noexcept;
|
||||||
|
// NOTE: Provided signature returns Vector4<float> and (in current code) sets only x,y,z.
|
||||||
|
// See "Notes & caveats" for a corrected version you may prefer.
|
||||||
|
static Vector4<float> from_im_vec4(const ImVec4& other) noexcept;
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Hashing & formatting
|
||||||
|
|
||||||
|
* **Hash specialization** (only for `Vector4<float>`):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<> struct std::hash<omath::Vector4<float>> {
|
||||||
|
std::size_t operator()(const omath::Vector4<float>&) const noexcept;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
std::unordered_map<omath::Vector4<float>, int> counts;
|
||||||
|
counts[{1.f, 2.f, 3.f, 1.f}] = 7;
|
||||||
|
```
|
||||||
|
|
||||||
|
* **`std::formatter`** (for any `Type`, all character kinds):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<class Type>
|
||||||
|
struct std::formatter<omath::Vector4<Type>>; // -> "[x, y, z, w]"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes & caveats (as implemented)
|
||||||
|
|
||||||
|
* `clamp(min,max)` **clamps only `x`, `y`, `z`** and **does not clamp `w`**. This may be intentional (e.g., when `w` is a homogeneous coordinate) — document your intent in your codebase.
|
||||||
|
If you want to clamp `w` too:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
w = std::clamp(w, min, max);
|
||||||
|
```
|
||||||
|
|
||||||
|
* **ImGui interop**:
|
||||||
|
|
||||||
|
* The header references `ImVec4` but does not include `<imgui.h>` itself. Ensure it’s included **before** this header whenever `OMATH_IMGUI_INTEGRATION` is defined.
|
||||||
|
* `from_im_vec4` currently returns `Vector4<float>` and (in the snippet shown) initializes **only x,y,z**. A more consistent version would be:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#ifdef OMATH_IMGUI_INTEGRATION
|
||||||
|
static Vector4<Type> from_im_vec4(const ImVec4& v) noexcept {
|
||||||
|
return {static_cast<Type>(v.x), static_cast<Type>(v.y),
|
||||||
|
static_cast<Type>(v.z), static_cast<Type>(v.w)};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
* Many scalar compound operators (`+= Type`, `-= Type`) are inherited from `Vector3<Type>`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API summary (signatures)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Ctors
|
||||||
|
constexpr Vector4() noexcept;
|
||||||
|
constexpr Vector4(const Type& x, const Type& y, const Type& z, const Type& w);
|
||||||
|
|
||||||
|
// Equality & ordering
|
||||||
|
constexpr bool operator==(const Vector4&) const noexcept;
|
||||||
|
constexpr bool operator!=(const Vector4&) const noexcept;
|
||||||
|
bool operator< (const Vector4&) const noexcept;
|
||||||
|
bool operator> (const Vector4&) const noexcept;
|
||||||
|
bool operator<=(const Vector4&) const noexcept;
|
||||||
|
bool operator>=(const Vector4&) const noexcept;
|
||||||
|
|
||||||
|
// Mutating arithmetic
|
||||||
|
Vector4& operator+=(const Vector4&) noexcept;
|
||||||
|
Vector4& operator-=(const Vector4&) noexcept;
|
||||||
|
Vector4& operator*=(const Vector4&) noexcept;
|
||||||
|
Vector4& operator/=(const Vector4&) noexcept;
|
||||||
|
Vector4& operator*=(const Type&) noexcept;
|
||||||
|
Vector4& operator/=(const Type&) noexcept;
|
||||||
|
// (inherited) Vector4& operator+=(const Type&) noexcept;
|
||||||
|
// (inherited) Vector4& operator-=(const Type&) noexcept;
|
||||||
|
|
||||||
|
// Non-mutating arithmetic
|
||||||
|
constexpr Vector4 operator-() const noexcept;
|
||||||
|
constexpr Vector4 operator+(const Vector4&) const noexcept;
|
||||||
|
constexpr Vector4 operator-(const Vector4&) const noexcept;
|
||||||
|
constexpr Vector4 operator*(const Vector4&) const noexcept;
|
||||||
|
constexpr Vector4 operator/(const Vector4&) const noexcept;
|
||||||
|
constexpr Vector4 operator*(const Type&) const noexcept;
|
||||||
|
constexpr Vector4 operator/(const Type&) const noexcept;
|
||||||
|
|
||||||
|
// Geometry & helpers
|
||||||
|
constexpr Type length_sqr() const noexcept;
|
||||||
|
Type length() const noexcept;
|
||||||
|
constexpr Type dot(const Vector4&) const noexcept;
|
||||||
|
Vector4& abs() noexcept;
|
||||||
|
Vector4& clamp(const Type& min, const Type& max) noexcept;
|
||||||
|
constexpr Type sum() const noexcept;
|
||||||
|
|
||||||
|
// ImGui (optional)
|
||||||
|
#ifdef OMATH_IMGUI_INTEGRATION
|
||||||
|
constexpr ImVec4 to_im_vec4() const noexcept;
|
||||||
|
static Vector4<float> from_im_vec4(const ImVec4&) noexcept; // see note for preferred template version
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Hash (float) and formatter specializations provided below the class
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 31 Oct 2025*
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
site_name: OM Docs
|
site_name: OMATH Docs
|
||||||
theme:
|
theme:
|
||||||
name: darkly
|
name: darkly
|
||||||
Reference in New Issue
Block a user