From 6a1c1849298b76f5146890938dab9fe3338fd336 Mon Sep 17 00:00:00 2001 From: Desour Date: Thu, 10 Oct 2024 19:04:25 +0200 Subject: [PATCH] create ConvexPolygon struct --- src/client/clientmap.cpp | 28 ++++++------- src/client/clientmap.h | 5 ++- src/util/convex_polygon.cpp | 83 +++++++++++++++++++------------------ src/util/convex_polygon.h | 52 +++++++++++++---------- 4 files changed, 91 insertions(+), 77 deletions(-) diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp index f5a8d3f1fad5..423f58bbe6af 100644 --- a/src/client/clientmap.cpp +++ b/src/client/clientmap.cpp @@ -1069,7 +1069,7 @@ int ClientMap::getBackgroundBrightness(float max_d, u32 daylight_factor, return ret; } -std::vector, video::SColor>> +std::vector> ClientMap::getPostFxPolygons() { using mat4 = core::matrix4; @@ -1168,7 +1168,7 @@ ClientMap::getPostFxPolygons() return mat4(proj_mat * view_mat, mat4::EM4CONST_INVERSE_TRANSPOSED); }(); - std::vector, video::SColor>> polygons; + std::vector> polygons; // Go through all 8 nodes that the near plane possibly instersects with @@ -1199,12 +1199,12 @@ ClientMap::getPostFxPolygons() if (post_color.getAlpha() == 0) continue; - const std::vector screen_polygon{ + const ConvexPolygon screen_polygon{{ {0.0f, 0.0f}, // upper-left {1.0f, 0.0f}, // upper-right {1.0f, 1.0f}, // lower-right {0.0f, 1.0f}, // lower-left - }; + }}; // the (inverse and inverse transposed) world matrix for the node // Transforms planes from node-local space to camera-offset-local world @@ -1216,7 +1216,7 @@ ClientMap::getPostFxPolygons() const mat4 wvp_mat_ti = vp_mat_ti * world_mat_ti; - auto clip_polygon_by_objsp_plane = [&](std::vector &polyg, + auto clip_polygon_by_objsp_plane = [&](ConvexPolygon &polyg, const v4f &clip_plane) -> bool { v4f clip_plane_clipspace = mat4_mult_v4f(wvp_mat_ti, clip_plane); @@ -1225,11 +1225,11 @@ ClientMap::getPostFxPolygons() // a*p.X + b*p.Y + c*p.Z + d >= 0 v3f clip_line(clip_plane_clipspace[0], clip_plane_clipspace[1], clip_plane_clipspace[3]); - polyg = clip_convex_polygon(polyg, clip_line); - return polyg.size() >= 3; + polyg = polyg.clip(clip_line); + return polyg.vertices.size() >= 3; }; - auto clip_polygon_by_objsp_planes = [&](std::vector &polyg, + auto clip_polygon_by_objsp_planes = [&](ConvexPolygon &polyg, const std::vector &clip_planes) -> bool { for (const v4f &clip_plane : clip_planes) if (!clip_polygon_by_objsp_plane(polyg, clip_plane)) @@ -1239,7 +1239,7 @@ ClientMap::getPostFxPolygons() if (features.drawtype == NDT_NORMAL) { // draw full cube - std::vector polygon = screen_polygon; + ConvexPolygon polygon = screen_polygon; if (!clip_polygon_by_objsp_planes(polygon, { { 2.0f, 0.0f, 0.0f, 1.0f}, {-2.0f, 0.0f, 0.0f, 1.0f}, @@ -1253,7 +1253,7 @@ ClientMap::getPostFxPolygons() } else if (features.drawtype == NDT_LIQUID || features.drawtype == NDT_FLOWINGLIQUID) { - std::vector polygon = screen_polygon; + ConvexPolygon polygon = screen_polygon; // clip by all but top if (!clip_polygon_by_objsp_planes(polygon, { { 2.0f, 0.0f, 0.0f, 1.0f}, @@ -1311,8 +1311,8 @@ ClientMap::getPostFxPolygons() indices = {0, 1, 3, 0, 3, 2}; } - std::vector polygon1 = polygon; - std::vector &polygon2 = polygon; + ConvexPolygon polygon1 = polygon; + ConvexPolygon &polygon2 = polygon; if (clip_polygon_by_objsp_plane(polygon1, triangle_split_plane) && clip_polygon_by_objsp_plane(polygon1, @@ -1346,7 +1346,7 @@ video::SColorf ClientMap::renderPostFx() video::IVideoDriver *driver = SceneManager->getVideoDriver(); for (const auto &[polygon, post_color] : polygons) { - draw_convex_polygon(driver, polygon, post_color); + polygon.draw(driver, post_color); } // Color for wield item @@ -1358,7 +1358,7 @@ video::SColorf ClientMap::renderPostFx() video::SColorf color = post_color; // (screen size and aspect ratio don't matter for relative screen area) - f32 area = get_convex_polygon_area(polygon); + f32 area = polygon.area(); color.a *= area; color_sum.r += color.a * color.r; diff --git a/src/client/clientmap.h b/src/client/clientmap.h index 8d2b92eeb295..a16df8b32d65 100644 --- a/src/client/clientmap.h +++ b/src/client/clientmap.h @@ -25,6 +25,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include +struct ConvexPolygon; + struct MapDrawControl { // Wanted drawing range @@ -158,10 +160,9 @@ class ClientMap : public Map, public scene::ISceneNode void updateTransparentMeshBuffers(); // helper for renderPostFx - std::vector, video::SColor>> + std::vector> getPostFxPolygons(); - // Orders blocks by distance to the camera class MapBlockComparer { diff --git a/src/util/convex_polygon.cpp b/src/util/convex_polygon.cpp index b656fde03f64..079c9f62972c 100644 --- a/src/util/convex_polygon.cpp +++ b/src/util/convex_polygon.cpp @@ -9,10 +9,9 @@ #include -void draw_convex_polygon(video::IVideoDriver *driver, const std::vector &polygon, - const video::SColor &color) +void ConvexPolygon::draw(video::IVideoDriver *driver, const video::SColor &color) const { - if (polygon.size() < 3) + if (vertices.size() < 3) return; auto new_2d_vertex = [&color](const v2f &pos) -> video::S3DVertex { @@ -21,14 +20,14 @@ void draw_convex_polygon(video::IVideoDriver *driver, const std::vector &po v3f(), color, v2f()); }; - std::vector vertices; - vertices.reserve(polygon.size()); - for (const v2f &v : polygon) - vertices.push_back(new_2d_vertex(v)); + std::vector s3d_vertices; + s3d_vertices.reserve(vertices.size()); + for (const v2f &v : vertices) + s3d_vertices.push_back(new_2d_vertex(v)); std::vector index_list; - index_list.reserve(polygon.size()); - for (size_t i = 0; i < polygon.size(); ++i) + index_list.reserve(vertices.size()); + for (size_t i = 0; i < vertices.size(); ++i) index_list.push_back(i); video::SMaterial material; @@ -40,7 +39,7 @@ void draw_convex_polygon(video::IVideoDriver *driver, const std::vector &po driver->setTransform(video::ETS_VIEW, core::matrix4::EM4CONST_IDENTITY); driver->setTransform(video::ETS_WORLD, core::matrix4::EM4CONST_IDENTITY); - driver->drawVertexPrimitiveList((void *)&vertices[0], (u32)vertices.size(), + driver->drawVertexPrimitiveList((void *)&s3d_vertices[0], (u32)s3d_vertices.size(), (void *)&index_list[0], (u32)index_list.size() - 2, video::EVT_STANDARD, // S3DVertex vertices scene::EPT_TRIANGLE_FAN, @@ -49,16 +48,16 @@ void draw_convex_polygon(video::IVideoDriver *driver, const std::vector &po #endif // !def(SERVER) -f32 get_convex_polygon_area(const std::vector &polygon) +f32 ConvexPolygon::area() const { - if (polygon.size() < 3) + if (vertices.size() < 3) return 0.0f; // sum up the areas of all triangles f32 area = 0.0f; - const v2f &v1 = polygon[0]; - for (size_t i = 2; i < polygon.size(); ++i) { - const v2f &v2 = polygon[i-1]; - const v2f &v3 = polygon[i]; + const v2f &v1 = vertices[0]; + for (size_t i = 2; i < vertices.size(); ++i) { + const v2f &v2 = vertices[i-1]; + const v2f &v3 = vertices[i]; // area of the triangle v1 v2 v3: 0.5 * det(d1 d2) // (winding order matters, for sign) v2f d1 = v2 - v1; @@ -68,12 +67,16 @@ f32 get_convex_polygon_area(const std::vector &polygon) return area; } -std::vector clip_convex_polygon(const std::vector &polygon, v3f clip_line) +ConvexPolygon ConvexPolygon::clip(v3f clip_line) const { using polygon_iterator = std::vector::const_iterator; // the return value - std::vector polygon_clipped; + ConvexPolygon clipped; + auto &vertices_out = clipped.vertices; + + if (vertices.empty()) + return clipped; // emtpty // returns whether pos is in the not clipped half-space auto is_in = [&](const v2f &pos) { @@ -102,39 +105,39 @@ std::vector clip_convex_polygon(const std::vector &polygon, v3f clip_l // before polygon_iterator first_in, first_out; polygon_iterator last_out, last_in; - if (is_in(polygon[0])) { - first_out = std::find_if(polygon.begin() + 1, polygon.end(), is_out); - if (first_out == polygon.end()) { + if (is_in(vertices[0])) { + first_out = std::find_if(vertices.begin() + 1, vertices.end(), is_out); + if (first_out == vertices.end()) { // all are in - polygon_clipped = polygon; - return polygon_clipped; + clipped = {vertices}; + return clipped; } last_in = first_out - 1; - first_in = std::find_if(first_out + 1, polygon.end(), is_in); + first_in = std::find_if(first_out + 1, vertices.end(), is_in); last_out = first_in - 1; - if (first_in == polygon.end()) - first_in = polygon.begin(); // we already checked that the 0th is in + if (first_in == vertices.end()) + first_in = vertices.begin(); // we already checked that the 0th is in } else { - first_in = std::find_if(polygon.begin() + 1, polygon.end(), is_in); - if (first_in == polygon.end()) { + first_in = std::find_if(vertices.begin() + 1, vertices.end(), is_in); + if (first_in == vertices.end()) { // all are out - return polygon_clipped; // empty + return clipped; // empty } last_out = first_in - 1; - first_out = std::find_if(first_in + 1, polygon.end(), is_out); + first_out = std::find_if(first_in + 1, vertices.end(), is_out); last_in = first_out - 1; - if (first_out == polygon.end()) - first_out = polygon.begin(); // we already checked that the 0th is out + if (first_out == vertices.end()) + first_out = vertices.begin(); // we already checked that the 0th is out } // copy all vertices that are in if (first_in <= last_in) { - polygon_clipped.reserve((last_in - first_in) + 1 + 2); - polygon_clipped.insert(polygon_clipped.end(), first_in, last_in + 1); + vertices_out.reserve((last_in - first_in) + 1 + 2); + vertices_out.insert(vertices_out.end(), first_in, last_in + 1); } else { - polygon_clipped.reserve((polygon.end() - first_in) + (last_in - polygon.begin()) + 1 + 2); - polygon_clipped.insert(polygon_clipped.end(), first_in, polygon.end()); - polygon_clipped.insert(polygon_clipped.end(), polygon.begin(), last_in + 1); + vertices_out.reserve((vertices.end() - first_in) + (last_in - vertices.begin()) + 1 + 2); + vertices_out.insert(vertices_out.end(), first_in, vertices.end()); + vertices_out.insert(vertices_out.end(), vertices.begin(), last_in + 1); } auto split_edge = [&](const v2f &p1, const v2f &p2) { @@ -147,10 +150,10 @@ std::vector clip_convex_polygon(const std::vector &polygon, v3f clip_l }; // split in-out pair - polygon_clipped.push_back(split_edge(*last_in, *first_out)); + vertices_out.push_back(split_edge(*last_in, *first_out)); // split out-in pair - polygon_clipped.push_back(split_edge(*last_out, *first_in)); + vertices_out.push_back(split_edge(*last_out, *first_in)); - return polygon_clipped; + return clipped; } diff --git a/src/util/convex_polygon.h b/src/util/convex_polygon.h index 72b7c4eeb514..a717638c112b 100644 --- a/src/util/convex_polygon.h +++ b/src/util/convex_polygon.h @@ -12,29 +12,39 @@ #ifndef SERVER namespace irr::video { class IVideoDriver; } +#endif // !def(SERVER) -/** Draws a convex polygon over the whole screen. - * @param polygon Ordered list of corner vertices. - * X coordinates go from 0 (left) to 1 (right), Y from 0 (up) to - * 1 (down). +/** + * A polygon, stored as closed polyonal chain (ordered vertex list). + * The functions assume it's convex. */ -void draw_convex_polygon(video::IVideoDriver *driver, const std::vector &polygon, - const video::SColor &color); +struct ConvexPolygon +{ + std::vector vertices; + +#ifndef SERVER + + /** Draws the polygon over the whole screen. + * + * X coordinates go from 0 (left) to 1 (right), Y from 0 (up) to 1 (down). + */ + void draw(video::IVideoDriver *driver, const video::SColor &color) const; #endif // !def(SERVER) -/** Calculates the area of a convex polygon, given by its corners - * @param polygon Ordered list of corner vertices. - * @return The area. - */ -f32 get_convex_polygon_area(const std::vector &polygon); - -/** Clips away the parts of a convex polygon that are on the wrong side of the - * given clip line. - * @param polygon Nonempty list of vertices that form a convex polygon if you connect - * them in order. - * @param clip_line The homogeneous coordinates of an oriented 2D line. Clips - * away all points p for which dot(clip_line, p) < 0 holds. - * @return The clipped polygon. - */ -std::vector clip_convex_polygon(const std::vector &polygon, v3f clip_line); + /** Calculates the area. + * + * @return The area. + */ + [[nodiscard]] + f32 area() const; + + /** Clips away the parts of the polygon that are on the wrong side of the + * given clip line. + * @param clip_line The homogeneous coordinates of an oriented 2D line. Clips + * away all points p for which dot(clip_line, p) < 0 holds. + * @return The clipped polygon. + */ + [[nodiscard]] + ConvexPolygon clip(v3f clip_line) const; +};