mirror of
https://github.com/blender/blender
synced 2026-09-29 04:37:17 +03:00
Fix T93272: Material index mapping missing for mesh boolean node
This commit implements copying of materials and material indices from all of the boolean node's input meshes. The materials are added to the final mesh in the order that they appear when looking through the materials of the input meshes in the same order of the multi-socket input node. All material remapping is done with mesh-level materials. Object-level materials are not considered, since the meshes don't come from objects. Merging all materials rather than just the materials on the first mesh requires a change to the boolean-mesh conversion. This subtly changes the behavior for object linked materials, but in a good way I think; now the material remap arrays are respected no matter the number of materials on the first mesh input. Differential Revision: https://developer.blender.org/D14788
This commit is contained in:
parent
c09c3246eb
commit
1a6d0ec71c
2 changed files with 41 additions and 11 deletions
|
|
@ -407,17 +407,11 @@ static void copy_poly_attributes(Mesh *dest_mesh,
|
|||
int index_in_orig_me,
|
||||
Span<short> material_remap)
|
||||
{
|
||||
mp->mat_nr = orig_mp->mat_nr;
|
||||
if (mp->mat_nr >= dest_mesh->totcol) {
|
||||
mp->mat_nr = 0;
|
||||
if (material_remap.size() > 0 && material_remap.index_range().contains(orig_mp->mat_nr)) {
|
||||
mp->mat_nr = material_remap[orig_mp->mat_nr];
|
||||
}
|
||||
else {
|
||||
if (material_remap.size() > 0) {
|
||||
short mat_nr = material_remap[orig_mp->mat_nr];
|
||||
if (mat_nr >= 0 && mat_nr < dest_mesh->totcol) {
|
||||
mp->mat_nr = mat_nr;
|
||||
}
|
||||
}
|
||||
mp->mat_nr = orig_mp->mat_nr;
|
||||
}
|
||||
|
||||
mp->flag = orig_mp->flag;
|
||||
|
|
|
|||
|
|
@ -68,6 +68,9 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
Vector<const Mesh *> meshes;
|
||||
Vector<const float4x4 *> transforms;
|
||||
|
||||
VectorSet<Material *> materials;
|
||||
Vector<Array<short>> material_remaps;
|
||||
|
||||
GeometrySet set_a;
|
||||
if (operation == GEO_NODE_BOOLEAN_DIFFERENCE) {
|
||||
set_a = params.extract_input<GeometrySet>("Mesh 1");
|
||||
|
|
@ -78,6 +81,10 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
if (mesh_in_a != nullptr) {
|
||||
meshes.append(mesh_in_a);
|
||||
transforms.append(nullptr);
|
||||
for (Material *material : Span(mesh_in_a->mat, mesh_in_a->totcol)) {
|
||||
materials.add(material);
|
||||
}
|
||||
material_remaps.append({});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -89,6 +96,25 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
bke::geometry_set_gather_instances(geometry_set, set_groups);
|
||||
}
|
||||
|
||||
for (const bke::GeometryInstanceGroup &set_group : set_groups) {
|
||||
const Mesh *mesh = set_group.geometry_set.get_mesh_for_read();
|
||||
if (mesh != nullptr) {
|
||||
for (Material *material : Span(mesh->mat, mesh->totcol)) {
|
||||
materials.add(material);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const bke::GeometryInstanceGroup &set_group : set_groups) {
|
||||
const Mesh *mesh = set_group.geometry_set.get_mesh_for_read();
|
||||
if (mesh != nullptr) {
|
||||
Array<short> map(mesh->totcol);
|
||||
for (const int i : IndexRange(mesh->totcol)) {
|
||||
map[i] = materials.index_of(mesh->mat[i]);
|
||||
}
|
||||
material_remaps.append(std::move(map));
|
||||
}
|
||||
}
|
||||
|
||||
for (const bke::GeometryInstanceGroup &set_group : set_groups) {
|
||||
const Mesh *mesh_in = set_group.geometry_set.get_mesh_for_read();
|
||||
if (mesh_in != nullptr) {
|
||||
|
|
@ -99,8 +125,18 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
}
|
||||
}
|
||||
|
||||
Mesh *result = blender::meshintersect::direct_mesh_boolean(
|
||||
meshes, transforms, float4x4::identity(), {}, use_self, hole_tolerant, operation);
|
||||
Mesh *result = blender::meshintersect::direct_mesh_boolean(meshes,
|
||||
transforms,
|
||||
float4x4::identity(),
|
||||
material_remaps,
|
||||
use_self,
|
||||
hole_tolerant,
|
||||
operation);
|
||||
|
||||
MEM_SAFE_FREE(result->mat);
|
||||
result->mat = (Material **)MEM_malloc_arrayN(materials.size(), sizeof(Material *), __func__);
|
||||
result->totcol = materials.size();
|
||||
MutableSpan(result->mat, result->totcol).copy_from(materials);
|
||||
|
||||
params.set_output("Mesh", GeometrySet::create_with_mesh(result));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue