Commit: 8ef03b070d6f757d0ed799fb8526db8edb02f9be Author: Jeroen Bakker Date: Tue Jun 7 14:39:08 2022 +0200 Branches: temp-T97352-3d-texturing-seam-bleeding-b2 https://developer.blender.org/rB8ef03b070d6f757d0ed799fb8526db8edb02f9be
Use edges for borders. =================================================================== M source/blender/blenkernel/BKE_uv_islands.hh M source/blender/blenkernel/intern/uv_islands.cc =================================================================== diff --git a/source/blender/blenkernel/BKE_uv_islands.hh b/source/blender/blenkernel/BKE_uv_islands.hh index 33aecaceca9..77c430dea7c 100644 --- a/source/blender/blenkernel/BKE_uv_islands.hh +++ b/source/blender/blenkernel/BKE_uv_islands.hh @@ -4,6 +4,7 @@ #pragma once #include <fstream> +#include <optional> #include "BLI_array.hh" #include "BLI_edgehash.h" @@ -71,6 +72,16 @@ struct MeshPrimitive { BLI_assert_unreachable(); return vertices[0]; } + + MeshUVVert *get_other_uv_vertex(const MeshVertex *v1, const MeshVertex *v2) + { + for (MeshUVVert &uv_vertex : vertices) { + if (uv_vertex.vertex != v1 && uv_vertex.vertex != v2) { + return &uv_vertex; + } + } + return nullptr; + } }; /** Wrapper to contain all required mesh data. */ @@ -284,43 +295,51 @@ struct UVPrimitive { } return false; } + + UVBorder extract_border() const; }; -struct UVBorderVert { - UVVertex *uv_vertex; +struct UVBorderEdge { + UVEdge *edge; + bool tag = false; + UVPrimitive *uv_primitive; + /* Should the vertices of the edge be evaluated in reverse order. */ + bool reverse_order = false; - /* Indexes of connected border verts. */ - int64_t index; - int64_t prev_index; - int64_t next_index; - int64_t border_index; + int64_t index = -1; + int64_t prev_index = -1; + int64_t next_index = -1; + int64_t border_index = -1; struct { - /** Should this vertex still be checked when performing extension. */ + /* Is possible to extend on the `get_uv_vertex(0)` */ bool extendable : 1; } flags; - explicit UVBorderVert(UVVertex *uv_vertex) : uv_vertex(uv_vertex) + explicit UVBorderEdge(UVEdge *edge, UVPrimitive *uv_primitive) + : edge(edge), uv_primitive(uv_primitive) { flags.extendable = true; } -}; - -struct UVBorderEdge { - UVEdge *edge; - bool tag = false; - UVPrimitive *uv_primitive; - explicit UVBorderEdge(UVEdge *edge, UVPrimitive *uv_primitive) - : edge(edge), uv_primitive(uv_primitive) + UVVertex *get_uv_vertex(int index) + { + int actual_index = reverse_order ? 1 - index : index; + return edge->vertices[actual_index]; + } + const UVVertex *get_uv_vertex(int index) const { + int actual_index = reverse_order ? 1 - index : index; + return edge->vertices[actual_index]; } }; +using UVBorderCorner = std::pair<UVBorderEdge &, UVBorderEdge &>; + struct UVBorder { /** Ordered list of UV Verts of the border of this island. */ // TODO: support multiple rings + order (CW, CCW) - Vector<UVBorderVert> verts; + Vector<UVBorderEdge> edges; /** * Flip the order of the verts, changing the order between CW and CCW. @@ -330,9 +349,11 @@ struct UVBorder { /** * Calculate the outside angle of the given vert. */ - float outside_angle(const UVBorderVert &vert) const; + float outside_angle(const UVBorderEdge &vert) const; void update_indexes(uint64_t border_index); + + static std::optional<UVBorder> extract_from_edges(Vector<UVBorderEdge> &edges); }; struct UVIsland { @@ -340,8 +361,8 @@ struct UVIsland { Vector<UVEdge> uv_edges; Vector<UVPrimitive> uv_primitives; /** - * List of borders of this island. There can be multiple borders per island as a border could be - * completely encapsulated by another one. + * List of borders of this island. There can be multiple borders per island as a border could + * be completely encapsulated by another one. */ Vector<UVBorder> borders; @@ -400,7 +421,7 @@ struct UVIsland { } /** Initialize the border attribute. */ - void extract_border(); + void extract_borders(); /** Iterative extend border to fit the mask. */ void extend_border(const UVIslandsMask &mask, const short island_index, @@ -504,8 +525,24 @@ struct UVIslands { void extract_borders() { for (UVIsland &island : islands) { - island.extract_border(); + island.extract_borders(); } + +#ifdef DEBUG_SVG + std::ofstream of; + of.open("/tmp/borders.svg"); + svg_header(of); + for (UVIsland &island : islands) { + int index = 0; + for (UVBorder &border : island.borders) { + border.update_indexes(index); + index++; + svg(of, border); + } + } + svg_footer(of); + of.close(); +#endif } void extend_borders(const UVIslandsMask &islands_mask, const MeshData &mesh_data) diff --git a/source/blender/blenkernel/intern/uv_islands.cc b/source/blender/blenkernel/intern/uv_islands.cc index 58e758a56d7..e69f19b7ee8 100644 --- a/source/blender/blenkernel/intern/uv_islands.cc +++ b/source/blender/blenkernel/intern/uv_islands.cc @@ -3,13 +3,17 @@ #include "BKE_uv_islands.hh" +#include <optional> + namespace blender::bke::uv_islands { + /* -------------------------------------------------------------------- */ /** \name UVIsland * \{ */ -void UVIsland::extract_border() +void UVIsland::extract_borders() { + /* Lookup all borders of the island. */ Vector<UVBorderEdge> edges; for (int64_t prim_index = 0; prim_index < uv_primitives.size(); prim_index++) { UVPrimitive &prim = uv_primitives[prim_index]; @@ -21,72 +25,38 @@ void UVIsland::extract_border() } while (true) { - UVBorder border; - /* Find a part of the border that haven't been extracted yet. */ - UVBorderEdge *starting_border_edge = nullptr; - for (UVBorderEdge &edge : edges) { - if (edge.tag == false) { - starting_border_edge = &edge; - break; - } - } - if (starting_border_edge == nullptr) { + std::optional<UVBorder> border = UVBorder::extract_from_edges(edges); + if (!border.has_value()) { break; } - - starting_border_edge->tag = true; - float2 first_uv = starting_border_edge->edge->vertices[0]->uv; - float2 current_uv = starting_border_edge->edge->vertices[1]->uv; - UVVertex *current_vert = starting_border_edge->edge->vertices[1]; - border.verts.append(UVBorderVert(starting_border_edge->edge->vertices[0])); - while (current_uv != first_uv) { - for (UVBorderEdge &border_edge : edges) { - if (border_edge.tag == true) { - continue; - } - int i; - for (i = 0; i < 2; i++) { - if (border_edge.edge->vertices[i]->uv == current_uv) { - border.verts.append(UVBorderVert(current_vert)); - current_uv = border_edge.edge->vertices[1 - i]->uv; - current_vert = border_edge.edge->vertices[1 - i]; - border_edge.tag = true; - break; - } - } - if (i != 2) { - break; - } - } - } - borders.append(border); + borders.append(*border); } } -static UVBorderVert *sharpest_border_vert(UVBorder &border, float *r_angle) +static std::optional<UVBorderCorner> sharpest_border_corner(UVBorder &border, float *r_angle) { *r_angle = std::numeric_limits<float>::max(); - UVBorderVert *result = nullptr; - for (UVBorderVert &vert : border.verts) { - if (vert.flags.extendable == false) { + std::optional<UVBorderCorner> result; + for (UVBorderEdge &edge : border.edges) { + if (edge.flags.extendable == false) { continue; } - float new_radius = border.outside_angle(vert); + float new_radius = border.outside_angle(edge); if (new_radius < *r_angle) { *r_angle = new_radius; - result = | + result = UVBorderCorner(border.edges[edge.prev_index], edge); } } return result; } -static UVBorderVert *sharpest_border_vert(UVIsland &island) +static std::optional<UVBorderCorner> sharpest_border_corner(UVIsland &island) { - UVBorderVert *result = nullptr; + std::optional<UVBorderCorner> result; float sharpest_angle = std::numeric_limits<float>::max(); for (UVBorder &border : island.borders) { float new_radius; - UVBorderVert *new_result = sharpest_border_vert(border, &new_radius); + std::optional<UVBorderCorner> new_result = sharpest_border_corner(border, &new_radius); if (new_radius < sharpest_angle) { sharpest_angle = new_radius; result = new_result; @@ -168,7 +138,7 @@ struct Fan { } } - void init_uv_coordinates(UVBorderVert &vert, const UVIsland &island) + void init_uv_coordinates(UVVertex &uv_vertex, const UVIsland &island) { for (FanSegment &segment : segments) { int2 test_edge = int2(segment.primitive->vertices[segment.vert_order[0]].vertex->v, @@ -178,9 +148,9 @@ struct Fan { int2 o(edge->vertices[0]->vertex->v, edge->vertices[1]->vertex->v); if ((test_edge.x == o.x && test_edge.y == o.y) || (test_edge.x == o.y && test_edge.y == o.x)) { - segment.uvs[0] = vert.uv_vertex->uv; + segment.uvs[0] = uv_vertex.uv; for (int i = 0; i < 2; i++) { - if (edge->vertices[i]->uv == vert.uv_vertex->uv) { + if (edge->vertices[i]->uv == uv_vertex.uv) { segment.uvs[1] = edge->vertices[1 - i]->uv; break; } @@ -211,18 +181,20 @@ static void print(const Fan &fan) } } -static void extend_at_vert(UVIsland &island, UVBorderVert &vert, const MeshData &mesh_data) +static void extend_at_vert(UVIsland &island, UVBorderCorner &corner, const MeshData &mesh_data) { - Fan fan(*vert.uv_vertex->vertex); + BLI_assert(corner.first.get_uv_vertex(1) == corner.second.get_uv_vertex(0)); + UVVertex *uv_vertex = corner.second.get_uv_vertex(0); + Fan fan(*(uv_vertex->vertex)); print(fan); - fan.init_uv_coordinates(vert, island); + fan.init_uv_coordinates(*uv_vertex, island); print(fan); for (FanSegment &segment : fan.segments) { segment.flags.found = false; MeshVertex *v0 = segment.primitive->vertices[segment.vert_order[0]].vertex; MeshVertex *v1 = segment.primitive->vertices[segment.vert_order[1]].vertex; - for (UVEdge *edge : vert.uv_vertex->uv_edges) { + for (UVEdge *edge : uv_vertex->uv_edges) { if ((edge->vertices[0]->vertex == v0 && edge->vertices[1]->vertex == v1) || (edge->vertices[0]->vertex == v1 && edge->vertices[1]->vertex == v0)) { segment.flags.found = true; @@ -244,34 +216,59 @@ static vo @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs