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/mesh.cc
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/mesh.cc')
-rw-r--r--source/blender/blenkernel/intern/mesh.cc95
1 files changed, 53 insertions, 42 deletions
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