Commit: b2d30c95f8954082a382dfa36c7a2704de33a8ef Author: Martijn Versteegh Date: Tue Dec 6 13:59:19 2022 +0100 Branches: refactor-mesh-uv-map-generic https://developer.blender.org/rBb2d30c95f8954082a382dfa36c7a2704de33a8ef
Merge branch 'master' into refactor-mesh-uv-map-generic =================================================================== =================================================================== diff --cc release/scripts/addons index 63e1e6227af,0b0052bd53a..90c87dd771e --- a/release/scripts/addons +++ b/release/scripts/addons @@@ -1,1 -1,1 +1,1 @@@ - Subproject commit 63e1e6227af42c1090fadc116e19b604d734a56c -Subproject commit 0b0052bd53ad8249ed07dfb87705c338af698bde ++Subproject commit 90c87dd771e027e0ffa157a0e294399bfd605d99 diff --cc source/blender/blenkernel/BKE_uv_islands.hh index 00000000000,406ecf39b71..3dc842bd510 mode 000000,100644..100644 --- a/source/blender/blenkernel/BKE_uv_islands.hh +++ b/source/blender/blenkernel/BKE_uv_islands.hh @@@ -1,0 -1,746 +1,746 @@@ + /* SPDX-License-Identifier: GPL-2.0-or-later */ + + #pragma once + + #include <fstream> + #include <optional> + + #include "BLI_array.hh" + #include "BLI_edgehash.h" + #include "BLI_float3x3.hh" + #include "BLI_map.hh" + #include "BLI_math.h" + #include "BLI_math_vec_types.hh" + #include "BLI_rect.h" + #include "BLI_vector.hh" + #include "BLI_vector_list.hh" + + #include "DNA_meshdata_types.h" + + namespace blender::bke::uv_islands { + + struct MeshEdge; + struct MeshPrimitive; + struct UVBorder; + struct UVEdge; + struct UVIslands; + struct UVIslandsMask; + struct UVPrimitive; + struct UVPrimitiveEdge; + struct UVVertex; + + struct MeshVertex { + int64_t v; + Vector<MeshEdge *> edges; + }; + + struct MeshUVVert { + MeshVertex *vertex; + float2 uv; + int64_t loop; + }; + + struct MeshEdge { + MeshVertex *vert1; + MeshVertex *vert2; + Vector<MeshPrimitive *> primitives; + }; + + /** Represents a triangle in 3d space (MLoopTri) */ + struct MeshPrimitive { + int64_t index; + int64_t poly; + Vector<MeshEdge *, 3> edges; + Vector<MeshUVVert, 3> vertices; + + /** + * UV island this primitive belongs to. This is used to speed up the initial uv island + * extraction, but should not be used when extending uv islands. + */ + int64_t uv_island_id; + + MeshUVVert *get_other_uv_vertex(const MeshVertex *v1, const MeshVertex *v2) + { + BLI_assert(vertices[0].vertex == v1 || vertices[1].vertex == v1 || vertices[2].vertex == v1); + BLI_assert(vertices[0].vertex == v2 || vertices[1].vertex == v2 || vertices[2].vertex == v2); + for (MeshUVVert &uv_vertex : vertices) { + if (uv_vertex.vertex != v1 && uv_vertex.vertex != v2) { + return &uv_vertex; + } + } + return nullptr; + } + + rctf uv_bounds() const; + + bool has_shared_uv_edge(const MeshPrimitive *other) const + { + int shared_uv_verts = 0; + for (const MeshUVVert &vert : vertices) { + for (const MeshUVVert &other_vert : other->vertices) { + if (vert.uv == other_vert.uv) { + shared_uv_verts += 1; + } + } + } + return shared_uv_verts >= 2; + } + }; + + /** + * MeshData contains input geometry data converted in a list of primitives, edges and vertices for + * quick access for both local space and uv space. + */ + struct MeshData { + public: + const MLoopTri *looptri; + const int64_t looptri_len; + const int64_t vert_len; + const MLoop *mloop; - const MLoopUV *mloopuv; ++ const float2 *mloopuv; + + public: + Vector<MeshPrimitive> primitives; + Vector<MeshEdge> edges; + Vector<MeshVertex> vertices; + /** Total number of uv islands detected. */ + int64_t uv_island_len; + + explicit MeshData(const MLoopTri *looptri, + const int64_t looptri_len, + const int64_t vert_len, + const MLoop *mloop, - const MLoopUV *mloopuv) ++ const float2 *mloopuv) + : looptri(looptri), + looptri_len(looptri_len), + vert_len(vert_len), + mloop(mloop), + mloopuv(mloopuv) + { + init_vertices(); + init_primitives(); + init_edges(); + init_primitive_uv_island_ids(); + } + + void init_vertices() + { + vertices.reserve(vert_len); + for (int64_t i = 0; i < vert_len; i++) { + MeshVertex vert; + vert.v = i; + vertices.append(vert); + } + } + + void init_primitives() + { + primitives.reserve(looptri_len); + for (int64_t i = 0; i < looptri_len; i++) { + const MLoopTri &tri = looptri[i]; + MeshPrimitive primitive; + primitive.index = i; + primitive.poly = tri.poly; + + for (int j = 0; j < 3; j++) { + MeshUVVert uv_vert; + uv_vert.loop = tri.tri[j]; + uv_vert.vertex = &vertices[mloop[uv_vert.loop].v]; - uv_vert.uv = mloopuv[uv_vert.loop].uv; ++ uv_vert.uv = mloopuv[uv_vert.loop]; + primitive.vertices.append(uv_vert); + } + primitives.append(primitive); + } + } + + void init_edges() + { + edges.reserve(looptri_len * 2); + EdgeHash *eh = BLI_edgehash_new_ex(__func__, looptri_len * 3); + for (int64_t i = 0; i < looptri_len; i++) { + const MLoopTri &tri = looptri[i]; + MeshPrimitive &primitive = primitives[i]; + for (int j = 0; j < 3; j++) { + int v1 = mloop[tri.tri[j]].v; + int v2 = mloop[tri.tri[(j + 1) % 3]].v; + /* TODO: Use lookup_ptr to be able to store edge 0. */ + void *v = BLI_edgehash_lookup(eh, v1, v2); + int64_t edge_index; + if (v == nullptr) { + edge_index = edges.size(); + BLI_edgehash_insert(eh, v1, v2, POINTER_FROM_INT(edge_index + 1)); + MeshEdge edge; + edge.vert1 = &vertices[v1]; + edge.vert2 = &vertices[v2]; + edges.append(edge); + MeshEdge *edge_ptr = &edges.last(); + vertices[v1].edges.append(edge_ptr); + vertices[v2].edges.append(edge_ptr); + } + else { + edge_index = POINTER_AS_INT(v) - 1; + } + + MeshEdge *edge = &edges[edge_index]; + edge->primitives.append(&primitive); + primitive.edges.append(edge); + } + } + BLI_edgehash_free(eh, nullptr); + } + + static const int64_t INVALID_UV_ISLAND_ID = -1; + /** + * NOTE: doesn't support weird topology where unconnected mesh primitives share the same uv + * island. For a accurate implementation we should use implement an uv_prim_lookup. + */ + static void extract_uv_neighbors(Vector<MeshPrimitive *> &prims_to_add, MeshPrimitive *primitive) + { + for (MeshEdge *edge : primitive->edges) { + for (MeshPrimitive *other_primitive : edge->primitives) { + if (primitive == other_primitive) { + continue; + } + if (other_primitive->uv_island_id != MeshData::INVALID_UV_ISLAND_ID) { + continue; + } + + if (primitive->has_shared_uv_edge(other_primitive)) { + prims_to_add.append(other_primitive); + } + } + } + } + + void init_primitive_uv_island_ids() + { + for (MeshPrimitive &primitive : primitives) { + primitive.uv_island_id = INVALID_UV_ISLAND_ID; + } + + int64_t uv_island_id = 0; + Vector<MeshPrimitive *> prims_to_add; + for (MeshPrimitive &primitive : primitives) { + /* Early exit when uv island id is already extracted during uv neighbor extractions. */ + if (primitive.uv_island_id != INVALID_UV_ISLAND_ID) { + continue; + } + + prims_to_add.append(&primitive); + while (!prims_to_add.is_empty()) { + MeshPrimitive *primitive = prims_to_add.pop_last(); + primitive->uv_island_id = uv_island_id; + extract_uv_neighbors(prims_to_add, primitive); + } + uv_island_id++; + } + uv_island_len = uv_island_id; + } + }; + + struct UVVertex { + MeshVertex *vertex; + /* Position in uv space. */ + float2 uv; + + /* uv edges that share this UVVertex. */ + Vector<UVEdge *> uv_edges; + + struct { + bool is_border : 1; + bool is_extended : 1; + } flags; + + explicit UVVertex() + { + flags.is_border = false; + flags.is_extended = false; + } + + explicit UVVertex(const MeshUVVert &vert) : vertex(vert.vertex), uv(vert.uv) + { + flags.is_border = false; + flags.is_extended = false; + } + }; + + struct UVEdge { + std::array<UVVertex *, 2> vertices; + Vector<UVPrimitive *, 2> uv_primitives; + + bool has_shared_edge(const MeshUVVert &v1, const MeshUVVert &v2) const + { + return (vertices[0]->uv == v1.uv && vertices[1]->uv == v2.uv) || + (vertices[0]->uv == v2.uv && vertices[1]->uv == v1.uv); + } + + bool has_shared_edge(const UVVertex &v1, const UVVertex &v2) const + { + return (vertices[0]->uv == v1.uv && vertices[1]->uv == v2.uv) || + (vertices[0]->uv == v2.uv && vertices[1]->uv == v1.uv); + } + + bool has_shared_edge(const UVEdge &other) const + { + return has_shared_edge(*other.vertices[0], *other.vertices[1]); + } + + bool has_same_vertices(const MeshVertex &vert1, const MeshVertex &vert2) const + { + return (vertices[0]->vertex == &vert1 && vertices[1]->vertex == &vert2) || + (vertices[0]->vertex == &vert2 && vertices[1]->vertex == &vert1); + } + + bool has_same_uv_vertices(const UVEdge &other) const + { + return has_shared_edge(other) && + has_same_vertices(*other.vertices[0]->vertex, *other.vertices[1]->vertex); + ; + } + + bool has_same_vertices(const MeshEdge &edge) const + { + return has_same_vertices(*edge.vert1, *edge.vert2); + } + + bool is_border_edge() const + { + return uv_primitives.size() == 1; + } + + void append_to_uv_vertices() + { + for (UVVertex *vertex : vertices) { + vertex->uv_edges.append_non_duplicates(this); + } + } + + UVVertex *get_other_uv_vertex(const MeshVertex *vertex) + { + if (vertices[0]->vertex == vertex) { + return vertices[1]; + } + return vertices[0]; + } + }; + + struct UVPrimitive { + /** + * Index of the primitive in the original mesh. + */ + MeshPrimitive *primitive; + Vector<UVEdge *, 3> edges; + + explicit UVPrimitive(MeshPrimitive *primitive) : primitive(primitive) + { + } + + void append_to_uv_edges() + { + for (UVEdge *uv_edge : edges) { + uv_edge->uv_primitives.append_non_du @@ 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