Geometry Nodes: take materials into account when joining geometries
Materials are now kept intact when using the Join Geometry node or when realizing instaces.
This commit is contained in:
parent
02b80276b3
commit
5e6f3b8564
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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<GeometryInstanceGrou
|
|||
int64_t cd_dirty_poly = 0;
|
||||
int64_t cd_dirty_edge = 0;
|
||||
int64_t cd_dirty_loop = 0;
|
||||
VectorSet<Material *> 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(Span<GeometryInstanceGrou
|
|||
cd_dirty_poly |= mesh.runtime.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);
|
||||
}
|
||||
}
|
||||
if (convert_points_to_vertices && set.has_pointcloud()) {
|
||||
const PointCloud &pointcloud = *set.get_pointcloud_for_read();
|
||||
|
@ -396,6 +403,10 @@ static Mesh *join_mesh_topology_and_builtin_attributes(Span<GeometryInstanceGrou
|
|||
break;
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
@ -409,6 +420,14 @@ static Mesh *join_mesh_topology_and_builtin_attributes(Span<GeometryInstanceGrou
|
|||
const GeometrySet &set = set_group.geometry_set;
|
||||
if (set.has_mesh()) {
|
||||
const Mesh &mesh = *set.get_mesh_for_read();
|
||||
|
||||
Array<int> 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(Span<GeometryInstanceGrou
|
|||
MPoly &new_poly = new_mesh->mpoly[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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<const MeshComponent
|
|||
int64_t cd_dirty_edge = 0;
|
||||
int64_t cd_dirty_loop = 0;
|
||||
|
||||
VectorSet<Material *> 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(Span<const MeshComponent
|
|||
cd_dirty_poly |= mesh->runtime.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<const MeshComponent
|
|||
continue;
|
||||
}
|
||||
|
||||
Array<int> 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(Span<const MeshComponent
|
|||
MPoly &new_poly = new_mesh->mpoly[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;
|
||||
|
|
Loading…
Reference in New Issue