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:
Diffstat (limited to 'source/blender/geometry/intern/realize_instances.cc')
-rw-r--r--source/blender/geometry/intern/realize_instances.cc120
1 files changed, 88 insertions, 32 deletions
diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc
index 87a610ac0a2..25ff705385c 100644
--- a/source/blender/geometry/intern/realize_instances.cc
+++ b/source/blender/geometry/intern/realize_instances.cc
@@ -9,6 +9,7 @@
#include "DNA_object_types.h"
#include "DNA_pointcloud_types.h"
+#include "BLI_devirtualize_parameters.hh"
#include "BLI_noise.hh"
#include "BLI_task.hh"
@@ -102,6 +103,7 @@ struct MeshRealizeInfo {
Array<std::optional<GVArraySpan>> attributes;
/** Vertex ids stored on the mesh. If there are no ids, this #Span is empty. */
Span<int> stored_vertex_ids;
+ VArray<int> material_indices;
};
struct RealizeMeshTask {
@@ -182,6 +184,7 @@ struct AllMeshesInfo {
/** Ordered materials on the output mesh. */
VectorSet<Material *> materials;
bool create_id_attribute = false;
+ bool create_material_index_attribute = false;
};
struct AllCurvesInfo {
@@ -787,7 +790,10 @@ static void execute_realize_pointcloud_tasks(const RealizeInstancesOptions &opti
* \{ */
static OrderedAttributes gather_generic_mesh_attributes_to_propagate(
- const GeometrySet &in_geometry_set, const RealizeInstancesOptions &options, bool &r_create_id)
+ const GeometrySet &in_geometry_set,
+ const RealizeInstancesOptions &options,
+ bool &r_create_id,
+ bool &r_create_material_index)
{
Vector<GeometryComponentType> src_component_types;
src_component_types.append(GEO_COMPONENT_TYPE_MESH);
@@ -800,10 +806,10 @@ static OrderedAttributes gather_generic_mesh_attributes_to_propagate(
src_component_types, GEO_COMPONENT_TYPE_MESH, true, attributes_to_propagate);
attributes_to_propagate.remove("position");
attributes_to_propagate.remove("normal");
- attributes_to_propagate.remove("material_index");
attributes_to_propagate.remove("shade_smooth");
attributes_to_propagate.remove("crease");
r_create_id = attributes_to_propagate.pop_try("id").has_value();
+ r_create_material_index = attributes_to_propagate.pop_try("material_index").has_value();
OrderedAttributes ordered_attributes;
for (const auto item : attributes_to_propagate.items()) {
ordered_attributes.ids.add_new(item.key);
@@ -833,13 +839,19 @@ static AllMeshesInfo preprocess_meshes(const GeometrySet &geometry_set,
{
AllMeshesInfo info;
info.attributes = gather_generic_mesh_attributes_to_propagate(
- geometry_set, options, info.create_id_attribute);
+ geometry_set, options, info.create_id_attribute, info.create_material_index_attribute);
gather_meshes_to_realize(geometry_set, info.order);
for (const Mesh *mesh : info.order) {
- for (const int slot_index : IndexRange(mesh->totcol)) {
- Material *material = mesh->mat[slot_index];
- info.materials.add(material);
+ if (mesh->totcol == 0) {
+ /* Add an empty material slot for the default material. */
+ info.materials.add(nullptr);
+ }
+ else {
+ for (const int slot_index : IndexRange(mesh->totcol)) {
+ Material *material = mesh->mat[slot_index];
+ info.materials.add(material);
+ }
}
}
info.realize_info.reinitialize(info.order.size());
@@ -849,11 +861,16 @@ static AllMeshesInfo preprocess_meshes(const GeometrySet &geometry_set,
mesh_info.mesh = mesh;
/* Create material index mapping. */
- mesh_info.material_index_map.reinitialize(mesh->totcol);
- for (const int old_slot_index : IndexRange(mesh->totcol)) {
- Material *material = mesh->mat[old_slot_index];
- const int new_slot_index = info.materials.index_of(material);
- mesh_info.material_index_map[old_slot_index] = new_slot_index;
+ mesh_info.material_index_map.reinitialize(std::max<int>(mesh->totcol, 1));
+ if (mesh->totcol == 0) {
+ mesh_info.material_index_map.first() = info.materials.index_of(nullptr);
+ }
+ else {
+ for (const int old_slot_index : IndexRange(mesh->totcol)) {
+ Material *material = mesh->mat[old_slot_index];
+ const int new_slot_index = info.materials.index_of(material);
+ mesh_info.material_index_map[old_slot_index] = new_slot_index;
+ }
}
/* Access attributes. */
@@ -874,6 +891,8 @@ static AllMeshesInfo preprocess_meshes(const GeometrySet &geometry_set,
mesh_info.stored_vertex_ids = ids_attribute.varray.get_internal_span().typed<int>();
}
}
+ mesh_info.material_indices = attributes.lookup_or_default<int>(
+ "material_index", ATTR_DOMAIN_FACE, 0);
}
return info;
}
@@ -883,7 +902,8 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options,
const OrderedAttributes &ordered_attributes,
Mesh &dst_mesh,
MutableSpan<GSpanAttributeWriter> dst_attribute_writers,
- MutableSpan<int> all_dst_vertex_ids)
+ MutableSpan<int> all_dst_vertex_ids,
+ MutableSpan<int> all_dst_material_indices)
{
const MeshRealizeInfo &mesh_info = *task.mesh_info;
const Mesh &mesh = *mesh_info.mesh;
@@ -893,14 +913,19 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options,
const Span<MLoop> src_loops{mesh.mloop, mesh.totloop};
const Span<MPoly> src_polys{mesh.mpoly, mesh.totpoly};
- MutableSpan<MVert> dst_verts{dst_mesh.mvert + task.start_indices.vertex, mesh.totvert};
- MutableSpan<MEdge> dst_edges{dst_mesh.medge + task.start_indices.edge, mesh.totedge};
- MutableSpan<MLoop> dst_loops{dst_mesh.mloop + task.start_indices.loop, mesh.totloop};
- MutableSpan<MPoly> dst_polys{dst_mesh.mpoly + task.start_indices.poly, mesh.totpoly};
+ const IndexRange dst_vert_range(task.start_indices.vertex, src_verts.size());
+ const IndexRange dst_edge_range(task.start_indices.edge, src_edges.size());
+ const IndexRange dst_poly_range(task.start_indices.poly, src_polys.size());
+ const IndexRange dst_loop_range(task.start_indices.loop, src_loops.size());
+
+ MutableSpan dst_verts = MutableSpan(dst_mesh.mvert, dst_mesh.totvert).slice(dst_vert_range);
+ MutableSpan dst_edges = MutableSpan(dst_mesh.medge, dst_mesh.totedge).slice(dst_edge_range);
+ MutableSpan dst_polys = MutableSpan(dst_mesh.mpoly, dst_mesh.totpoly).slice(dst_poly_range);
+ MutableSpan dst_loops = MutableSpan(dst_mesh.mloop, dst_mesh.totloop).slice(dst_loop_range);
const Span<int> material_index_map = mesh_info.material_index_map;
- threading::parallel_for(IndexRange(mesh.totvert), 1024, [&](const IndexRange vert_range) {
+ threading::parallel_for(src_verts.index_range(), 1024, [&](const IndexRange vert_range) {
for (const int i : vert_range) {
const MVert &src_vert = src_verts[i];
MVert &dst_vert = dst_verts[i];
@@ -908,7 +933,7 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options,
copy_v3_v3(dst_vert.co, task.transform * float3(src_vert.co));
}
});
- threading::parallel_for(IndexRange(mesh.totedge), 1024, [&](const IndexRange edge_range) {
+ threading::parallel_for(src_edges.index_range(), 1024, [&](const IndexRange edge_range) {
for (const int i : edge_range) {
const MEdge &src_edge = src_edges[i];
MEdge &dst_edge = dst_edges[i];
@@ -917,7 +942,7 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options,
dst_edge.v2 += task.start_indices.vertex;
}
});
- threading::parallel_for(IndexRange(mesh.totloop), 1024, [&](const IndexRange loop_range) {
+ threading::parallel_for(src_loops.index_range(), 1024, [&](const IndexRange loop_range) {
for (const int i : loop_range) {
const MLoop &src_loop = src_loops[i];
MLoop &dst_loop = dst_loops[i];
@@ -926,21 +951,38 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options,
dst_loop.e += task.start_indices.edge;
}
});
- threading::parallel_for(IndexRange(mesh.totpoly), 1024, [&](const IndexRange poly_range) {
+ threading::parallel_for(src_polys.index_range(), 1024, [&](const IndexRange poly_range) {
for (const int i : poly_range) {
const MPoly &src_poly = src_polys[i];
MPoly &dst_poly = dst_polys[i];
dst_poly = src_poly;
dst_poly.loopstart += task.start_indices.loop;
- if (src_poly.mat_nr >= 0 && src_poly.mat_nr < mesh.totcol) {
- dst_poly.mat_nr = material_index_map[src_poly.mat_nr];
+ }
+ });
+ if (!all_dst_material_indices.is_empty()) {
+ MutableSpan<int> dst_material_indices = all_dst_material_indices.slice(dst_poly_range);
+ if (mesh.totcol == 0) {
+ /* The material index map contains the index of the null material in the result. */
+ dst_material_indices.fill(material_index_map.first());
+ }
+ else {
+ if (mesh_info.material_indices.is_single()) {
+ const int src_index = mesh_info.material_indices.get_internal_single();
+ const bool valid = IndexRange(mesh.totcol).contains(src_index);
+ dst_material_indices.fill(valid ? material_index_map[src_index] : 0);
}
else {
- /* The material index was invalid before. */
- dst_poly.mat_nr = 0;
+ VArraySpan<int> indices_span(mesh_info.material_indices);
+ threading::parallel_for(src_polys.index_range(), 1024, [&](const IndexRange poly_range) {
+ for (const int i : poly_range) {
+ const int src_index = indices_span[i];
+ const bool valid = IndexRange(mesh.totcol).contains(src_index);
+ dst_material_indices[i] = valid ? material_index_map[src_index] : 0;
+ }
+ });
}
}
- });
+ }
if (!all_dst_vertex_ids.is_empty()) {
create_result_ids(options,
@@ -956,13 +998,13 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options,
[&](const eAttrDomain domain) {
switch (domain) {
case ATTR_DOMAIN_POINT:
- return IndexRange(task.start_indices.vertex, mesh.totvert);
+ return dst_vert_range;
case ATTR_DOMAIN_EDGE:
- return IndexRange(task.start_indices.edge, mesh.totedge);
- case ATTR_DOMAIN_CORNER:
- return IndexRange(task.start_indices.loop, mesh.totloop);
+ return dst_edge_range;
case ATTR_DOMAIN_FACE:
- return IndexRange(task.start_indices.poly, mesh.totpoly);
+ return dst_poly_range;
+ case ATTR_DOMAIN_CORNER:
+ return dst_loop_range;
default:
BLI_assert_unreachable();
return IndexRange();
@@ -1013,6 +1055,12 @@ static void execute_realize_mesh_tasks(const RealizeInstancesOptions &options,
if (all_meshes_info.create_id_attribute) {
vertex_ids = dst_attributes.lookup_or_add_for_write_only_span<int>("id", ATTR_DOMAIN_POINT);
}
+ /* Prepare material indices. */
+ SpanAttributeWriter<int> material_indices;
+ if (all_meshes_info.create_material_index_attribute) {
+ material_indices = dst_attributes.lookup_or_add_for_write_only_span<int>("material_index",
+ ATTR_DOMAIN_FACE);
+ }
/* Prepare generic output attributes. */
Vector<GSpanAttributeWriter> dst_attribute_writers;
@@ -1028,8 +1076,13 @@ static void execute_realize_mesh_tasks(const RealizeInstancesOptions &options,
threading::parallel_for(tasks.index_range(), 100, [&](const IndexRange task_range) {
for (const int task_index : task_range) {
const RealizeMeshTask &task = tasks[task_index];
- execute_realize_mesh_task(
- options, task, ordered_attributes, *dst_mesh, dst_attribute_writers, vertex_ids.span);
+ execute_realize_mesh_task(options,
+ task,
+ ordered_attributes,
+ *dst_mesh,
+ dst_attribute_writers,
+ vertex_ids.span,
+ material_indices.span);
}
});
@@ -1040,6 +1093,9 @@ static void execute_realize_mesh_tasks(const RealizeInstancesOptions &options,
if (vertex_ids) {
vertex_ids.finish();
}
+ if (material_indices) {
+ material_indices.finish();
+ }
}
/** \} */