From 175c71637b6bea6dcdd0faf3d614339983809bb1 Mon Sep 17 00:00:00 2001 From: vimene Date: Thu, 15 Jan 2026 05:15:59 +0100 Subject: rewrote entirely the triangle clipping algorithm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is still a lot of work needed to refactor it properly. - use the Sutherland–Hodgman algorithm, with some minor changes - made clipping more general, allowing clipping of any coordinate, before and after division by w - compute the z coordinate only at the fragment stage instead of each time clipping creates / moves a vertex, in addition to the fragment stage - added VectorCoords to choose at compile-time different coordinates based on a template argument - added transpose struct to allow shuffling of vectors coordinates - added math::utils::lerp which interpolate linearly a float - added Vector{2,3,4}::map() which maps a vector from one range to another - added template parameter to DerivedVertex (and therefore TriangleDerived) to allow choosing which dimension to use --- src/math/vector.hpp | 205 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 202 insertions(+), 3 deletions(-) (limited to 'src/math/vector.hpp') diff --git a/src/math/vector.hpp b/src/math/vector.hpp index 471f30d..def469b 100644 --- a/src/math/vector.hpp +++ b/src/math/vector.hpp @@ -5,7 +5,122 @@ namespace engine::math { +namespace vector_coords { + +enum class VectorCoord { x, y, z, w }; + +template +struct transpose { template static constexpr VectorCoord id(); }; + +template<> struct transpose { template static constexpr VectorCoord id(); }; +template<> struct transpose { template static constexpr VectorCoord id(); }; +template<> struct transpose { template static constexpr VectorCoord id(); }; +template<> struct transpose { template static constexpr VectorCoord id(); }; + +template<> struct transpose { template static constexpr VectorCoord id(); }; +template<> struct transpose { template static constexpr VectorCoord id(); }; +template<> struct transpose { template static constexpr VectorCoord id(); }; +template<> struct transpose { template static constexpr VectorCoord id(); }; + +template<> struct transpose { template static constexpr VectorCoord id(); }; +template<> struct transpose { template static constexpr VectorCoord id(); }; +template<> struct transpose { template static constexpr VectorCoord id(); }; +template<> struct transpose { template static constexpr VectorCoord id(); }; + +template<> struct transpose { template static constexpr VectorCoord id(); }; +template<> struct transpose { template static constexpr VectorCoord id(); }; +template<> struct transpose { template static constexpr VectorCoord id(); }; +template<> struct transpose { template static constexpr VectorCoord id(); }; + +template<> constexpr VectorCoord transpose::id() { return VectorCoord::x; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::y; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::z; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::w; } + +template<> constexpr VectorCoord transpose::id() { return VectorCoord::y; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::x; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::z; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::w; } + +template<> constexpr VectorCoord transpose::id() { return VectorCoord::z; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::y; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::x; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::w; } + +template<> constexpr VectorCoord transpose::id() { return VectorCoord::w; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::y; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::z; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::x; } + +template<> constexpr VectorCoord transpose::id() { return VectorCoord::y; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::x; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::z; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::w; } + +template<> constexpr VectorCoord transpose::id() { return VectorCoord::x; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::y; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::z; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::w; } + +template<> constexpr VectorCoord transpose::id() { return VectorCoord::x; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::z; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::y; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::w; } + +template<> constexpr VectorCoord transpose::id() { return VectorCoord::x; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::w; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::z; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::y; } + +template<> constexpr VectorCoord transpose::id() { return VectorCoord::z; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::y; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::x; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::w; } + +template<> constexpr VectorCoord transpose::id() { return VectorCoord::x; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::z; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::y; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::w; } + +template<> constexpr VectorCoord transpose::id() { return VectorCoord::x; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::y; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::z; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::w; } + +template<> constexpr VectorCoord transpose::id() { return VectorCoord::x; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::y; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::w; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::z; } + +template<> constexpr VectorCoord transpose::id() { return VectorCoord::w; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::y; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::z; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::x; } + +template<> constexpr VectorCoord transpose::id() { return VectorCoord::x; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::w; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::z; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::y; } + +template<> constexpr VectorCoord transpose::id() { return VectorCoord::x; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::y; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::w; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::z; } + +template<> constexpr VectorCoord transpose::id() { return VectorCoord::x; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::y; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::z; } +template<> constexpr VectorCoord transpose::id() { return VectorCoord::w; } + +} + struct Vector2; +struct Vector3; +struct Vector4; + +template +concept VectorTypeConcept = std::is_same_v || std::is_same_v || std::is_same_v; + constexpr Vector2 operator*(float n, const Vector2& other); constexpr Vector2 operator/(const Vector2& other, float n); @@ -18,6 +133,25 @@ struct Vector2 { float x, y; + constexpr Vector2() {} + constexpr Vector2(float x, float y) : x { x }, y { y } {} + + template + constexpr float& v() & + requires (id == vector_coords::VectorCoord::x || id == vector_coords::VectorCoord::y) + { + if constexpr (id == vector_coords::VectorCoord::x) return x; + else return y; + } + + template + constexpr const float& v() const & + requires (id == vector_coords::VectorCoord::x || id == vector_coords::VectorCoord::y) + { + if constexpr (id == vector_coords::VectorCoord::x) return x; + else return y; + } + constexpr bool operator==(const Vector2& other) const & { return x == other.x && y == other.y; } @@ -59,6 +193,13 @@ struct Vector2 { constexpr Vector2 mul_term(const Vector2& other) const & { return { x * other.x, y * other.y }; } + + constexpr Vector2 map(const Vector2& from1, const Vector2& from2, const Vector2& to1, const Vector2& to2) { + return { + to1.x + (x - from1.x) * (to2.x - to1.x) / (from2.x - from1.x), + to1.y + (y - from1.y) * (to2.y - to1.y) / (from2.y - from1.y), + }; + } }; constexpr Vector2 operator*(float n, const Vector2& other) { @@ -81,7 +222,6 @@ constexpr Vector2 operator-(const Vector2& other, float n) { return { other.x - n, other.y - n }; } -struct Vector3; constexpr Vector3 operator*(float n, const Vector3& other); constexpr Vector3 operator/(const Vector3& other, float n); @@ -94,6 +234,28 @@ struct Vector3 { float x, y, z; + constexpr Vector3() {} + constexpr Vector3(float x, float y, float z) : x { x }, y { y }, z { z } {} + constexpr Vector3(const Vector2& v, float z) : x { v.x }, y { v.y }, z { z } {} + + template + constexpr float& v() & + requires (id == vector_coords::VectorCoord::x || id == vector_coords::VectorCoord::y || id == vector_coords::VectorCoord::z) + { + if constexpr (id == vector_coords::VectorCoord::x) return x; + else if constexpr (id == vector_coords::VectorCoord::y) return y; + else return z; + } + + template + constexpr const float& v() const & + requires (id == vector_coords::VectorCoord::x || id == vector_coords::VectorCoord::y || id == vector_coords::VectorCoord::z) + { + if constexpr (id == vector_coords::VectorCoord::x) return x; + else if constexpr (id == vector_coords::VectorCoord::y) return y; + else return z; + } + constexpr bool operator==(const Vector3& other) const & { return x == other.x && y == other.y && z == other.z; } @@ -125,6 +287,10 @@ struct Vector3 { return *this; } + constexpr Vector2 xy() const & { + return { x, y }; + } + constexpr Vector3 round() { return { std::round(x), std::round(y), std::round(z) }; } @@ -152,6 +318,14 @@ struct Vector3 { constexpr Vector3 normalize() const & { return *this / length(); } + + constexpr Vector3 map(const Vector3& from1, const Vector3& from2, const Vector3& to1, const Vector3& to2) { + return { + to1.x + (x - from1.x) * (to2.x - to1.x) / (from2.x - from1.x), + to1.y + (y - from1.y) * (to2.y - to1.y) / (from2.y - from1.y), + to1.z + (z - from1.z) * (to2.z - to1.z) / (from2.z - from1.z), + }; + } }; constexpr Vector3 operator*(float n, const Vector3& other) { @@ -175,6 +349,22 @@ struct Vector4 { float x, y, z, w; + template + constexpr float& v() & { + if constexpr (id == vector_coords::VectorCoord::x) return x; + else if constexpr (id == vector_coords::VectorCoord::y) return y; + else if constexpr (id == vector_coords::VectorCoord::z) return z; + else return w; + } + + template + constexpr const float& v() const & { + if constexpr (id == vector_coords::VectorCoord::x) return x; + else if constexpr (id == vector_coords::VectorCoord::y) return y; + else if constexpr (id == vector_coords::VectorCoord::z) return z; + else return w; + } + constexpr Vector4() {} constexpr Vector4(float x, float y, float z, float w) : x{x}, y{y}, z{z}, w{w} {} constexpr Vector4(const Vector2& v, float z, float w) : x{v.x}, y{v.y}, z{z}, w{w} {} @@ -216,8 +406,17 @@ struct Vector4 { return { x, y, z }; } - constexpr Vector4 div_by_w() const & { - return {x / w, y / w, z / w, w}; + constexpr Vector3 div_by_w() const & { + return { x / w, y / w, w }; + } + + constexpr Vector4 map(const Vector4& from1, const Vector4& from2, const Vector4& to1, const Vector4& to2) { + return { + to1.x + (x - from1.x) * (to2.x - to1.x) / (from2.x - from1.x), + to1.y + (y - from1.y) * (to2.y - to1.y) / (from2.y - from1.y), + to1.z + (z - from1.z) * (to2.z - to1.z) / (from2.z - from1.z), + to1.w + (w - from1.w) * (to2.w - to1.w) / (from2.w - from1.w), + }; } }; -- cgit v1.2.3