[Bf-blender-cvs] [f1c0249f34c] master: Mesh: Move material indices to a generic attribute

Hans Goudey noreply at git.blender.org
Wed Aug 31 16:09:26 CEST 2022


Commit: f1c0249f34c4171ec311b5b9882e36fed5889259
Author: Hans Goudey
Date:   Wed Aug 31 09:09:01 2022 -0500
Branches: master
https://developer.blender.org/rBf1c0249f34c4171ec311b5b9882e36fed5889259

Mesh: Move material indices to a generic attribute

This patch moves material indices from the mesh `MPoly` struct to a
generic integer attribute. The builtin material index was already
exposed in geometry nodes, but this makes it a "proper" attribute
accessible with Python and visible in the "Attributes" panel.

The goals of the refactor are code simplification and memory and
performance improvements, mainly because the attribute doesn't have
to be stored and processed if there are no materials. However, until
4.0, material indices will still be read and written in the old
format, meaning there may be a temporary increase in memory usage.

Further notes:
* Completely removing the `MPoly.mat_nr` after 4.0 may require
  changes to DNA or introducing a new `MPoly` type.
* Geometry nodes regression tests didn't look at material indices,
  so the change reveals a bug in the realize instances node that I fixed.
* Access to material indices from the RNA `MeshPolygon` type is slower
  with this patch. The `material_index` attribute can be used instead.
* Cycles is changed to read from the attribute instead.
* BMesh isn't changed in this patch. Theoretically it could be though,
  to save 2 bytes per face when less than two materials are used.
* Eventually we could use a 16 bit integer attribute type instead.

Ref T95967

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

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

M	intern/cycles/blender/mesh.cpp
M	release/scripts/startup/bl_ui/properties_data_mesh.py
M	source/blender/blenkernel/BKE_mesh.h
M	source/blender/blenkernel/BKE_mesh_legacy_convert.h
M	source/blender/blenkernel/intern/customdata.cc
M	source/blender/blenkernel/intern/fluid.c
M	source/blender/blenkernel/intern/geometry_component_mesh.cc
M	source/blender/blenkernel/intern/gpencil_geom.cc
M	source/blender/blenkernel/intern/mesh.cc
M	source/blender/blenkernel/intern/mesh_boolean_convert.cc
M	source/blender/blenkernel/intern/mesh_convert.cc
M	source/blender/blenkernel/intern/mesh_legacy_convert.cc
M	source/blender/blenkernel/intern/mesh_validate.cc
M	source/blender/blenkernel/intern/pbvh.c
M	source/blender/blenkernel/intern/pbvh_intern.h
M	source/blender/blenkernel/intern/subdiv_ccg_material.c
M	source/blender/blenkernel/intern/subsurf_ccg.c
M	source/blender/blenlib/BLI_vector_set.hh
M	source/blender/bmesh/intern/bmesh_mesh_convert.cc
M	source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc
M	source/blender/draw/intern/draw_cache_impl_subdivision.cc
M	source/blender/draw/intern/mesh_extractors/extract_mesh.hh
M	source/blender/editors/mesh/meshtools.cc
M	source/blender/editors/object/object_bake.c
M	source/blender/editors/sculpt_paint/paint_image_proj.c
M	source/blender/editors/sculpt_paint/paint_utils.c
M	source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
M	source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
M	source/blender/geometry/intern/realize_instances.cc
M	source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
M	source/blender/gpu/intern/gpu_buffers.c
M	source/blender/io/alembic/exporter/abc_writer_mesh.cc
M	source/blender/io/alembic/intern/abc_reader_mesh.cc
M	source/blender/io/alembic/intern/abc_reader_mesh.h
M	source/blender/io/collada/GeometryExporter.cpp
M	source/blender/io/collada/MeshImporter.cpp
M	source/blender/io/collada/MeshImporter.h
M	source/blender/io/usd/intern/usd_reader_mesh.cc
M	source/blender/io/usd/intern/usd_reader_mesh.h
M	source/blender/io/usd/intern/usd_writer_mesh.cc
M	source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc
M	source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc
M	source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh
M	source/blender/io/wavefront_obj/importer/obj_import_mesh.cc
M	source/blender/makesdna/DNA_mesh_types.h
M	source/blender/makesdna/DNA_meshdata_types.h
M	source/blender/makesrna/intern/rna_mesh.c
M	source/blender/modifiers/intern/MOD_screw.c
M	source/blender/modifiers/intern/MOD_solidify_extrude.c
M	source/blender/modifiers/intern/MOD_solidify_nonmanifold.c
M	source/blender/nodes/geometry/nodes/node_geo_material_selection.cc
M	source/blender/nodes/geometry/nodes/node_geo_set_material.cc
M	source/blender/render/intern/bake.c
M	source/blender/render/intern/multires_bake.c

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

diff --git a/intern/cycles/blender/mesh.cpp b/intern/cycles/blender/mesh.cpp
index 63913b7cd7f..2e2dfd6583b 100644
--- a/intern/cycles/blender/mesh.cpp
+++ b/intern/cycles/blender/mesh.cpp
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: Apache-2.0
  * Copyright 2011-2022 Blender Foundation */
 
+#include <optional>
+
 #include "blender/session.h"
 #include "blender/sync.h"
 #include "blender/util.h"
@@ -879,6 +881,23 @@ static void attr_create_random_per_island(Scene *scene,
 
 /* Create Mesh */
 
+static std::optional<BL::IntAttribute> find_material_index_attribute(BL::Mesh b_mesh)
+{
+  for (BL::Attribute &b_attribute : b_mesh.attributes) {
+    if (b_attribute.domain() != BL::Attribute::domain_FACE) {
+      continue;
+    }
+    if (b_attribute.data_type() != BL::Attribute::data_type_INT) {
+      continue;
+    }
+    if (b_attribute.name() != "material_index") {
+      continue;
+    }
+    return BL::IntAttribute{b_attribute};
+  }
+  return std::nullopt;
+}
+
 static void create_mesh(Scene *scene,
                         Mesh *mesh,
                         BL::Mesh &b_mesh,
@@ -950,13 +969,22 @@ static void create_mesh(Scene *scene,
     }
   }
 
+  std::optional<BL::IntAttribute> material_indices = find_material_index_attribute(b_mesh);
+  auto get_material_index = [&](const int poly_index) -> int {
+    if (material_indices) {
+      return clamp(material_indices->data[poly_index].value(), 0, used_shaders.size() - 1);
+    }
+    return 0;
+  };
+
   /* create faces */
   if (!subdivision) {
     for (BL::MeshLoopTriangle &t : b_mesh.loop_triangles) {
-      BL::MeshPolygon p = b_mesh.polygons[t.polygon_index()];
+      const int poly_index = t.polygon_index();
+      BL::MeshPolygon p = b_mesh.polygons[poly_index];
       int3 vi = get_int3(t.vertices());
 
-      int shader = clamp(p.material_index(), 0, used_shaders.size() - 1);
+      int shader = get_material_index(poly_index);
       bool smooth = p.use_smooth() || use_loop_normals;
 
       if (use_loop_normals) {
@@ -977,9 +1005,10 @@ static void create_mesh(Scene *scene,
   else {
     vector<int> vi;
 
-    for (BL::MeshPolygon &p : b_mesh.polygons) {
+    for (int poly_index = 0; poly_index < numfaces; poly_index++) {
+      BL::MeshPolygon p = b_mesh.polygons[poly_index];
       int n = p.loop_total();
-      int shader = clamp(p.material_index(), 0, used_shaders.size() - 1);
+      int shader = get_material_index(poly_index);
       bool smooth = p.use_smooth() || use_loop_normals;
 
       vi.resize(n);
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index 8f2141ba6fc..686d455b6b4 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -580,7 +580,7 @@ class DATA_PT_mesh_attributes(MeshButtonsPanel, Panel):
         colliding_names = []
         for collection in (
                 # Built-in names.
-                {"position": None, "material_index": None, "shade_smooth": None, "normal": None, "crease": None},
+                {"position": None, "shade_smooth": None, "normal": None, "crease": None},
                 mesh.attributes,
                 mesh.uv_layers,
                 ob.vertex_groups,
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 8cf973b785c..ec6799ee995 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -6,6 +6,9 @@
  * \ingroup bke
  */
 
+#include "DNA_mesh_types.h"
+
+#include "BKE_customdata.h"
 #include "BKE_mesh_types.h"
 #include "BLI_compiler_attrs.h"
 #include "BLI_utildefines.h"
@@ -1019,6 +1022,30 @@ char *BKE_mesh_debug_info(const struct Mesh *me)
 void BKE_mesh_debug_print(const struct Mesh *me) ATTR_NONNULL(1);
 #endif
 
+/**
+ * \return The material index for each polygon. May be null.
+ * \note In C++ code, prefer using the attribute API (#MutableAttributeAccessor)/
+ */
+BLI_INLINE const int *BKE_mesh_material_indices(const Mesh *mesh)
+{
+  return (const int *)CustomData_get_layer_named(&mesh->pdata, CD_PROP_INT32, "material_index");
+}
+
+/**
+ * \return The material index for each polygon. Create the layer if it doesn't exist.
+ * \note In C++ code, prefer using the attribute API (#MutableAttributeAccessor)/
+ */
+BLI_INLINE int *BKE_mesh_material_indices_for_write(Mesh *mesh)
+{
+  int *indices = (int *)CustomData_duplicate_referenced_layer_named(
+      &mesh->pdata, CD_PROP_INT32, "material_index", mesh->totpoly);
+  if (indices) {
+    return indices;
+  }
+  return (int *)CustomData_add_layer_named(
+      &mesh->pdata, CD_PROP_INT32, CD_SET_DEFAULT, NULL, mesh->totpoly, "material_index");
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/blenkernel/BKE_mesh_legacy_convert.h b/source/blender/blenkernel/BKE_mesh_legacy_convert.h
index bbc61d5af5e..11ee86c62a7 100644
--- a/source/blender/blenkernel/BKE_mesh_legacy_convert.h
+++ b/source/blender/blenkernel/BKE_mesh_legacy_convert.h
@@ -27,6 +27,16 @@ void BKE_mesh_legacy_convert_hide_layers_to_flags(struct Mesh *mesh);
  */
 void BKE_mesh_legacy_convert_flags_to_hide_layers(struct Mesh *mesh);
 
+/**
+ * Move material indices from a generic attribute to #MPoly.
+ */
+void BKE_mesh_legacy_convert_material_indices_to_mpoly(struct Mesh *mesh);
+/**
+ * Move material indices from the #MPoly struct to a generic attributes.
+ * Only add the attribute when the indices are not all zero.
+ */
+void BKE_mesh_legacy_convert_mpoly_to_material_indices(struct Mesh *mesh);
+
 /**
  * Recreate #MFace Tessellation.
  *
diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc
index 447921b6d84..51edf8308c3 100644
--- a/source/blender/blenkernel/intern/customdata.cc
+++ b/source/blender/blenkernel/intern/customdata.cc
@@ -2375,7 +2375,7 @@ bool CustomData_merge(const CustomData *source,
 
 static bool attribute_stored_in_bmesh_flag(const StringRef name)
 {
-  return ELEM(name, ".hide_vert", ".hide_edge", ".hide_poly");
+  return ELEM(name, ".hide_vert", ".hide_edge", ".hide_poly", "material_index");
 }
 
 static CustomData shallow_copy_remove_non_bmesh_attributes(const CustomData &src)
diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c
index 0fc09803088..57b84575c84 100644
--- a/source/blender/blenkernel/intern/fluid.c
+++ b/source/blender/blenkernel/intern/fluid.c
@@ -3247,7 +3247,8 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds,
     mp_example = *mpoly;
   }
 
-  const short mp_mat_nr = mp_example.mat_nr;
+  const int *orig_material_indices = BKE_mesh_material_indices(orgmesh);
+  const short mp_mat_nr = orig_material_indices ? orig_material_indices[0] : 0;
   const char mp_flag = mp_example.flag;
 
   int i;
@@ -3358,10 +3359,12 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds,
     }
   }
 
+  int *material_indices = BKE_mesh_material_indices_for_write(me);
+
   /* Loop for triangles. */
   for (i = 0; i < num_faces; i++, mpolys++, mloops += 3) {
     /* Initialize from existing face. */
-    mpolys->mat_nr = mp_mat_nr;
+    material_indices[i] = mp_mat_nr;
     mpolys->flag = mp_flag;
 
     mpolys->loopstart = i * 3;
diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc
index 14c31da488b..ff55409d5fc 100644
--- a/source/blender/blenkernel/intern/geometry_component_mesh.cc
+++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc
@@ -842,16 +842,6 @@ static void tag_component_positions_changed(void *owner)
   }
 }
 
-static int get_material_index(const MPoly &mpoly)
-{
-  return static_cast<int>(mpoly.mat_nr);
-}
-
-static void set_material_index(MPoly &mpoly, int index)
-{
-  mpoly.mat_nr = static_cast<short>(std::clamp(index, 0, SHRT_MAX));
-}
-
 static bool get_shade_smooth(const MPoly &mpoly)
 {
   return mpoly.flag & ME_SMOOTH;
@@ -1201,18 +1191,17 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
                                            make_array_write_attribute<int>,
                                            nullptr);
 
-  static BuiltinCustomDataLayerProvider material_index(
-      "material_index",
-      ATTR_DOMAIN_FACE,
-      CD_PROP_INT32,
-      CD_MPOLY,
-      BuiltinAttributeProvider::NonCreatable,
-      BuiltinAttributeProvider::Writable,
-      BuiltinAttributeProvider::NonDeletable,
-      face_access,
-      make_derived_read_attribute<MPoly, int, get_material_index>,
-      make_derived_write_attribute<MPoly, int, get_material_index, set_material_index>,
-      nullptr);
+  static BuiltinCustomDataLayerProvider material_index("material_index",
+                                                       ATTR_DOMAIN_FACE,
+                                                       CD_PROP_INT32,
+                                                       CD_PROP_INT32,
+                                                       BuiltinAttributeProvider::Creatable,
+                                                       BuiltinAttributeProvider::Writable,
+                                                       BuiltinAttributeProvider::Deletable,
+                                                       face_access,
+                                                       make_array_read_attribute<int>,
+                                                       make_array_write_attribute<int>,
+                                                       nullptr);
 
   static BuiltinCustomDataLayerProvider shade_smooth(
       "shade_smooth",
diff --git a/source/blender/blenkernel/intern/gpencil_geom.cc b/source/blender/blenkernel/intern/gpencil_geom.cc
index f7d84b8dc84..ce2e106c664 100644
--- a/source/blender/blenkernel/intern/gpencil_geom.cc
+++ b/source/blender/blenkernel/intern/gpencil_geom.cc
@@ -35,6 +35,7 @@
 
 #include "BLT_translation.h"
 
+#include "BKE_attribute.hh"
 #include "BKE_context.h"
 #include "BKE_deform.h"
 #include "BKE_gpencil.h"
@@ -2662,6 +2663,8 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
                               const bool use_faces,
                               cons

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list