[Bf-blender-cvs] [b9177014b6f] master: 3D Texturing: Replace pointers with indexes in pbvh_uv_islands

Jeroen Bakker noreply at git.blender.org
Thu Jan 12 08:36:08 CET 2023


Commit: b9177014b6f0081534635347153a0a9380a1d018
Author: Jeroen Bakker
Date:   Thu Jan 12 08:35:14 2023 +0100
Branches: master
https://developer.blender.org/rBb9177014b6f0081534635347153a0a9380a1d018

3D Texturing: Replace pointers with indexes in pbvh_uv_islands

Replace the pointers in the MeshEdge with indexes, removing MeshPrimitive and MeshVertex.

Code cleanup proposed by the geometry nodes to make the data structures more reusable by
other areas of Blender as well. Old implementation was to focused to the texture painting.

Initial the idea was to do the same with the data structures in UVIslands, but there some
concerns were raised that requires a different design than expected from a clean-up patch.

Concerns raised about converting UVIslands:
* Maps between UVPrimitive, UVEdge and UVVertex will be stored inside the UVIsland.
   During UVIsland extraction detected islands can be merged. When they are merged all
   Indexes should be updated.
* It is not possible to pre-allocate all buffers as they grow, what will lead to more re-allocations. The current
   implementation uses a VectorList to ensure that re-allocations don't require the data to be
   moved to the newly allocated memory. We could store some information about last used
   sizes in runtime data to reduce the re-allocation overhead.
* Solution would require index based access inside a VectorList, which might increase the
   complexity.
* UVIslands during 3d texturing is used as intermediate data, the final data is stored as PackedPixelRows.
   We could proceed converting UVIslands as well, but that would lower the performance noticeably.
   3D texturing has performance requirements, so when doing so we should make sure that
   it matches that as well.

Reviewed By: HooglyBoogly

Maniphest Tasks: T101740

Differential Revision: https://developer.blender.org/D16752

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

M	source/blender/blenkernel/BKE_pbvh_pixels.hh
M	source/blender/blenkernel/intern/pbvh_pixels.cc
M	source/blender/blenkernel/intern/pbvh_uv_islands.cc
M	source/blender/blenkernel/intern/pbvh_uv_islands.hh

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

diff --git a/source/blender/blenkernel/BKE_pbvh_pixels.hh b/source/blender/blenkernel/BKE_pbvh_pixels.hh
index a6b5bb565c5..b6e006805ec 100644
--- a/source/blender/blenkernel/BKE_pbvh_pixels.hh
+++ b/source/blender/blenkernel/BKE_pbvh_pixels.hh
@@ -51,7 +51,7 @@ struct PaintGeometryPrimitives {
 
   int64_t mem_size() const
   {
-    return size() * sizeof(int3);
+    return this->vert_indices.as_span().size_in_bytes();
   }
 };
 
diff --git a/source/blender/blenkernel/intern/pbvh_pixels.cc b/source/blender/blenkernel/intern/pbvh_pixels.cc
index 884da8b89f0..39651349ae9 100644
--- a/source/blender/blenkernel/intern/pbvh_pixels.cc
+++ b/source/blender/blenkernel/intern/pbvh_pixels.cc
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-or-later
  * Copyright 2022 Blender Foundation. All rights reserved. */
 
+#include "BKE_attribute.hh"
 #include "BKE_customdata.h"
 #include "BKE_mesh.h"
 #include "BKE_mesh_mapping.h"
@@ -105,10 +106,10 @@ static void update_geom_primitives(PBVH &pbvh, const uv_islands::MeshData &mesh_
 {
   PBVHData &pbvh_data = BKE_pbvh_pixels_data_get(pbvh);
   pbvh_data.clear_data();
-  for (const uv_islands::MeshPrimitive &mesh_primitive : mesh_data.primitives) {
-    pbvh_data.geom_primitives.append(int3(mesh_primitive.vertices[0].vertex->v,
-                                          mesh_primitive.vertices[1].vertex->v,
-                                          mesh_primitive.vertices[2].vertex->v));
+  for (const MLoopTri &looptri : mesh_data.looptris) {
+    pbvh_data.geom_primitives.append(int3(mesh_data.loops[looptri.tri[0]].v,
+                                          mesh_data.loops[looptri.tri[1]].v,
+                                          mesh_data.loops[looptri.tri[2]].v));
   }
 }
 
@@ -134,7 +135,7 @@ struct UVPrimitiveLookup {
       for (VectorList<uv_islands::UVPrimitive>::UsedVector &uv_primitives :
            uv_island.uv_primitives) {
         for (uv_islands::UVPrimitive &uv_primitive : uv_primitives) {
-          lookup[uv_primitive.primitive->index].append_as(Entry(&uv_primitive, uv_island_index));
+          lookup[uv_primitive.primitive_i].append_as(Entry(&uv_primitive, uv_island_index));
         }
       }
       uv_island_index++;
@@ -143,11 +144,11 @@ struct UVPrimitiveLookup {
 };
 
 struct EncodePixelsUserData {
+  const uv_islands::MeshData *mesh_data;
   Image *image;
   ImageUser *image_user;
   PBVH *pbvh;
   Vector<PBVHNode *> *nodes;
-  const float2 *ldata_uv;
   const uv_islands::UVIslandsMask *uv_masks;
   /** Lookup to retrieve the UV primitives based on the primitive index. */
   const UVPrimitiveLookup *uv_primitive_lookup;
@@ -158,6 +159,7 @@ static void do_encode_pixels(void *__restrict userdata,
                              const TaskParallelTLS *__restrict /*tls*/)
 {
   EncodePixelsUserData *data = static_cast<EncodePixelsUserData *>(userdata);
+  const uv_islands::MeshData &mesh_data = *data->mesh_data;
   Image *image = data->image;
   ImageUser image_user = *data->image_user;
   PBVHNode *node = (*data->nodes)[n];
@@ -183,9 +185,9 @@ static void do_encode_pixels(void *__restrict userdata,
            data->uv_primitive_lookup->lookup[geom_prim_index]) {
         uv_islands::UVBorder uv_border = entry.uv_primitive->extract_border();
         float2 uvs[3] = {
-            entry.uv_primitive->get_uv_vertex(0)->uv - tile_offset,
-            entry.uv_primitive->get_uv_vertex(1)->uv - tile_offset,
-            entry.uv_primitive->get_uv_vertex(2)->uv - tile_offset,
+            entry.uv_primitive->get_uv_vertex(mesh_data, 0)->uv - tile_offset,
+            entry.uv_primitive->get_uv_vertex(mesh_data, 1)->uv - tile_offset,
+            entry.uv_primitive->get_uv_vertex(mesh_data, 2)->uv - tile_offset,
         };
         const float minv = clamp_f(min_fff(uvs[0].y, uvs[1].y, uvs[2].y), 0.0f, 1.0f);
         const int miny = floor(minv * image_buffer->y);
@@ -355,16 +357,16 @@ static void update_pixels(PBVH *pbvh, Mesh *mesh, Image *image, ImageUser *image
     return;
   }
 
-  const float2 *ldata_uv = static_cast<const float2 *>(
-      CustomData_get_layer(&mesh->ldata, CD_PROP_FLOAT2));
-  if (ldata_uv == nullptr) {
+  const StringRef active_uv_name = CustomData_get_active_layer_name(&mesh->ldata, CD_PROP_FLOAT2);
+  if (active_uv_name.is_empty()) {
     return;
   }
 
-  uv_islands::MeshData mesh_data({pbvh->looptri, pbvh->totprim},
-                                 {pbvh->mloop, mesh->totloop},
-                                 pbvh->totvert,
-                                 {ldata_uv, mesh->totloop});
+  const AttributeAccessor attributes = mesh->attributes();
+  const VArraySpan<float2> uv_map = attributes.lookup<float2>(active_uv_name, ATTR_DOMAIN_CORNER);
+
+  uv_islands::MeshData mesh_data(
+      {pbvh->looptri, pbvh->totprim}, {pbvh->mloop, mesh->totloop}, pbvh->totvert, uv_map);
   uv_islands::UVIslands islands(mesh_data);
 
   uv_islands::UVIslandsMask uv_masks;
@@ -380,20 +382,20 @@ static void update_pixels(PBVH *pbvh, Mesh *mesh, Image *image, ImageUser *image
                       ushort2(tile_buffer->x, tile_buffer->y));
     BKE_image_release_ibuf(image, tile_buffer, nullptr);
   }
-  uv_masks.add(islands);
+  uv_masks.add(mesh_data, islands);
   uv_masks.dilate(image->seam_margin);
 
   islands.extract_borders();
-  islands.extend_borders(uv_masks);
+  islands.extend_borders(mesh_data, uv_masks);
   update_geom_primitives(*pbvh, mesh_data);
 
   UVPrimitiveLookup uv_primitive_lookup(mesh_data.looptris.size(), islands);
 
   EncodePixelsUserData user_data;
+  user_data.mesh_data = &mesh_data;
   user_data.pbvh = pbvh;
   user_data.image = image;
   user_data.image_user = image_user;
-  user_data.ldata_uv = ldata_uv;
   user_data.nodes = &nodes_to_update;
   user_data.uv_primitive_lookup = &uv_primitive_lookup;
   user_data.uv_masks = &uv_masks;
diff --git a/source/blender/blenkernel/intern/pbvh_uv_islands.cc b/source/blender/blenkernel/intern/pbvh_uv_islands.cc
index 5f4a888805e..aac61750d47 100644
--- a/source/blender/blenkernel/intern/pbvh_uv_islands.cc
+++ b/source/blender/blenkernel/intern/pbvh_uv_islands.cc
@@ -28,27 +28,40 @@ static void uv_primitive_append_to_uv_vertices(UVPrimitive &uv_primitive)
 }
 
 /* -------------------------------------------------------------------- */
-/** \name MeshPrimitive
+/** \name Mesh Primitives
  * \{ */
 
-MeshUVVert *MeshPrimitive::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 (!ELEM(uv_vertex.vertex, v1, v2)) {
-      return &uv_vertex;
+int primitive_get_other_uv_vertex(const MeshData &mesh_data,
+                                  const MLoopTri &looptri,
+                                  const int v1,
+                                  const int v2)
+{
+  const Span<MLoop> mesh_loops = mesh_data.loops;
+  BLI_assert(ELEM(v1,
+                  mesh_loops[looptri.tri[0]].v,
+                  mesh_loops[looptri.tri[1]].v,
+                  mesh_loops[looptri.tri[2]].v));
+  BLI_assert(ELEM(v2,
+                  mesh_loops[looptri.tri[0]].v,
+                  mesh_loops[looptri.tri[1]].v,
+                  mesh_loops[looptri.tri[2]].v));
+  for (const int loop : looptri.tri) {
+    const int vert = mesh_loops[loop].v;
+    if (vert != v1 && vert != v2) {
+      return vert;
     }
   }
-  return nullptr;
+  return -1;
 }
 
-bool MeshPrimitive::has_shared_uv_edge(const MeshPrimitive *other) const
+bool primitive_has_shared_uv_edge(const Span<float2> uv_map,
+                                  const MLoopTri &looptri,
+                                  const MLoopTri &other)
 {
   int shared_uv_verts = 0;
-  for (const MeshUVVert &vert : vertices) {
-    for (const MeshUVVert &other_vert : other->vertices) {
-      if (vert.uv == other_vert.uv) {
+  for (const int loop : looptri.tri) {
+    for (const int other_loop : other.tri) {
+      if (uv_map[loop] == uv_map[other_loop]) {
         shared_uv_verts += 1;
       }
     }
@@ -56,33 +69,34 @@ bool MeshPrimitive::has_shared_uv_edge(const MeshPrimitive *other) const
   return shared_uv_verts >= 2;
 }
 
-static const MeshUVVert &get_uv_vert(const MeshPrimitive &mesh_primitive, const MeshVertex *vert)
+static int get_uv_loop(const MeshData &mesh_data, const MLoopTri &looptri, const int vert)
 {
-  for (const MeshUVVert &uv_vert : mesh_primitive.vertices) {
-    if (uv_vert.vertex == vert) {
-      return uv_vert;
+  for (const int loop : looptri.tri) {
+    if (mesh_data.loops[loop].v == vert) {
+      return loop;
     }
   }
   BLI_assert_unreachable();
-  return mesh_primitive.vertices[0];
+  return looptri.tri[0];
 }
 
-static bool has_vertex(const MeshPrimitive &mesh_primitive, const MeshVertex &mesh_vertex)
+static bool has_vertex(const MeshData &mesh_data, const MLoopTri &looptri, const int vert)
 {
   for (int i = 0; i < 3; i++) {
-    if (mesh_primitive.vertices[i].vertex == &mesh_vertex) {
+    const int vert_i = mesh_data.loops[looptri.tri[i]].v;
+    if (vert_i == vert) {
       return true;
     }
   }
   return false;
 }
 
-rctf MeshPrimitive::uv_bounds() const
+rctf primitive_uv_bounds(const MLoopTri &looptri, const Span<float2> uv_map)
 {
   rctf result;
   BLI_rctf_init_minmax(&result);
-  for (const MeshUVVert &uv_vertex : vertices) {
-    BLI_rctf_do_minmax_v(&result, uv_vertex.uv);
+  for (const int loop : looptri.tri) {
+    BLI_rctf_do_minmax_v(&result, uv_map[loop]);
   }
   return result;
 }
@@ -93,43 +107,13 @@ rctf MeshPrimitive::uv_bounds() const
 /** \name MeshData
  * \{ */
 
-static void mesh_data_init_vertices(MeshData &mesh_data)
-{
-  mesh_data.vertices.reserve(mesh_data.verts_num);
-  for (int64_t i = 0; i < mesh_data.verts_num; i++) {
-    MeshVertex vert;
-    vert.v = i;
-    mesh_data.vertices.append(vert);
-  }
-}
-
-static void mesh_data_init_primitives(MeshData &mesh_data)
-{
-  mesh_data.primitives.reserve(mesh_data.looptris.size());
-  for (int64_t i = 0; i < mesh_data.looptris.size(); i++) {
-    const MLoopTri &tri = mesh_data.looptris[i];
-    MeshPri

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list