diff options
-rw-r--r-- | Userland/Libraries/LibSoftGPU/Clipper.cpp | 78 | ||||
-rw-r--r-- | Userland/Libraries/LibSoftGPU/Clipper.h | 31 |
2 files changed, 51 insertions, 58 deletions
diff --git a/Userland/Libraries/LibSoftGPU/Clipper.cpp b/Userland/Libraries/LibSoftGPU/Clipper.cpp index 2dec517b02..e46d79eedd 100644 --- a/Userland/Libraries/LibSoftGPU/Clipper.cpp +++ b/Userland/Libraries/LibSoftGPU/Clipper.cpp @@ -11,35 +11,44 @@ namespace SoftGPU { -bool Clipper::point_within_clip_plane(FloatVector4 const& vertex, ClipPlane plane) const +static constexpr FloatVector4 clip_plane_normals[] = { + { 1, 0, 0, 0 }, // Left Plane + { -1, 0, 0, 0 }, // Right Plane + { 0, -1, 0, 0 }, // Top Plane + { 0, 1, 0, 0 }, // Bottom plane + { 0, 0, 1, 0 }, // Near Plane + { 0, 0, -1, 0 } // Far Plane +}; + +static constexpr bool point_within_clip_plane(FloatVector4 const& vertex, Clipper::ClipPlane plane) { switch (plane) { - case ClipPlane::LEFT: + case Clipper::ClipPlane::LEFT: return vertex.x() >= -vertex.w(); - case ClipPlane::RIGHT: + case Clipper::ClipPlane::RIGHT: return vertex.x() <= vertex.w(); - case ClipPlane::TOP: + case Clipper::ClipPlane::TOP: return vertex.y() <= vertex.w(); - case ClipPlane::BOTTOM: + case Clipper::ClipPlane::BOTTOM: return vertex.y() >= -vertex.w(); - case ClipPlane::NEAR: + case Clipper::ClipPlane::NEAR: return vertex.z() >= -vertex.w(); - case ClipPlane::FAR: + case Clipper::ClipPlane::FAR: return vertex.z() <= vertex.w(); } return false; } -Vertex Clipper::clip_intersection_point(Vertex const& p1, Vertex const& p2, ClipPlane plane_index) const +static Vertex clip_intersection_point(Vertex const& p1, Vertex const& p2, Clipper::ClipPlane plane) { // See https://www.microsoft.com/en-us/research/wp-content/uploads/1978/01/p245-blinn.pdf // "Clipping Using Homogeneous Coordinates" Blinn/Newell, 1978 float const w1 = p1.clip_coordinates.w(); float const w2 = p2.clip_coordinates.w(); - float const x1 = clip_plane_normals[plane_index].dot(p1.clip_coordinates); - float const x2 = clip_plane_normals[plane_index].dot(p2.clip_coordinates); + float const x1 = clip_plane_normals[to_underlying(plane)].dot(p1.clip_coordinates); + float const x2 = clip_plane_normals[to_underlying(plane)].dot(p2.clip_coordinates); float const a = (w1 + x1) / ((w1 + x1) - (w2 + x2)); Vertex out; @@ -53,35 +62,40 @@ Vertex Clipper::clip_intersection_point(Vertex const& p1, Vertex const& p2, Clip return out; } -void Clipper::clip_triangle_against_frustum(Vector<Vertex>& input_verts) +static void clip_plane(Vector<Vertex>& read_list, Vector<Vertex>& write_list, Clipper::ClipPlane plane) { - list_a = input_verts; - list_b.clear_with_capacity(); + auto read_from = &read_list; + auto write_to = &write_list; - auto read_from = &list_a; - auto write_to = &list_b; + write_to->clear_with_capacity(); + // FIXME C++23. Static reflection will provide looping over all enum values. + for (size_t i = 0; i < read_from->size(); i++) { + auto const& curr_vec = read_from->at((i + 1) % read_from->size()); + auto const& prev_vec = read_from->at(i); - for (size_t plane = 0; plane < NUMBER_OF_CLIPPING_PLANES; plane++) { - write_to->clear_with_capacity(); - // Save me, C++23 - for (size_t i = 0; i < read_from->size(); i++) { - auto const& curr_vec = read_from->at((i + 1) % read_from->size()); - auto const& prev_vec = read_from->at(i); - - if (point_within_clip_plane(curr_vec.clip_coordinates, static_cast<ClipPlane>(plane))) { - if (!point_within_clip_plane(prev_vec.clip_coordinates, static_cast<ClipPlane>(plane))) { - auto const intersect = clip_intersection_point(prev_vec, curr_vec, static_cast<ClipPlane>(plane)); - write_to->append(intersect); - } - write_to->append(curr_vec); - } else if (point_within_clip_plane(prev_vec.clip_coordinates, static_cast<ClipPlane>(plane))) { - auto const intersect = clip_intersection_point(prev_vec, curr_vec, static_cast<ClipPlane>(plane)); + if (point_within_clip_plane(curr_vec.clip_coordinates, plane)) { + if (!point_within_clip_plane(prev_vec.clip_coordinates, plane)) { + auto const intersect = clip_intersection_point(prev_vec, curr_vec, plane); write_to->append(intersect); } + write_to->append(curr_vec); + } else if (point_within_clip_plane(prev_vec.clip_coordinates, plane)) { + auto const intersect = clip_intersection_point(prev_vec, curr_vec, plane); + write_to->append(intersect); } - swap(write_to, read_from); + } + swap(write_list, read_list); +} + +void Clipper::clip_triangle_against_frustum(Vector<Vertex>& input_verts) +{ + list_a = input_verts; + list_b.clear_with_capacity(); + + for (size_t plane = 0; plane < NUMBER_OF_CLIPPING_PLANES; plane++) { + clip_plane(list_a, list_b, static_cast<ClipPlane>(plane)); } - input_verts = *read_from; + input_verts = list_a; } } diff --git a/Userland/Libraries/LibSoftGPU/Clipper.h b/Userland/Libraries/LibSoftGPU/Clipper.h index d2bf2c85ba..87b14c4c4a 100644 --- a/Userland/Libraries/LibSoftGPU/Clipper.h +++ b/Userland/Libraries/LibSoftGPU/Clipper.h @@ -13,7 +13,10 @@ namespace SoftGPU { class Clipper final { - enum ClipPlane : u8 { + static constexpr u8 NUMBER_OF_CLIPPING_PLANES = 6; + +public: + enum class ClipPlane : u8 { LEFT = 0, RIGHT, TOP, @@ -22,35 +25,11 @@ class Clipper final { FAR }; - static constexpr u8 NUMBER_OF_CLIPPING_PLANES = 6; - static constexpr u8 MAX_CLIPPED_VERTS = 6; - - static constexpr FloatVector4 clip_planes[] = { - { -1, 0, 0, 1 }, // Left Plane - { 1, 0, 0, 1 }, // Right Plane - { 0, 1, 0, 1 }, // Top Plane - { 0, -1, 0, 1 }, // Bottom plane - { 0, 0, 1, 1 }, // Near Plane - { 0, 0, -1, 1 } // Far Plane - }; - - static constexpr FloatVector4 clip_plane_normals[] = { - { 1, 0, 0, 0 }, // Left Plane - { -1, 0, 0, 0 }, // Right Plane - { 0, -1, 0, 0 }, // Top Plane - { 0, 1, 0, 0 }, // Bottom plane - { 0, 0, 1, 0 }, // Near Plane - { 0, 0, -1, 0 } // Far Plane - }; - -public: - Clipper() { } + Clipper() = default; void clip_triangle_against_frustum(Vector<Vertex>& input_vecs); private: - bool point_within_clip_plane(FloatVector4 const& vertex, ClipPlane plane) const; - Vertex clip_intersection_point(Vertex const& vec, Vertex const& prev_vec, ClipPlane plane_index) const; Vector<Vertex> list_a; Vector<Vertex> list_b; }; |