[Bf-blender-cvs] [5dd77444867] temp-T97352-3d-texturing-seam-bleeding-b2: Fix compilation of VALIDATION checks.

Jeroen Bakker noreply at git.blender.org
Mon Oct 10 13:48:25 CEST 2022


Commit: 5dd77444867d1b944f37f5a7a75c7ee29bb771a5
Author: Jeroen Bakker
Date:   Wed Aug 3 13:28:05 2022 +0200
Branches: temp-T97352-3d-texturing-seam-bleeding-b2
https://developer.blender.org/rB5dd77444867d1b944f37f5a7a75c7ee29bb771a5

Fix compilation of VALIDATION checks.

===================================================================

A	source/blender/blenkernel/BKE_uv_islands.hh

===================================================================

diff --git a/source/blender/blenkernel/BKE_uv_islands.hh b/source/blender/blenkernel/BKE_uv_islands.hh
new file mode 100644
index 00000000000..6fdd3976d74
--- /dev/null
+++ b/source/blender/blenkernel/BKE_uv_islands.hh
@@ -0,0 +1,867 @@
+
+/* 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"
+
+#include "PIL_time_utildefines.h"
+
+namespace blender::bke::uv_islands {
+/*
+ * When enabled various parts of the code would generate an SVG file to visual see how the
+ * algorithm makes decisions.
+ *
+ * TODO: These will be removed before this patch will land in master.
+ */
+//#define DEBUG_SVG
+//#define VALIDATE
+
+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;
+
+ 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)
+      : looptri(looptri),
+        looptri_len(looptri_len),
+        vert_len(vert_len),
+        mloop(mloop),
+        mloopuv(mloopuv)
+  {
+    TIMEIT_START(init_mesh_data);
+    init_vertices();
+    init_primitives();
+    init_edges();
+    init_primitive_uv_island_ids();
+
+#ifdef VALIDATE
+    for (const MeshVertex &v : vertices) {
+      printf("Vert {v%lld}\n", v.v);
+      for (const MeshEdge *e : v.edges) {
+        printf("-Edge {v%lld v%lld}\n", e->vert1->v, e->vert2->v);
+        for (const MeshPrimitive *p : e->primitives) {
+          printf(" -Prim {p%lld, v%lld v%lld v%lld}\n",
+                 p->index,
+                 p->vertices[0].vertex->v,
+                 p->vertices[1].vertex->v,
+                 p->vertices[2].vertex->v);
+        }
+      }
+    }
+#endif
+    TIMEIT_END(init_mesh_data);
+  }
+
+  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;
+        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 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list