From 5e6f3b85646fe96031c3eafe65e9bc7b55468685 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Wed, 19 May 2021 11:02:25 +0200 Subject: Geometry Nodes: take materials into account when joining geometries Materials are now kept intact when using the Join Geometry node or when realizing instaces. --- source/blender/blenkernel/BKE_material.h | 1 + .../blenkernel/intern/geometry_set_instances.cc | 26 +++++++++++++++++++++ source/blender/blenkernel/intern/material.c | 25 ++++++++++++++++++++ .../nodes/geometry/nodes/node_geo_join_geometry.cc | 27 ++++++++++++++++++++++ 4 files changed, 79 insertions(+) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index 96aae2d2d42..ef1de891bfe 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -109,6 +109,7 @@ void BKE_id_material_clear(struct Main *bmain, struct ID *id); /* eval api */ struct Material *BKE_object_material_get_eval(struct Object *ob, short act); int BKE_object_material_count_eval(struct Object *ob); +void BKE_id_material_eval_assign(struct ID *id, int slot, struct Material *material); /* rendering */ diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc index b6ee0337dbf..97892075eca 100644 --- a/source/blender/blenkernel/intern/geometry_set_instances.cc +++ b/source/blender/blenkernel/intern/geometry_set_instances.cc @@ -15,6 +15,7 @@ */ #include "BKE_geometry_set_instances.hh" +#include "BKE_material.h" #include "BKE_mesh.h" #include "BKE_mesh_wrapper.h" #include "BKE_modifier.h" @@ -361,6 +362,8 @@ static Mesh *join_mesh_topology_and_builtin_attributes(Span materials; + for (const GeometryInstanceGroup &set_group : set_groups) { const GeometrySet &set = set_group.geometry_set; const int tot_transforms = set_group.transforms.size(); @@ -374,6 +377,10 @@ static Mesh *join_mesh_topology_and_builtin_attributes(Spanid, i + 1, material); + } new_mesh->runtime.cd_dirty_vert = cd_dirty_vert; new_mesh->runtime.cd_dirty_poly = cd_dirty_poly; new_mesh->runtime.cd_dirty_edge = cd_dirty_edge; @@ -409,6 +420,14 @@ static Mesh *join_mesh_topology_and_builtin_attributes(Span material_index_map(mesh.totcol); + for (const int i : IndexRange(mesh.totcol)) { + Material *material = mesh.mat[i]; + const int new_material_index = materials.index_of(material); + material_index_map[i] = new_material_index; + } + for (const float4x4 &transform : set_group.transforms) { for (const int i : IndexRange(mesh.totvert)) { const MVert &old_vert = mesh.mvert[i]; @@ -438,6 +457,13 @@ static Mesh *join_mesh_topology_and_builtin_attributes(Spanmpoly[poly_offset + i]; new_poly = old_poly; new_poly.loopstart += loop_offset; + if (old_poly.mat_nr >= 0 && old_poly.mat_nr < mesh.totcol) { + new_poly.mat_nr = material_index_map[new_poly.mat_nr]; + } + else { + /* The material index was invalid before. */ + new_poly.mat_nr = 0; + } } vert_offset += mesh.totvert; diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 73afea98163..73a7a69f5a5 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -768,6 +768,31 @@ int BKE_object_material_count_eval(Object *ob) return len_p ? *len_p : 0; } +void BKE_id_material_eval_assign(ID *id, int slot, Material *material) +{ + Material ***materials_ptr = BKE_id_material_array_p(id); + short *len_ptr = BKE_id_material_len_p(id); + if (ELEM(NULL, materials_ptr, len_ptr)) { + BLI_assert_unreachable(); + return; + } + + const int slot_index = slot - 1; + const int old_length = *len_ptr; + + if (slot_index >= old_length) { + /* Need to grow slots array. */ + const int new_length = slot_index + 1; + *materials_ptr = MEM_reallocN(*materials_ptr, sizeof(void *) * new_length); + *len_ptr = new_length; + for (int i = old_length; i < new_length; i++) { + (*materials_ptr)[i] = NULL; + } + } + + (*materials_ptr)[slot_index] = material; +} + Material *BKE_gpencil_material(Object *ob, short act) { Material *ma = BKE_object_material_get(ob, act); diff --git a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc index a6e78048ea6..915ebc1e1f2 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc @@ -14,6 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "BKE_material.h" #include "BKE_mesh.h" #include "BKE_mesh_runtime.h" #include "BKE_pointcloud.h" @@ -57,6 +58,8 @@ static Mesh *join_mesh_topology_and_builtin_attributes(Span materials; + for (const MeshComponent *mesh_component : src_components) { const Mesh *mesh = mesh_component->get_for_read(); totverts += mesh->totvert; @@ -67,12 +70,22 @@ static Mesh *join_mesh_topology_and_builtin_attributes(Spanruntime.cd_dirty_poly; cd_dirty_edge |= mesh->runtime.cd_dirty_edge; cd_dirty_loop |= mesh->runtime.cd_dirty_loop; + + for (const int slot_index : IndexRange(mesh->totcol)) { + Material *material = mesh->mat[slot_index]; + materials.add(material); + } } const Mesh *first_input_mesh = src_components[0]->get_for_read(); Mesh *new_mesh = BKE_mesh_new_nomain(totverts, totedges, 0, totloops, totpolys); BKE_mesh_copy_settings(new_mesh, first_input_mesh); + for (const int i : IndexRange(materials.size())) { + Material *material = materials[i]; + BKE_id_material_eval_assign(&new_mesh->id, i + 1, material); + } + new_mesh->runtime.cd_dirty_vert = cd_dirty_vert; new_mesh->runtime.cd_dirty_poly = cd_dirty_poly; new_mesh->runtime.cd_dirty_edge = cd_dirty_edge; @@ -88,6 +101,13 @@ static Mesh *join_mesh_topology_and_builtin_attributes(Span material_index_map(mesh->totcol); + for (const int i : IndexRange(mesh->totcol)) { + Material *material = mesh->mat[i]; + const int new_material_index = materials.index_of(material); + material_index_map[i] = new_material_index; + } + for (const int i : IndexRange(mesh->totvert)) { const MVert &old_vert = mesh->mvert[i]; MVert &new_vert = new_mesh->mvert[vert_offset + i]; @@ -113,6 +133,13 @@ static Mesh *join_mesh_topology_and_builtin_attributes(Spanmpoly[poly_offset + i]; new_poly = old_poly; new_poly.loopstart += loop_offset; + if (old_poly.mat_nr >= 0 && old_poly.mat_nr < mesh->totcol) { + new_poly.mat_nr = material_index_map[new_poly.mat_nr]; + } + else { + /* The material index was invalid before. */ + new_poly.mat_nr = 0; + } } vert_offset += mesh->totvert; -- cgit v1.2.3