Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2022-08-31 17:09:01 +0300
committerHans Goudey <h.goudey@me.com>2022-08-31 17:09:01 +0300
commitf1c0249f34c4171ec311b5b9882e36fed5889259 (patch)
tree7dd630c9301b8dd468c8279e8c446c62824fb6d6 /source/blender/blenkernel/intern
parent3e73afb5360592fe2bf43419e216035ea3c281f9 (diff)
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
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r--source/blender/blenkernel/intern/customdata.cc2
-rw-r--r--source/blender/blenkernel/intern/fluid.c7
-rw-r--r--source/blender/blenkernel/intern/geometry_component_mesh.cc33
-rw-r--r--source/blender/blenkernel/intern/gpencil_geom.cc8
-rw-r--r--source/blender/blenkernel/intern/mesh.cc95
-rw-r--r--source/blender/blenkernel/intern/mesh_boolean_convert.cc21
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.cc10
-rw-r--r--source/blender/blenkernel/intern/mesh_legacy_convert.cc39
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.cc31
-rw-r--r--source/blender/blenkernel/intern/pbvh.c31
-rw-r--r--source/blender/blenkernel/intern/pbvh_intern.h2
-rw-r--r--source/blender/blenkernel/intern/subdiv_ccg_material.c6
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c6
13 files changed, 184 insertions, 107 deletions
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,
const bool use_vgroups)
{
+ using namespace blender;
+ using namespace blender::bke;
if (ELEM(nullptr, ob_gp, ob_mesh) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == nullptr)) {
return false;
}
@@ -2708,12 +2711,15 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
bGPDframe *gpf_fill = BKE_gpencil_layer_frame_get(
gpl_fill, scene->r.cfra + frame_offset, GP_GETFRAME_ADD_NEW);
int i;
+
+ const VArray<int> mesh_material_indices = mesh_attributes(*me_eval).lookup_or_default<int>(
+ "material_index", ATTR_DOMAIN_FACE, 0);
for (i = 0; i < mpoly_len; i++) {
const MPoly *mp = &mpoly[i];
/* Find material. */
int mat_idx = 0;
- Material *ma = BKE_object_material_get(ob_mesh, mp->mat_nr + 1);
+ Material *ma = BKE_object_material_get(ob_mesh, mesh_material_indices[i] + 1);
make_element_name(
ob_mesh->id.name + 2, (ma != nullptr) ? ma->id.name + 2 : "Fill", 64, element_name);
mat_idx = BKE_gpencil_material_find_index_by_name_prefix(ob_gp, element_name);
diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc
index 0a5eddfd319..b44a956eec4 100644
--- a/source/blender/blenkernel/intern/mesh.cc
+++ b/source/blender/blenkernel/intern/mesh.cc
@@ -33,6 +33,7 @@
#include "BLI_task.hh"
#include "BLI_utildefines.h"
#include "BLI_vector.hh"
+#include "BLI_virtual_array.hh"
#include "BLT_translation.h"
@@ -253,6 +254,7 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
Set<std::string> names_to_skip;
if (!BLO_write_is_undo(writer)) {
BKE_mesh_legacy_convert_hide_layers_to_flags(mesh);
+ BKE_mesh_legacy_convert_material_indices_to_mpoly(mesh);
/* When converting to the old mesh format, don't save redundant attributes. */
names_to_skip.add_multiple_new({".hide_vert", ".hide_edge", ".hide_poly"});
}
@@ -341,6 +343,7 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id)
if (!BLO_read_data_is_undo(reader)) {
BKE_mesh_legacy_convert_flags_to_hide_layers(mesh);
+ BKE_mesh_legacy_convert_mpoly_to_material_indices(mesh);
}
/* We don't expect to load normals from files, since they are derived data. */
@@ -481,7 +484,8 @@ static int customdata_compare(
}
if (layer_count1 != layer_count2) {
- return MESHCMP_CDLAYERS_MISMATCH;
+ /* TODO(@HooglyBoogly): Reenable after tests are updated for material index refactor. */
+ // return MESHCMP_CDLAYERS_MISMATCH;
}
l1 = c1->layers;
@@ -1416,61 +1420,57 @@ void BKE_mesh_assign_object(Main *bmain, Object *ob, Mesh *me)
void BKE_mesh_material_index_remove(Mesh *me, short index)
{
- MPoly *mp;
- MFace *mf;
- int i;
-
- for (mp = me->mpoly, i = 0; i < me->totpoly; i++, mp++) {
- if (mp->mat_nr && mp->mat_nr >= index) {
- mp->mat_nr--;
- }
+ using namespace blender;
+ using namespace blender::bke;
+ MutableAttributeAccessor attributes = mesh_attributes_for_write(*me);
+ AttributeWriter<int> material_indices = attributes.lookup_for_write<int>("material_index");
+ if (!material_indices) {
+ return;
}
-
- for (mf = me->mface, i = 0; i < me->totface; i++, mf++) {
- if (mf->mat_nr && mf->mat_nr >= index) {
- mf->mat_nr--;
+ if (material_indices.domain != ATTR_DOMAIN_FACE) {
+ BLI_assert_unreachable();
+ return;
+ }
+ MutableVArraySpan<int> indices_span(material_indices.varray);
+ for (const int i : indices_span.index_range()) {
+ if (indices_span[i] > 0 && indices_span[i] > index) {
+ indices_span[i]--;
}
}
+ indices_span.save();
+ material_indices.finish();
+
+ BKE_mesh_tessface_clear(me);
}
bool BKE_mesh_material_index_used(Mesh *me, short index)
{
- MPoly *mp;
- MFace *mf;
- int i;
-
- for (mp = me->mpoly, i = 0; i < me->totpoly; i++, mp++) {
- if (mp->mat_nr == index) {
- return true;
- }
- }
-
- for (mf = me->mface, i = 0; i < me->totface; i++, mf++) {
- if (mf->mat_nr == index) {
- return true;
- }
+ using namespace blender;
+ using namespace blender::bke;
+ const AttributeAccessor attributes = mesh_attributes(*me);
+ const VArray<int> material_indices = attributes.lookup_or_default<int>(
+ "material_index", ATTR_DOMAIN_FACE, 0);
+ if (material_indices.is_single()) {
+ return material_indices.get_internal_single() == index;
}
-
- return false;
+ const VArraySpan<int> indices_span(material_indices);
+ return indices_span.contains(index);
}
void BKE_mesh_material_index_clear(Mesh *me)
{
- MPoly *mp;
- MFace *mf;
- int i;
-
- for (mp = me->mpoly, i = 0; i < me->totpoly; i++, mp++) {
- mp->mat_nr = 0;
- }
+ using namespace blender;
+ using namespace blender::bke;
+ MutableAttributeAccessor attributes = mesh_attributes_for_write(*me);
+ attributes.remove("material_index");
- for (mf = me->mface, i = 0; i < me->totface; i++, mf++) {
- mf->mat_nr = 0;
- }
+ BKE_mesh_tessface_clear(me);
}
void BKE_mesh_material_remap(Mesh *me, const uint *remap, uint remap_len)
{
+ using namespace blender;
+ using namespace blender::bke;
const short remap_len_short = (short)remap_len;
#define MAT_NR_REMAP(n) \
@@ -1490,10 +1490,21 @@ void BKE_mesh_material_remap(Mesh *me, const uint *remap, uint remap_len)
}
}
else {
- int i;
- for (i = 0; i < me->totpoly; i++) {
- MAT_NR_REMAP(me->mpoly[i].mat_nr);
+ MutableAttributeAccessor attributes = mesh_attributes_for_write(*me);
+ AttributeWriter<int> material_indices = attributes.lookup_for_write<int>("material_index");
+ if (!material_indices) {
+ return;
+ }
+ if (material_indices.domain != ATTR_DOMAIN_FACE) {
+ BLI_assert_unreachable();
+ return;
+ }
+ MutableVArraySpan<int> indices_span(material_indices.varray);
+ for (const int i : indices_span.index_range()) {
+ MAT_NR_REMAP(indices_span[i]);
}
+ indices_span.save();
+ material_indices.finish();
}
#undef MAT_NR_REMAP
diff --git a/source/blender/blenkernel/intern/mesh_boolean_convert.cc b/source/blender/blenkernel/intern/mesh_boolean_convert.cc
index 903198e249a..fb4a9248d8d 100644
--- a/source/blender/blenkernel/intern/mesh_boolean_convert.cc
+++ b/source/blender/blenkernel/intern/mesh_boolean_convert.cc
@@ -9,6 +9,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
+#include "BKE_attribute.hh"
#include "BKE_customdata.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
@@ -23,6 +24,7 @@
#include "BLI_mesh_intersect.hh"
#include "BLI_span.hh"
#include "BLI_task.hh"
+#include "BLI_virtual_array.hh"
namespace blender::meshintersect {
@@ -405,13 +407,17 @@ static void copy_poly_attributes(Mesh *dest_mesh,
const Mesh *orig_me,
int mp_index,
int index_in_orig_me,
- Span<short> material_remap)
+ Span<short> material_remap,
+ MutableSpan<int> dst_material_indices)
{
- if (material_remap.size() > 0 && material_remap.index_range().contains(orig_mp->mat_nr)) {
- mp->mat_nr = material_remap[orig_mp->mat_nr];
+ const VArray<int> src_material_indices = bke::mesh_attributes(*orig_me).lookup_or_default<int>(
+ "material_index", ATTR_DOMAIN_FACE, 0);
+ const int src_index = src_material_indices[index_in_orig_me];
+ if (material_remap.size() > 0 && material_remap.index_range().contains(src_index)) {
+ dst_material_indices[mp_index] = material_remap[src_index];
}
else {
- mp->mat_nr = orig_mp->mat_nr;
+ dst_material_indices[mp_index] = src_index;
}
mp->flag = orig_mp->flag;
@@ -722,6 +728,9 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim)
/* Set the loopstart and totloop for each output poly,
* and set the vertices in the appropriate loops. */
+ bke::SpanAttributeWriter<int> dst_material_indices =
+ bke::mesh_attributes_for_write(*result).lookup_or_add_for_write_only_span<int>(
+ "material_index", ATTR_DOMAIN_FACE);
int cur_loop_index = 0;
MLoop *l = result->mloop;
for (int fi : im->face_index_range()) {
@@ -750,9 +759,11 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim)
index_in_orig_me,
(mim.material_remaps.size() > 0) ?
mim.material_remaps[orig_me_index].as_span() :
- Span<short>());
+ Span<short>(),
+ dst_material_indices.span);
copy_or_interp_loop_attributes(result, f, mp, orig_mp, orig_me, orig_me_index, mim);
}
+ dst_material_indices.finish();
/* BKE_mesh_calc_edges will calculate and populate all the
* MEdges from the MPolys. */
diff --git a/source/blender/blenkernel/intern/mesh_convert.cc b/source/blender/blenkernel/intern/mesh_convert.cc
index cb72e09af16..393d54bb03e 100644
--- a/source/blender/blenkernel/intern/mesh_convert.cc
+++ b/source/blender/blenkernel/intern/mesh_convert.cc
@@ -140,6 +140,7 @@ static void make_edges_mdata_extend(Mesh &mesh)
static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispbase)
{
+ using namespace blender::bke;
const float *data;
int a, b, ofs, vertcount, startvert, totvert = 0, totedge = 0, totloop = 0, totpoly = 0;
int p1, p2, p3, p4, *index;
@@ -194,6 +195,9 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
MEdge *medge = edges.data();
MPoly *mpoly = polys.data();
MLoop *mloop = loops.data();
+ MutableAttributeAccessor attributes = mesh_attributes_for_write(*mesh);
+ SpanAttributeWriter<int> material_indices = attributes.lookup_or_add_for_write_only_span<int>(
+ "material_index", ATTR_DOMAIN_FACE);
MLoopUV *mloopuv = static_cast<MLoopUV *>(CustomData_add_layer_named(
&mesh->ldata, CD_MLOOPUV, CD_SET_DEFAULT, nullptr, mesh->totloop, "UVMap"));
@@ -272,7 +276,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
mloop[2].v = startvert + index[1];
mpoly->loopstart = (int)(mloop - loops.data());
mpoly->totloop = 3;
- mpoly->mat_nr = dl->col;
+ material_indices.span[mpoly - polys.data()] = dl->col;
if (mloopuv) {
for (int i = 0; i < 3; i++, mloopuv++) {
@@ -332,7 +336,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
mloop[3].v = p2;
mpoly->loopstart = (int)(mloop - loops.data());
mpoly->totloop = 4;
- mpoly->mat_nr = dl->col;
+ material_indices.span[mpoly - polys.data()] = dl->col;
if (mloopuv) {
int orco_sizeu = dl->nr - 1;
@@ -385,6 +389,8 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
make_edges_mdata_extend(*mesh);
}
+ material_indices.finish();
+
return mesh;
}
diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc
index 45cbf3aa28b..2fc984997b8 100644
--- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc
+++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc
@@ -963,3 +963,42 @@ void BKE_mesh_legacy_convert_flags_to_hide_layers(Mesh *mesh)
}
/** \} */
+/* -------------------------------------------------------------------- */
+/** \name Material Index Conversion
+ * \{ */
+
+void BKE_mesh_legacy_convert_material_indices_to_mpoly(Mesh *mesh)
+{
+ using namespace blender;
+ using namespace blender::bke;
+ const AttributeAccessor attributes = mesh_attributes(*mesh);
+ MutableSpan<MPoly> polys(mesh->mpoly, mesh->totpoly);
+ const VArray<int> material_indices = attributes.lookup_or_default<int>(
+ "material_index", ATTR_DOMAIN_FACE, 0);
+ threading::parallel_for(polys.index_range(), 4096, [&](IndexRange range) {
+ for (const int i : range) {
+ polys[i].mat_nr = material_indices[i];
+ }
+ });
+}
+
+void BKE_mesh_legacy_convert_mpoly_to_material_indices(Mesh *mesh)
+{
+ using namespace blender;
+ using namespace blender::bke;
+ MutableAttributeAccessor attributes = mesh_attributes_for_write(*mesh);
+ const Span<MPoly> polys(mesh->mpoly, mesh->totpoly);
+ if (std::any_of(
+ polys.begin(), polys.end(), [](const MPoly &poly) { return poly.mat_nr != 0; })) {
+ SpanAttributeWriter<int> material_indices = attributes.lookup_or_add_for_write_only_span<int>(
+ "material_index", ATTR_DOMAIN_FACE);
+ threading::parallel_for(polys.index_range(), 4096, [&](IndexRange range) {
+ for (const int i : range) {
+ material_indices.span[i] = polys[i].mat_nr;
+ }
+ });
+ material_indices.finish();
+ }
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/mesh_validate.cc b/source/blender/blenkernel/intern/mesh_validate.cc
index 95a2eaec1aa..3d8bbe3d6f8 100644
--- a/source/blender/blenkernel/intern/mesh_validate.cc
+++ b/source/blender/blenkernel/intern/mesh_validate.cc
@@ -24,6 +24,7 @@
#include "BLI_math_vector.h"
#include "BLI_utildefines.h"
+#include "BKE_attribute.hh"
#include "BKE_customdata.h"
#include "BKE_deform.h"
#include "BKE_mesh.h"
@@ -238,6 +239,10 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
} \
(void)0
+ blender::bke::AttributeWriter<int> material_indices =
+ blender::bke::mesh_attributes_for_write(*mesh).lookup_for_write<int>("material_index");
+ blender::MutableVArraySpan<int> material_indices_span(material_indices.varray);
+
MVert *mv = mverts;
MEdge *me;
MLoop *ml;
@@ -559,10 +564,10 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
/* Material index, isolated from other tests here. While large indices are clamped,
* negative indices aren't supported by drawing, exporters etc.
* To check the indices are in range, use #BKE_mesh_validate_material_indices */
- if (mp->mat_nr < 0) {
- PRINT_ERR("\tPoly %u has invalid material (%d)", sp->index, mp->mat_nr);
+ if (material_indices && material_indices_span[i] < 0) {
+ PRINT_ERR("\tPoly %u has invalid material (%d)", sp->index, material_indices_span[i]);
if (do_fixes) {
- mp->mat_nr = 0;
+ material_indices_span[i] = 0;
}
}
@@ -916,6 +921,9 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
}
}
+ material_indices_span.save();
+ material_indices.finish();
+
PRINT_MSG("%s: finished\n\n", __func__);
*r_changed = (fix_flag.as_flag || free_flag.as_flag || recalc_flag.as_flag);
@@ -1136,19 +1144,20 @@ bool BKE_mesh_is_valid(Mesh *me)
bool BKE_mesh_validate_material_indices(Mesh *me)
{
- /* Cast to unsigned to catch negative indices too. */
- const uint16_t mat_nr_max = max_ii(0, me->totcol - 1);
- MPoly *mp;
- const int totpoly = me->totpoly;
- int i;
+ const int mat_nr_max = max_ii(0, me->totcol - 1);
bool is_valid = true;
- for (mp = me->mpoly, i = 0; i < totpoly; i++, mp++) {
- if ((uint16_t)mp->mat_nr > mat_nr_max) {
- mp->mat_nr = 0;
+ blender::bke::AttributeWriter<int> material_indices =
+ blender::bke::mesh_attributes_for_write(*me).lookup_for_write<int>("material_index");
+ blender::MutableVArraySpan<int> material_indices_span(material_indices.varray);
+ for (const int i : material_indices_span.index_range()) {
+ if (material_indices_span[i] < 0 || material_indices_span[i] > mat_nr_max) {
+ material_indices_span[i] = 0;
is_valid = false;
}
}
+ material_indices_span.save();
+ material_indices.finish();
if (!is_valid) {
DEG_id_tag_update(&me->id, ID_RECALC_GEOMETRY_ALL_MODES);
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 24f3097f9e3..1c6274ef35e 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -145,9 +145,14 @@ static void update_node_vb(PBVH *pbvh, PBVHNode *node)
// BB_expand(&node->vb, co);
//}
-static bool face_materials_match(const MPoly *f1, const MPoly *f2)
+static bool face_materials_match(const PBVH *pbvh, const int a, const int b)
{
- return ((f1->flag & ME_SMOOTH) == (f2->flag & ME_SMOOTH) && (f1->mat_nr == f2->mat_nr));
+ if (pbvh->material_indices) {
+ if (pbvh->material_indices[a] != pbvh->material_indices[b]) {
+ return false;
+ }
+ }
+ return (pbvh->mpoly[a].flag & ME_SMOOTH) == (pbvh->mpoly[b].flag & ME_SMOOTH);
}
static bool grid_materials_match(const DMFlagMat *f1, const DMFlagMat *f2)
@@ -180,30 +185,23 @@ static int partition_indices(int *prim_indices, int lo, int hi, int axis, float
/* Returns the index of the first element on the right of the partition */
static int partition_indices_material(PBVH *pbvh, int lo, int hi)
{
- const MPoly *mpoly = pbvh->mpoly;
const MLoopTri *looptri = pbvh->looptri;
const DMFlagMat *flagmats = pbvh->grid_flag_mats;
const int *indices = pbvh->prim_indices;
- const void *first;
int i = lo, j = hi;
- if (pbvh->looptri) {
- first = &mpoly[looptri[pbvh->prim_indices[lo]].poly];
- }
- else {
- first = &flagmats[pbvh->prim_indices[lo]];
- }
-
for (;;) {
if (pbvh->looptri) {
- for (; face_materials_match(first, &mpoly[looptri[indices[i]].poly]); i++) {
+ const int first = looptri[pbvh->prim_indices[lo]].poly;
+ for (; face_materials_match(pbvh, first, looptri[indices[i]].poly); i++) {
/* pass */
}
- for (; !face_materials_match(first, &mpoly[looptri[indices[j]].poly]); j--) {
+ for (; !face_materials_match(pbvh, first, looptri[indices[j]].poly); j--) {
/* pass */
}
}
else {
+ const DMFlagMat *first = &flagmats[pbvh->prim_indices[lo]];
for (; grid_materials_match(first, &flagmats[indices[i]]); i++) {
/* pass */
}
@@ -424,12 +422,9 @@ static bool leaf_needs_material_split(PBVH *pbvh, int offset, int count)
if (pbvh->looptri) {
const MLoopTri *first = &pbvh->looptri[pbvh->prim_indices[offset]];
- const MPoly *mp = &pbvh->mpoly[first->poly];
-
for (int i = offset + count - 1; i > offset; i--) {
int prim = pbvh->prim_indices[i];
- const MPoly *mp_other = &pbvh->mpoly[pbvh->looptri[prim].poly];
- if (!face_materials_match(mp, mp_other)) {
+ if (!face_materials_match(pbvh, first->poly, pbvh->looptri[prim].poly)) {
return true;
}
}
@@ -557,6 +552,8 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
pbvh->mesh = mesh;
pbvh->header.type = PBVH_FACES;
pbvh->mpoly = mpoly;
+ pbvh->material_indices = (const int *)CustomData_get_layer_named(
+ &mesh->pdata, CD_PROP_INT32, "material_index");
pbvh->mloop = mloop;
pbvh->looptri = looptri;
pbvh->verts = verts;
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
index 3d67ab9ba6b..b848327b7a9 100644
--- a/source/blender/blenkernel/intern/pbvh_intern.h
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -156,6 +156,8 @@ struct PBVH {
bool *hide_vert;
struct MVert *verts;
const struct MPoly *mpoly;
+ /** Material indices. Only valid for polygon meshes. */
+ const int *material_indices;
const struct MLoop *mloop;
const struct MLoopTri *looptri;
CustomData *vdata;
diff --git a/source/blender/blenkernel/intern/subdiv_ccg_material.c b/source/blender/blenkernel/intern/subdiv_ccg_material.c
index cf49db15b7b..9095a628418 100644
--- a/source/blender/blenkernel/intern/subdiv_ccg_material.c
+++ b/source/blender/blenkernel/intern/subdiv_ccg_material.c
@@ -5,6 +5,7 @@
* \ingroup bke
*/
+#include "BKE_customdata.h"
#include "BKE_subdiv_ccg.h"
#include "MEM_guardedalloc.h"
@@ -14,6 +15,7 @@
typedef struct CCGMaterialFromMeshData {
const Mesh *mesh;
+ const int *material_indices;
} CCGMaterialFromMeshData;
static DMFlagMat subdiv_ccg_material_flags_eval(
@@ -26,7 +28,7 @@ static DMFlagMat subdiv_ccg_material_flags_eval(
const MPoly *poly = &mpoly[coarse_face_index];
DMFlagMat material_flags;
material_flags.flag = poly->flag;
- material_flags.mat_nr = poly->mat_nr;
+ material_flags.mat_nr = data->material_indices ? data->material_indices[coarse_face_index] : 0;
return material_flags;
}
@@ -42,6 +44,8 @@ void BKE_subdiv_ccg_material_flags_init_from_mesh(
CCGMaterialFromMeshData *data = MEM_mallocN(sizeof(CCGMaterialFromMeshData),
"ccg material eval");
data->mesh = mesh;
+ data->material_indices = (const int *)CustomData_get_layer_named(
+ &mesh->pdata, CD_PROP_INT32, "material_index");
material_flags_evaluator->eval_material_flags = subdiv_ccg_material_flags_eval;
material_flags_evaluator->free = subdiv_ccg_material_flags_free;
material_flags_evaluator->user_data = data;
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 9737801291e..52df555090f 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -1134,14 +1134,12 @@ static void ccgDM_copyFinalPolyArray(DerivedMesh *dm, MPoly *mpoly)
CCGFace *f = ccgdm->faceMap[index].face;
int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
int flag = (faceFlags) ? faceFlags[index].flag : ME_SMOOTH;
- int mat_nr = (faceFlags) ? faceFlags[index].mat_nr : 0;
for (S = 0; S < numVerts; S++) {
for (y = 0; y < gridSize - 1; y++) {
for (x = 0; x < gridSize - 1; x++) {
MPoly *mp = &mpoly[i];
- mp->mat_nr = mat_nr;
mp->flag = flag;
mp->loopstart = k;
mp->totloop = 4;
@@ -1607,6 +1605,8 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
medge = dm->getEdgeArray(dm);
const MPoly *mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
+ const int *material_indices = CustomData_get_layer_named(
+ &dm->polyData, CD_MPOLY, "material_index");
const int *base_polyOrigIndex = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
int *vertOrigIndex = DM_get_vert_data_layer(&ccgdm->dm, CD_ORIGINDEX);
@@ -1635,7 +1635,7 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
ccgdm->faceMap[index].startFace = faceNum;
faceFlags->flag = mpoly ? mpoly[origIndex].flag : 0;
- faceFlags->mat_nr = mpoly ? mpoly[origIndex].mat_nr : 0;
+ faceFlags->mat_nr = material_indices ? material_indices[origIndex] : 0;
faceFlags++;
/* set the face base vert */