45 return this->kinds.
size();
97 const Mesh *mesh =
nullptr;
337 curves(gather_info.curves.attributes.size()),
339 instances(gather_info.instances_attriubutes.size())
350 points_num += task.start_index + task.pointcloud_info->pointcloud->totpoint;
354 points_num += task.start_indices.vertex + task.mesh_info->mesh->verts_num;
358 points_num += task.start_indices.point + task.curve_info->curves->geometry.point_num;
377 for (const int i : range) {
378 dst[i] = math::transform_point(transform, src[i]);
386 threading::parallel_for(positions.index_range(), 1024, [&](
const IndexRange range) {
387 for (const int i : range) {
388 positions[i] = math::transform_point(transform, positions[i]);
398 if (
math::is_equal(normal_transform, float3x3::identity(), 1e-6f)) {
403 for (const int i : range) {
404 dst[i] = normal_transform * src[i];
415 src.type().copy_construct_n(src.slice(range).data(), dst.slice(range).data(), range.size());
423 value.type()->fill_construct_n(value.get(), dst.slice(range).data(), range.size());
428 const Span<std::optional<GVArraySpan>> src_attributes,
434 threading::parallel_for(
436 for (const int attribute_index : attribute_range) {
437 const bke::AttrDomain domain = ordered_attributes.kinds[attribute_index].domain;
438 const IndexRange element_slice = range_fn(domain);
440 GMutableSpan dst_span = dst_attribute_writers[attribute_index].span.slice(element_slice);
441 if (src_attributes[attribute_index].has_value()) {
442 threaded_copy(*src_attributes[attribute_index], dst_span);
445 const CPPType &cpp_type = dst_span.type();
446 const void *fallback = attribute_fallbacks.array[attribute_index] == nullptr ?
447 cpp_type.default_value() :
448 attribute_fallbacks.array[attribute_index];
449 threaded_fill({cpp_type, fallback}, dst_span);
460 if (
options.keep_original_ids) {
471 for (const int i : range) {
472 dst_ids[i] = noise::hash(task_id, i);
478 for (const int i : range) {
479 dst_ids[i] = noise::hash(task_id, stored_ids[i]);
492 const int current_depth,
493 const int target_depth,
494 const bke::GeometrySet &geometry_set,
495 const float4x4 &base_transform,
496 const InstanceContext &base_instance_context);
511 const int attribute_index = ordered_attributes.
ids.index_of_try(iter.
name);
512 if (attribute_index == -1) {
517 if (!attribute || !attribute.varray.is_span()) {
520 GSpan span = attribute.varray.get_internal_span();
524 const CPPType &to_type = *bke::custom_data_type_to_cpp_type(expected_type);
531 std::unique_ptr<GArray<>> temporary_array = std::make_unique<GArray<>>(
532 to_type, instances.instances_num());
534 span = temporary_array->as_span();
537 attributes_to_override.
append({attribute_index, span});
539 return attributes_to_override;
554 reference.to_geometry_set(geometry_set);
555 fn(geometry_set, base_transform,
id);
559 const int current_depth,
560 const int target_depth,
566 const Span<int> handles = instances.reference_handles();
573 stored_instance_ids = ids.
varray.get_internal_span();
590 const bool is_top_level = current_depth == 0;
594 indices.foreach_index([&](
const int i) {
596 const int child_target_depth = is_top_level ? gather_info.
depths[i] : target_depth;
597 const int handle = handles[i];
598 const float4x4 &transform = transforms[i];
603 for (
const std::pair<int, GSpan> &pair : pointcloud_attributes_to_override) {
606 for (
const std::pair<int, GSpan> &pair : mesh_attributes_to_override) {
607 instance_context.
meshes.
array[pair.first] = pair.second[i];
609 for (
const std::pair<int, GSpan> &pair : curve_attributes_to_override) {
610 instance_context.
curves.
array[pair.first] = pair.second[i];
612 for (
const std::pair<int, GSpan> &pair : grease_pencil_attributes_to_override) {
615 for (
const std::pair<int, GSpan> &pair : instance_attributes_to_override) {
621 if (stored_instance_ids.
is_empty()) {
625 local_instance_id =
uint32_t(stored_instance_ids[i]);
628 const uint32_t instance_id = noise::hash(base_instance_context.
id, local_instance_id);
637 instance_context.
id = id;
641 instance_geometry_set,
652 const int current_depth,
653 const int target_depth,
661 case bke::GeometryComponent::Type::Mesh: {
663 if (mesh !=
nullptr && mesh->verts_num > 0) {
669 base_instance_context.
meshes,
670 base_instance_context.
id});
678 case bke::GeometryComponent::Type::PointCloud: {
681 const PointCloud *pointcloud = pointcloud_component.get();
682 if (pointcloud !=
nullptr && pointcloud->
totpoint > 0) {
690 base_instance_context.
id});
695 case bke::GeometryComponent::Type::Curve: {
697 const Curves *curves = curve_component.get();
698 if (curves !=
nullptr && curves->geometry.curve_num > 0) {
704 base_instance_context.
curves,
705 base_instance_context.
id});
711 case bke::GeometryComponent::Type::GreasePencil: {
714 const GreasePencil *grease_pencil = grease_pencil_component.get();
715 if (grease_pencil !=
nullptr && !grease_pencil->layers().is_empty()) {
728 case bke::GeometryComponent::Type::Instance: {
729 if (current_depth == target_depth) {
737 if (instances !=
nullptr && instances->instances_num() > 0) {
743 base_instance_context);
748 case bke::GeometryComponent::Type::Volume: {
758 case bke::GeometryComponent::Type::Edit: {
761 if (edit_component->gizmo_edit_hints_ || edit_component->curves_edit_hints_) {
774 const int current_depth,
775 const std::optional<int> max_depth,
779 if (r_components.
add_as(component)) {
780 component->add_user();
783 if (current_depth == max_depth) {
787 if (!instances_component) {
794 if (
options.realize_instance_attributes) {
795 if (r_components.
add_as(instances_component)) {
796 instances_component->add_user();
801 reference.to_geometry_set(reference_geometry);
803 reference_geometry, component_type,
options, current_depth + 1, max_depth, r_components);
815 if (r_components.
add_as(component)) {
816 component->add_user();
820 if (!instances_component) {
829 const Span<int> handles = instances->reference_handles();
830 const int references_num = references.
size();
834 const int reference_i = handles[instance_i];
835 const int instance_depth = varied_depth_option.
depths[instance_i];
836 std::optional<int> &max_depth = max_reference_depth[reference_i];
837 if (!max_depth.has_value()) {
841 if (instance_depth == VariedDepthOptions::MAX_DEPTH) {
845 max_depth = std::max<int>(*max_depth, instance_depth);
848 bool is_anything_realized =
false;
849 for (
const int reference_i :
IndexRange(references_num)) {
850 const std::optional<int> max_depth = max_reference_depth[reference_i];
851 if (max_depth == 0) {
856 reference.to_geometry_set(reference_geometry);
858 reference_geometry, component_type,
options, 1, max_depth, r_components);
859 is_anything_realized =
true;
862 if (is_anything_realized) {
863 if (
options.realize_instance_attributes) {
864 if (r_components.
add_as(instances_component)) {
865 instances_component->add_user();
881 const int top_level_instances_num = top_level_instances_component ?
883 AttrDomain::Instance) :
889 varied_depth_option.
selection.
size() == top_level_instances_num)
893 geometry, component_type,
options, 0, std::nullopt, components);
897 geometry, component_type,
options, varied_depth_option, components);
906 if (!bke::attribute_is_builtin_on_component_type(component_type, iter.
name)) {
919 AttrDomain dst_domain = iter.
domain;
920 if (component_type != bke::GeometryComponent::Type::Instance &&
921 dst_domain == AttrDomain::Instance)
924 dst_domain = AttrDomain::Point;
927 kind->domain = dst_domain;
931 kind->domain = bke::attribute_domain_highest_priority({kind->domain, dst_domain});
932 kind->data_type = bke::attribute_data_type_highest_complexity(
939 return attributes_to_propagate;
954 in_geometry_set, bke::GeometryComponent::Type::Instance,
options, varied_depth_option);
955 attributes_to_propagate.
pop_try(
"id");
957 for (
const auto item : attributes_to_propagate.
items()) {
958 ordered_attributes.
ids.add_new(item.key);
959 ordered_attributes.
kinds.append(item.value);
961 return ordered_attributes;
972 src_components.
size() == attribute_fallback.
size());
978 for (
const int component_index : src_components.
index_range()) {
980 *src_components[component_index]);
983 const OffsetIndices offsets = offset_indices::accumulate_counts_to_offsets(offsets_data);
985 std::unique_ptr<bke::Instances> dst_instances = std::make_unique<bke::Instances>();
989 for (
const int attribute_index : all_instances_attributes.
index_range()) {
991 const StringRef id = all_instances_attributes.
ids[attribute_index];
993 dst_instances->attributes_for_write()
994 .lookup_or_add_for_write_only_span(
id, domain, type)
999 MutableSpan<int> all_handles = dst_instances->reference_handles_for_write();
1001 for (
const int component_index : src_components.
index_range()) {
1003 *src_components[component_index]);
1005 const blender::float4x4 &src_base_transform = src_base_transforms[component_index];
1006 const Span<const void *> attribute_fallback_array = attribute_fallback[component_index].array;
1010 for (
const int src_handle : src_references.
index_range()) {
1011 handle_map[src_handle] = dst_instances->add_reference(src_references[src_handle]);
1013 const IndexRange dst_range = offsets[component_index];
1014 for (
const int attribute_index : all_instances_attributes.
index_range()) {
1015 const StringRef id = all_instances_attributes.
ids[attribute_index];
1017 const CPPType *cpp_type = bke::custom_data_type_to_cpp_type(type);
1020 dst_instances->attributes_for_write().lookup_for_write_span(
id);
1023 const void *attribute_ptr;
1024 if (attribute_fallback_array[attribute_index] !=
nullptr) {
1025 attribute_ptr = attribute_fallback_array[attribute_index];
1032 write_attribute.
finish();
1036 array_utils::gather(handle_map.
as_span(), src_handles, all_handles.
slice(dst_range));
1037 array_utils::copy(src_instances.
transforms(), all_transforms.
slice(dst_range));
1040 transform = src_base_transform *
transform;
1049 for_join_attributes.
append(component.get());
1054 join_attributes(for_join_attributes, dst_component, {
".reference_index",
"instance_transform"});
1067 bool &r_create_radii,
1071 in_geometry_set, bke::GeometryComponent::Type::PointCloud,
options, varied_depth_option);
1072 attributes_to_propagate.
remove(
"position");
1073 r_create_id = attributes_to_propagate.
pop_try(
"id").has_value();
1074 r_create_radii = attributes_to_propagate.
pop_try(
"radius").has_value();
1076 for (
const auto item : attributes_to_propagate.
items()) {
1077 ordered_attributes.
ids.add_new(item.key);
1078 ordered_attributes.
kinds.append(item.value);
1080 return ordered_attributes;
1087 if (pointcloud->totpoint > 0) {
1088 r_pointclouds.
add(pointcloud);
1092 instances->foreach_referenced_geometry([&](
const bke::GeometrySet &instance_geometry_set) {
1105 varied_depth_option,
1111 for (
const int pointcloud_index : info.
realize_info.index_range()) {
1123 if (attributes.contains(attribute_id)) {
1124 GVArray attribute = *attributes.lookup_or_default(attribute_id, domain, data_type);
1125 pointcloud_info.
attributes[attribute_index].emplace(std::move(attribute));
1130 if (ids_attribute) {
1135 pointcloud_info.
radii = *attributes.lookup_or_default(
1136 "radius", bke::AttrDomain::Point, 0.01f);
1139 "position", bke::AttrDomain::Point,
float3(0));
1159 pointcloud_info.
positions, task.transform, all_dst_positions.
slice(point_slice));
1172 task.attribute_fallbacks,
1175 BLI_assert(domain == bke::AttrDomain::Point);
1176 UNUSED_VARS_NDEBUG(domain);
1179 dst_attribute_writers);
1187 for (
const int attribute_index : ordered_attributes.
index_range()) {
1188 const void *value = attribute_fallbacks.
array[attribute_index];
1194 const CPPType &cpp_type = *bke::custom_data_type_to_cpp_type(data_type);
1195 GVArray gvaray(GVArray::ForSingle(cpp_type, attributes.domain_size(domain), value));
1196 attributes.add(ordered_attributes.
ids[attribute_index],
1212 if (tasks.
size() == 1) {
1217 new_points->tag_positions_changed();
1220 ordered_attributes, task.attribute_fallbacks, new_points->attributes_for_write());
1240 "position", bke::AttrDomain::Point);
1246 bke::AttrDomain::Point);
1251 bke::AttrDomain::Point);
1256 for (
const int attribute_index : ordered_attributes.
index_range()) {
1257 const StringRef attribute_id = ordered_attributes.
ids[attribute_index];
1260 attribute_id, bke::AttrDomain::Point, data_type));
1265 for (const int task_index : task_range) {
1266 const RealizePointCloudTask &task = tasks[task_index];
1267 execute_realize_pointcloud_task(options,
1270 dst_attribute_writers,
1278 for (GSpanAttributeWriter &dst_attribute : dst_attribute_writers) {
1279 dst_attribute.finish();
1282 point_radii.finish();
1297 bool &r_create_material_index)
1300 in_geometry_set, bke::GeometryComponent::Type::Mesh,
options, varied_depth_option);
1301 attributes_to_propagate.
remove(
"position");
1302 attributes_to_propagate.
remove(
".edge_verts");
1303 attributes_to_propagate.
remove(
".corner_vert");
1304 attributes_to_propagate.
remove(
".corner_edge");
1305 r_create_id = attributes_to_propagate.
pop_try(
"id").has_value();
1306 r_create_material_index = attributes_to_propagate.
pop_try(
"material_index").has_value();
1308 for (
const auto item : attributes_to_propagate.
items()) {
1309 ordered_attributes.
ids.add_new(item.key);
1310 ordered_attributes.
kinds.append(item.value);
1312 return ordered_attributes;
1319 if (mesh->verts_num > 0) {
1324 instances->foreach_referenced_geometry([&](
const bke::GeometrySet &instance_geometry_set) {
1338 varied_depth_option,
1344 if (mesh->totcol == 0) {
1349 for (
const int slot_index :
IndexRange(mesh->totcol)) {
1350 Material *material = mesh->mat[slot_index];
1357 for (
const int mesh_index : info.
realize_info.index_range()) {
1359 const Mesh *mesh = info.
order[mesh_index];
1361 mesh_info.
positions = mesh->vert_positions();
1362 mesh_info.
edges = mesh->edges();
1363 mesh_info.
faces = mesh->faces();
1369 if (mesh->totcol == 0) {
1373 for (
const int old_slot_index :
IndexRange(mesh->totcol)) {
1374 Material *material = mesh->mat[old_slot_index];
1387 if (attributes.contains(attribute_id)) {
1388 GVArray attribute = *attributes.lookup_or_default(attribute_id, domain, data_type);
1389 mesh_info.
attributes[attribute_index].emplace(std::move(attribute));
1394 if (ids_attribute) {
1399 "material_index", bke::AttrDomain::Face, 0);
1404 return mesh->runtime->loose_edges_cache.is_cached() && mesh->loose_edges().count == 0;
1408 return mesh->runtime->loose_verts_cache.is_cached() && mesh->loose_verts().count == 0;
1412 return mesh->no_overlapping_topology();
1431 const Mesh &mesh = *mesh_info.
mesh;
1439 const IndexRange dst_vert_range(task.start_indices.vertex, src_positions.
size());
1440 const IndexRange dst_edge_range(task.start_indices.edge, src_edges.
size());
1441 const IndexRange dst_face_range(task.start_indices.face, src_faces.
size());
1442 const IndexRange dst_loop_range(task.start_indices.loop, src_corner_verts.
size());
1451 for (const int i : vert_range) {
1452 dst_positions[i] = math::transform_point(task.transform, src_positions[i]);
1455 threading::parallel_for(src_edges.index_range(), 1024, [&](
const IndexRange edge_range) {
1456 for (const int i : edge_range) {
1457 dst_edges[i] = src_edges[i] + task.start_indices.vertex;
1460 threading::parallel_for(src_corner_verts.index_range(), 1024, [&](
const IndexRange loop_range) {
1461 for (const int i : loop_range) {
1462 dst_corner_verts[i] = src_corner_verts[i] + task.start_indices.vertex;
1465 threading::parallel_for(src_corner_edges.index_range(), 1024, [&](
const IndexRange loop_range) {
1466 for (const int i : loop_range) {
1467 dst_corner_edges[i] = src_corner_edges[i] + task.start_indices.edge;
1470 threading::parallel_for(src_faces.index_range(), 1024, [&](
const IndexRange face_range) {
1471 for (const int i : face_range) {
1472 dst_face_offsets[i] = src_faces[i].start() + task.start_indices.loop;
1475 if (!all_dst_material_indices.is_empty()) {
1476 const Span<int> material_index_map = mesh_info.material_index_map;
1477 MutableSpan<int> dst_material_indices = all_dst_material_indices.
slice(dst_face_range);
1478 if (mesh.totcol == 0) {
1480 dst_material_indices.
fill(material_index_map.first());
1483 if (mesh_info.material_indices.is_single()) {
1484 const int src_index = mesh_info.material_indices.get_internal_single();
1485 const bool valid = IndexRange(mesh.totcol).contains(src_index);
1486 dst_material_indices.fill(valid ? material_index_map[src_index] : 0);
1489 VArraySpan<int> indices_span(mesh_info.material_indices);
1490 threading::parallel_for(src_faces.index_range(), 1024, [&](
const IndexRange face_range) {
1491 for (const int i : face_range) {
1492 const int src_index = indices_span[i];
1493 const bool valid = IndexRange(mesh.totcol).contains(src_index);
1494 dst_material_indices[i] = valid ? material_index_map[src_index] : 0;
1501 if (!all_dst_vertex_ids.is_empty()) {
1503 mesh_info.stored_vertex_ids,
1505 all_dst_vertex_ids.slice(
task.start_indices.vertex, mesh.verts_num));
1509 mesh_info.attributes,
1510 task.attribute_fallbacks,
1512 [&](
const bke::AttrDomain domain) {
1514 case bke::AttrDomain::Point:
1515 return dst_vert_range;
1516 case bke::AttrDomain::Edge:
1517 return dst_edge_range;
1518 case bke::AttrDomain::Face:
1519 return dst_face_range;
1520 case bke::AttrDomain::Corner:
1521 return dst_loop_range;
1523 BLI_assert_unreachable();
1524 return IndexRange();
1527 dst_attribute_writers);
1541 if (tasks.
size() == 1) {
1546 new_mesh->tag_positions_changed();
1549 ordered_attributes, task.attribute_fallbacks, new_mesh->attributes_for_write());
1580 Material *material = ordered_materials[i];
1588 bke::AttrDomain::Point);
1594 "material_index", bke::AttrDomain::Face);
1599 for (
const int attribute_index : ordered_attributes.
index_range()) {
1600 const StringRef attribute_id = ordered_attributes.
ids[attribute_index];
1603 dst_attribute_writers.
append(
1608 if (active_layer !=
nullptr) {
1616 if (render_layer !=
nullptr) {
1624 for (const int task_index : task_range) {
1625 const RealizeMeshTask &task = tasks[task_index];
1626 execute_realize_mesh_task(options,
1629 dst_attribute_writers,
1636 material_indices.span);
1641 for (GSpanAttributeWriter &dst_attribute : dst_attribute_writers) {
1642 dst_attribute.finish();
1644 vertex_ids.finish();
1645 material_indices.finish();
1647 if (all_meshes_info.no_loose_edges_hint) {
1648 dst_mesh->tag_loose_edges_none();
1650 if (all_meshes_info.no_loose_verts_hint) {
1651 dst_mesh->tag_loose_verts_none();
1653 if (all_meshes_info.no_overlapping_hint) {
1654 dst_mesh->tag_overlapping_none();
1671 in_geometry_set, bke::GeometryComponent::Type::Curve,
options, varied_depth_option);
1672 attributes_to_propagate.
remove(
"position");
1673 attributes_to_propagate.
remove(
"radius");
1674 attributes_to_propagate.
remove(
"nurbs_weight");
1675 attributes_to_propagate.
remove(
"resolution");
1676 attributes_to_propagate.
remove(
"handle_right");
1677 attributes_to_propagate.
remove(
"handle_left");
1678 attributes_to_propagate.
remove(
"custom_normal");
1679 r_create_id = attributes_to_propagate.
pop_try(
"id").has_value();
1681 for (
const auto item : attributes_to_propagate.
items()) {
1682 ordered_attributes.
ids.add_new(item.key);
1683 ordered_attributes.
kinds.append(item.value);
1685 return ordered_attributes;
1692 if (curves->geometry.curve_num != 0) {
1693 r_curves.
add(curves);
1697 instances->foreach_referenced_geometry([&](
const bke::GeometrySet &instance_geometry_set) {
1713 for (
const int curve_index : info.
realize_info.index_range()) {
1715 const Curves *curves_id = info.
order[curve_index];
1717 curve_info.
curves = curves_id;
1726 if (attributes.contains(attribute_id)) {
1727 GVArray attribute = *attributes.lookup_or_default(attribute_id, domain, data_type);
1728 curve_info.
attributes[attribute_index].emplace(std::move(attribute));
1738 if (attributes.contains(
"radius")) {
1740 attributes.lookup<
float>(
"radius", bke::AttrDomain::Point).varray.get_internal_span();
1743 if (attributes.contains(
"nurbs_weight")) {
1744 curve_info.
nurbs_weight = attributes.lookup<
float>(
"nurbs_weight", bke::AttrDomain::Point)
1745 .varray.get_internal_span();
1749 if (attributes.contains(
"resolution")) {
1752 if (attributes.contains(
"handle_right")) {
1753 curve_info.
handle_left = attributes.lookup<
float3>(
"handle_left", bke::AttrDomain::Point)
1754 .varray.get_internal_span();
1755 curve_info.
handle_right = attributes.lookup<
float3>(
"handle_right", bke::AttrDomain::Point)
1756 .varray.get_internal_span();
1759 if (attributes.contains(
"custom_normal")) {
1760 curve_info.
custom_normal = attributes.lookup<
float3>(
"custom_normal", bke::AttrDomain::Point)
1761 .varray.get_internal_span();
1786 const IndexRange dst_point_range{task.start_indices.point, curves.points_num()};
1787 const IndexRange dst_curve_range{task.start_indices.curve, curves.curves_num()};
1799 curves_info.
handle_left, task.transform, all_handle_left.
slice(dst_point_range));
1806 curves_info.
handle_right, task.transform, all_handle_right.
slice(dst_point_range));
1810 auto copy_point_span_with_default =
1813 all_dst.
slice(dst_point_range).fill(value);
1816 all_dst.
slice(dst_point_range).copy_from(src);
1820 copy_point_span_with_default(curves_info.
radius, all_radii, 1.0f);
1823 copy_point_span_with_default(curves_info.
nurbs_weight, all_nurbs_weights, 1.0f);
1836 curves_info.
custom_normal, task.transform, all_custom_normals.
slice(dst_point_range));
1841 const Span<int> src_offsets = curves.offsets();
1843 threading::parallel_for(curves.curves_range(), 2048, [&](
const IndexRange range) {
1844 for (const int i : range) {
1845 dst_offsets[i] = task.start_indices.point + src_offsets[i];
1849 if (!all_dst_ids.is_empty()) {
1851 options, curves_info.stored_ids, task.id, all_dst_ids.slice(dst_point_range));
1854 copy_generic_attributes_to_result(
1855 curves_info.attributes,
1856 task.attribute_fallbacks,
1858 [&](
const bke::AttrDomain domain) {
1860 case bke::AttrDomain::Point:
1861 return IndexRange(task.start_indices.point, curves.points_num());
1862 case bke::AttrDomain::Curve:
1863 return IndexRange(task.start_indices.curve, curves.curves_num());
1865 BLI_assert_unreachable();
1866 return IndexRange();
1869 dst_attribute_writers);
1882 if (tasks.
size() == 1) {
1886 new_curves->
geometry.wrap().transform(task.transform);
1889 task.attribute_fallbacks,
1890 new_curves->
geometry.wrap().attributes_for_write());
1901 Curves *dst_curves_id = bke::curves_new_nomain(points_num, curves_num);
1910 bke::curves_copy_parameters(first_curves_id, *dst_curves_id);
1916 bke::AttrDomain::Point);
1921 for (
const int attribute_index : ordered_attributes.
index_range()) {
1922 const StringRef attribute_id = ordered_attributes.
ids[attribute_index];
1925 dst_attribute_writers.
append(
1934 bke::AttrDomain::Point);
1936 "handle_right", bke::AttrDomain::Point);
1942 bke::AttrDomain::Point);
1947 bke::AttrDomain::Point);
1952 bke::AttrDomain::Curve);
1957 "custom_normal", bke::AttrDomain::Point);
1962 for (const int task_index : task_range) {
1963 const RealizeCurveTask &task = tasks[task_index];
1964 execute_realize_curve_task(options,
1969 dst_attribute_writers,
1976 custom_normal.span);
1981 dst_curves.runtime->type_counts.fill(0);
1982 for (
const RealizeCurveTask &task : tasks) {
1984 dst_curves.runtime->type_counts[i] +=
1985 task.curve_info->curves->geometry.runtime->type_counts[i];
1990 for (GSpanAttributeWriter &dst_attribute : dst_attribute_writers) {
1991 dst_attribute.finish();
1995 resolution.finish();
1996 nurbs_weight.finish();
1997 handle_left.finish();
1998 handle_right.finish();
1999 custom_normal.finish();
2014 in_geometry_set, bke::GeometryComponent::Type::GreasePencil,
options, varied_depth_options);
2016 for (
auto &&item : attributes_to_propagate.
items()) {
2017 ordered_attributes.
ids.add_new(item.key);
2018 ordered_attributes.
kinds.append(item.value);
2020 return ordered_attributes;
2027 if (!grease_pencil->layers().is_empty()) {
2028 r_grease_pencils.
add(grease_pencil);
2032 instances->foreach_referenced_geometry([&](
const bke::GeometrySet &instance_geometry_set) {
2045 geometry_set,
options, varied_depth_options);
2049 for (
const int grease_pencil_index : info.
realize_info.index_range()) {
2060 if (attributes.contains(attribute_id)) {
2061 GVArray attribute = *attributes.lookup_or_default(attribute_id, domain, data_type);
2062 grease_pencil_info.
attributes[attribute_index].emplace(std::move(attribute));
2084 const IndexRange dst_layers_slice{task.start_index, src_layers.
size()};
2088 for (
const int layer_i : src_layers.
index_range()) {
2093 dst_layer.set_name(src_layer.name());
2104 dst_curves = src_curves;
2110 for (
int &material_index : material_indices.
span) {
2115 material_indices.
finish();
2120 task.attribute_fallbacks,
2123 BLI_assert(domain == bke::AttrDomain::Layer);
2124 UNUSED_VARS_NDEBUG(domain);
2125 return dst_layers_slice;
2127 dst_attribute_writers);
2134 layer->set_local_transform(transform * layer->local_transform());
2148 if (tasks.
size() == 1) {
2155 ordered_attributes, task.attribute_fallbacks, new_gp->attributes_for_write());
2161 const int new_layers_num = last_task.
start_index +
2167 *dst_grease_pencil);
2171 dst_grease_pencil->add_layers_with_empty_drawings_for_eval(new_layers_num);
2187 for (
const int attribute_index : ordered_attributes.
index_range()) {
2188 const StringRef attribute_id = ordered_attributes.
ids[attribute_index];
2191 attribute_id, bke::AttrDomain::Layer, data_type));
2196 for (const int task_index : task_range) {
2197 const RealizeGreasePencilTask &task = tasks[task_index];
2198 execute_realize_grease_pencil_task(
2199 task, ordered_attributes, *dst_grease_pencil, dst_attribute_writers);
2204 for (GSpanAttributeWriter &dst_attribute : dst_attribute_writers) {
2205 dst_attribute.finish();
2221 if (!component.curves_edit_hints_) {
2222 if (task.edit_data->curves_edit_hints_) {
2224 *task.edit_data->curves_edit_hints_);
2227 if (
const bke::GizmoEditHints *src_gizmo_edit_hints = task.edit_data->gizmo_edit_hints_.get())
2229 if (!component.gizmo_edit_hints_) {
2230 component.gizmo_edit_hints_ = std::make_unique<bke::GizmoEditHints>();
2232 for (
auto item : src_gizmo_edit_hints->gizmo_transforms.items()) {
2233 component.gizmo_edit_hints_->gizmo_transforms.add(item.key, task.transform * item.value);
2249 instances->attributes_for_write().remove(
"id");
2265 inverse_selection_indices);
2267 if (inverse_selection.
is_empty()) {
2271 std::unique_ptr<Instances> new_instances = std::make_unique<Instances>(instances);
2272 new_instances->remove(inverse_selection, attribute_filter);
2276 new_instances_components.
replace(new_instances.release(), bke::GeometryOwnershipType::Owned);
2283 return geometry_set;
2305 return geometry_set;
2310 geometry_set, varied_depth_option.
selection, not_to_realize_set,
options.attribute_filter);
2312 if (
options.keep_original_ids) {
2317 geometry_set,
options, varied_depth_option);
2321 geometry_set,
options, varied_depth_option);
2323 geometry_set,
options, varied_depth_option);
2332 all_grease_pencils_info,
2333 all_instance_attributes,
2334 create_id_attribute,
2336 varied_depth_option.
depths,
2346 const float4x4 transform = float4x4::identity();
2350 gather_info, 0, VariedDepthOptions::MAX_DEPTH, geometry_set, transform, attribute_fallbacks);
2355 all_instance_attributes,
2362 const int64_t approximate_used_bytes_num = total_points_num * 32;
2363 threading::memory_bandwidth_bound_task(approximate_used_bytes_num, [&]() {
2365 all_pointclouds_info,
2390 return new_geometry_set;
struct Curves * BKE_curves_copy_for_eval(const struct Curves *curves_src)
Low-level operations for curves.
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_named_layer(const CustomData *data, eCustomDataType type, blender::StringRef name)
void CustomData_set_layer_render(CustomData *data, eCustomDataType type, int n)
const char * CustomData_get_render_layer_name(const CustomData *data, eCustomDataType type)
const char * CustomData_get_active_layer_name(const CustomData *data, eCustomDataType type)
void CustomData_set_layer_active(CustomData *data, eCustomDataType type, int n)
Low-level operations for grease pencil.
void BKE_grease_pencil_copy_parameters(const GreasePencil &src, GreasePencil &dst)
GreasePencil * BKE_grease_pencil_new_nomain()
void BKE_grease_pencil_copy_layer_parameters(const blender::bke::greasepencil::Layer &src, blender::bke::greasepencil::Layer &dst)
GreasePencil * BKE_grease_pencil_copy_for_eval(const GreasePencil *grease_pencil_src)
General operations, lookup, etc. for materials.
void BKE_id_material_eval_assign(struct ID *id, int slot, struct Material *material)
void BKE_mesh_copy_parameters_for_eval(Mesh *me_dst, const Mesh *me_src)
Mesh * BKE_mesh_new_nomain(int verts_num, int edges_num, int faces_num, int corners_num)
Mesh * BKE_mesh_copy_for_eval(const Mesh &source)
General operations for point clouds.
PointCloud * BKE_pointcloud_copy_for_eval(const PointCloud *pointcloud_src)
PointCloud * BKE_pointcloud_new_nomain(int totpoint)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Object groups, one object can be in many groups at once.
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
Span< T > as_span() const
void reinitialize(const int64_t new_size)
void fill_assign_n(const void *value, void *dst, int64_t n) const
const void * default_value() const
GMutableSpan slice(const int64_t start, int64_t size) const
const CPPType & type() const
const CPPType & type() const
GSpan get_internal_span() const
constexpr int64_t size() const
std::optional< Value > pop_try(const Key &key)
bool remove(const Key &key)
ItemIterator items() const
auto add_or_modify(const Key &key, const CreateValueF &create_value, const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr bool is_empty() const
constexpr void fill(const T &value) const
constexpr IndexRange index_range() const
constexpr void copy_from(Span< T > values) const
constexpr T & last(const int64_t n=0) const
bool add_as(ForwardKey &&key)
constexpr Span slice(int64_t start, int64_t size) const
constexpr const T & first() const
constexpr int64_t size() const
constexpr const T & last(const int64_t n=0) const
constexpr IndexRange index_range() const
constexpr bool is_empty() const
std::optional< T > get_if_single() const
void materialize(MutableSpan< T > r_span) const
Span< T > get_internal_span() const
int64_t index_of(const Key &key) const
const Key * begin() const
int64_t index_of_or_add(const Key &key)
void append(const T &value)
IndexRange index_range() const
void foreach_attribute(const FunctionRef< void(const AttributeIter &)> fn) const
eCustomDataType data_type
GAttributeReader get() const
MutableSpan< float3 > positions_for_write()
MutableAttributeAccessor attributes_for_write()
MutableSpan< int > offsets_for_write()
void convert_to_initialized_n(GSpan from_span, GMutableSpan to_span) const
bool is_convertible(const CPPType &from_type, const CPPType &to_type) const
std::unique_ptr< CurvesEditHints > curves_edit_hints_
int attribute_domain_size(AttrDomain domain) const
const Instances * get() const
GeometryComponentPtr copy() const override
void replace(Instances *instances, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
Span< int > reference_handles() const
Span< float4x4 > transforms() const
Span< InstanceReference > references() const
int instances_num() const
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type)
bke::CurvesGeometry & strokes_for_write()
const bke::CurvesGeometry & strokes() const
void set_local_transform(const float4x4 &transform)
float4x4 local_transform() const
IndexMask complement(const IndexMask &universe, IndexMaskMemory &memory) const
void foreach_index(Fn &&fn) const
CCL_NAMESPACE_BEGIN struct Options options
static void transform_positions(const Span< blender::float3 > src, const blender::float4x4 &transform, blender::MutableSpan< blender::float3 > dst)
void *(* MEM_dupallocN)(const void *vmemh)
struct blender::compositor::@172::@174 task
static void propagate_instances_to_keep(const bke::GeometrySet &geometry_set, const IndexMask &selection, bke::GeometrySet &new_geometry_set, const bke::AttributeFilter &attribute_filter)
static void execute_realize_mesh_tasks(const RealizeInstancesOptions &options, const AllMeshesInfo &all_meshes_info, const Span< RealizeMeshTask > tasks, const OrderedAttributes &ordered_attributes, const VectorSet< Material * > &ordered_materials, bke::GeometrySet &r_realized_geometry)
static void gather_realize_tasks_recursive(GatherTasksInfo &gather_info, const int current_depth, const int target_depth, const bke::GeometrySet &geometry_set, const float4x4 &base_transform, const InstanceContext &base_instance_context)
static OrderedAttributes gather_generic_pointcloud_attributes_to_propagate(const bke::GeometrySet &in_geometry_set, const RealizeInstancesOptions &options, const VariedDepthOptions &varied_depth_option, bool &r_create_radii, bool &r_create_id)
static void execute_instances_tasks(const Span< bke::GeometryComponentPtr > src_components, Span< blender::float4x4 > src_base_transforms, OrderedAttributes all_instances_attributes, Span< blender::geometry::AttributeFallbacksArray > attribute_fallback, bke::GeometrySet &r_realized_geometry)
static void execute_realize_pointcloud_tasks(const RealizeInstancesOptions &options, const AllPointCloudsInfo &all_pointclouds_info, const Span< RealizePointCloudTask > tasks, const OrderedAttributes &ordered_attributes, bke::GeometrySet &r_realized_geometry)
static void threaded_copy(const GSpan src, GMutableSpan dst)
static void execute_realize_curve_task(const RealizeInstancesOptions &options, const AllCurvesInfo &all_curves_info, const RealizeCurveTask &task, const OrderedAttributes &ordered_attributes, bke::CurvesGeometry &dst_curves, MutableSpan< GSpanAttributeWriter > dst_attribute_writers, MutableSpan< int > all_dst_ids, MutableSpan< float3 > all_handle_left, MutableSpan< float3 > all_handle_right, MutableSpan< float > all_radii, MutableSpan< float > all_nurbs_weights, MutableSpan< int > all_resolutions, MutableSpan< float3 > all_custom_normals)
static AllMeshesInfo preprocess_meshes(const bke::GeometrySet &geometry_set, const RealizeInstancesOptions &options, const VariedDepthOptions &varied_depth_option)
static void gather_grease_pencils_to_realize(const bke::GeometrySet &geometry_set, VectorSet< const GreasePencil * > &r_grease_pencils)
static void execute_realize_pointcloud_task(const RealizeInstancesOptions &options, const RealizePointCloudTask &task, const OrderedAttributes &ordered_attributes, MutableSpan< GSpanAttributeWriter > dst_attribute_writers, MutableSpan< float > all_dst_radii, MutableSpan< int > all_dst_ids, MutableSpan< float3 > all_dst_positions)
static int64_t get_final_points_num(const GatherTasks &tasks)
static void gather_pointclouds_to_realize(const bke::GeometrySet &geometry_set, VectorSet< const PointCloud * > &r_pointclouds)
static void execute_realize_grease_pencil_task(const RealizeGreasePencilTask &task, const OrderedAttributes &ordered_attributes, GreasePencil &dst_grease_pencil, MutableSpan< GSpanAttributeWriter > dst_attribute_writers)
static void execute_realize_curve_tasks(const RealizeInstancesOptions &options, const AllCurvesInfo &all_curves_info, const Span< RealizeCurveTask > tasks, const OrderedAttributes &ordered_attributes, bke::GeometrySet &r_realized_geometry)
static OrderedAttributes gather_generic_curve_attributes_to_propagate(const bke::GeometrySet &in_geometry_set, const RealizeInstancesOptions &options, const VariedDepthOptions &varied_depth_option, bool &r_create_id)
static void gather_realize_tasks_for_instances(GatherTasksInfo &gather_info, const int current_depth, const int target_depth, const Instances &instances, const float4x4 &base_transform, const InstanceContext &base_instance_context)
static void remove_id_attribute_from_instances(bke::GeometrySet &geometry_set)
static void create_result_ids(const RealizeInstancesOptions &options, const Span< int > stored_ids, const int task_id, MutableSpan< int > dst_ids)
static void gather_curves_to_realize(const bke::GeometrySet &geometry_set, VectorSet< const Curves * > &r_curves)
static void transform_grease_pencil_layers(Span< bke::greasepencil::Layer * > layers, const float4x4 &transform)
static void copy_generic_attributes_to_result(const Span< std::optional< GVArraySpan > > src_attributes, const AttributeFallbacksArray &attribute_fallbacks, const OrderedAttributes &ordered_attributes, const FunctionRef< IndexRange(bke::AttrDomain)> &range_fn, MutableSpan< GSpanAttributeWriter > dst_attribute_writers)
void join_attributes(const Span< const bke::GeometryComponent * > src_components, bke::GeometryComponent &r_result, const Span< StringRef > ignored_attributes={})
static void copy_transformed_normals(const Span< float3 > src, const float4x4 &transform, MutableSpan< float3 > dst)
static void gather_attribute_propagation_components_with_custom_depths(const bke::GeometrySet &geometry, const bke::GeometryComponent::Type component_type, const RealizeInstancesOptions &options, const VariedDepthOptions &varied_depth_option, Set< bke::GeometryComponentPtr > &r_components)
static Vector< std::pair< int, GSpan > > prepare_attribute_fallbacks(GatherTasksInfo &gather_info, const Instances &instances, const OrderedAttributes &ordered_attributes)
static AllPointCloudsInfo preprocess_pointclouds(const bke::GeometrySet &geometry_set, const RealizeInstancesOptions &options, const VariedDepthOptions &varied_depth_option)
static void execute_realize_mesh_task(const RealizeInstancesOptions &options, const RealizeMeshTask &task, const OrderedAttributes &ordered_attributes, MutableSpan< GSpanAttributeWriter > dst_attribute_writers, MutableSpan< float3 > all_dst_positions, MutableSpan< int2 > all_dst_edges, MutableSpan< int > all_dst_face_offsets, MutableSpan< int > all_dst_corner_verts, MutableSpan< int > all_dst_corner_edges, MutableSpan< int > all_dst_vertex_ids, MutableSpan< int > all_dst_material_indices)
static Map< StringRef, AttributeKind > gather_attributes_to_propagate(const bke::GeometrySet &geometry, const bke::GeometryComponent::Type component_type, const RealizeInstancesOptions &options, const VariedDepthOptions &varied_depth_option)
static AllCurvesInfo preprocess_curves(const bke::GeometrySet &geometry_set, const RealizeInstancesOptions &options, const VariedDepthOptions &varied_depth_option)
static void gather_meshes_to_realize(const bke::GeometrySet &geometry_set, VectorSet< const Mesh * > &r_meshes)
static void add_instance_attributes_to_single_geometry(const OrderedAttributes &ordered_attributes, const AttributeFallbacksArray &attribute_fallbacks, bke::MutableAttributeAccessor attributes)
static AllGreasePencilsInfo preprocess_grease_pencils(const bke::GeometrySet &geometry_set, const RealizeInstancesOptions &options, const VariedDepthOptions &varied_depth_options)
static OrderedAttributes gather_generic_instance_attributes_to_propagate(const bke::GeometrySet &in_geometry_set, const RealizeInstancesOptions &options, const VariedDepthOptions &varied_depth_option)
static void foreach_geometry_in_reference(const InstanceReference &reference, const float4x4 &base_transform, const uint32_t id, FunctionRef< void(const bke::GeometrySet &geometry_set, const float4x4 &transform, uint32_t id)> fn)
static void threaded_fill(const GPointer value, GMutableSpan dst)
static void execute_realize_edit_data_tasks(const Span< RealizeEditDataTask > tasks, bke::GeometrySet &r_realized_geometry)
static bool skip_transform(const float4x4 &transform)
static OrderedAttributes gather_generic_grease_pencil_attributes_to_propagate(const bke::GeometrySet &in_geometry_set, const RealizeInstancesOptions &options, const VariedDepthOptions &varied_depth_options)
bke::GeometrySet realize_instances(bke::GeometrySet geometry_set, const RealizeInstancesOptions &options)
static void gather_attribute_propagation_components(const bke::GeometrySet &geometry, const bke::GeometryComponent::Type component_type, const RealizeInstancesOptions &options, const int current_depth, const std::optional< int > max_depth, Set< bke::GeometryComponentPtr > &r_components)
static void execute_realize_grease_pencil_tasks(const AllGreasePencilsInfo &all_grease_pencils_info, const Span< RealizeGreasePencilTask > tasks, const OrderedAttributes &ordered_attributes, bke::GeometrySet &r_realized_geometry)
static void copy_transformed_positions(const Span< float3 > src, const float4x4 &transform, MutableSpan< float3 > dst)
static OrderedAttributes gather_generic_mesh_attributes_to_propagate(const bke::GeometrySet &in_geometry_set, const RealizeInstancesOptions &options, const VariedDepthOptions &varied_depth_option, bool &r_create_id, bool &r_create_material_index)
MatBase< T, NumCol, NumRow > transpose(const MatBase< T, NumRow, NumCol > &mat)
CartesianBasis invert(const CartesianBasis &basis)
bool is_equal(const MatBase< T, NumCol, NumRow > &a, const MatBase< T, NumCol, NumRow > &b, const T epsilon=T(0))
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
void uninitialized_copy_n(const T *src, int64_t n, T *dst)
struct Material ** material_array
ListBase vertex_group_names
static MatBase identity()
bool allow_skip(const StringRef name) const
GeometryComponent & get_component_for_write(GeometryComponent::Type component_type)
void replace_instances(Instances *instances, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
Instances * get_instances_for_write()
const GreasePencil * get_grease_pencil() const
Vector< const GeometryComponent * > get_components() const
void replace_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
const Curves * get_curves() const
const Instances * get_instances() const
bool has_instances() const
void replace_curves(Curves *curves, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
const PointCloud * get_pointcloud() const
const Mesh * get_mesh() const
void modify_geometry_sets(ForeachSubGeometryCallback callback)
void replace_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
void add(const GeometryComponent &component)
void replace_grease_pencil(GreasePencil *grease_pencil, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
MutableVArraySpan< T > span
bool create_handle_postion_attributes
OrderedAttributes attributes
bool create_radius_attribute
bool create_custom_normal_attribute
VectorSet< const Curves * > order
Array< RealizeCurveInfo > realize_info
bool create_resolution_attribute
bool create_nurbs_weight_attribute
VectorSet< Material * > materials
VectorSet< const GreasePencil * > order
OrderedAttributes attributes
Array< GreasePencilRealizeInfo > realize_info
Vector< AttributeFallbacksArray > attribute_fallback
Vector< float4x4 > instances_components_transforms
Vector< bke::GeometryComponentPtr > instances_components_to_merge
VectorSet< Material * > materials
VectorSet< const Mesh * > order
bool create_material_index_attribute
OrderedAttributes attributes
Array< MeshRealizeInfo > realize_info
Array< PointCloudRealizeInfo > realize_info
VectorSet< const PointCloud * > order
OrderedAttributes attributes
bool create_radius_attribute
AttributeFallbacksArray(int size)
Array< const void * > array
MeshElementStartIndices mesh_offsets
int grease_pencil_layer_offset
CurvesElementStartIndices curves_offsets
const AllPointCloudsInfo & pointclouds
const AllCurvesInfo & curves
const VArray< int > & depths
const AllMeshesInfo & meshes
bool create_id_attribute_on_any_component
AllInstancesInfo instances
Vector< std::unique_ptr< GArray<> > > & r_temporary_arrays
const OrderedAttributes & instances_attriubutes
const AllGreasePencilsInfo & grease_pencils
Vector< RealizeMeshTask > mesh_tasks
Vector< RealizeEditDataTask > edit_data_tasks
Vector< RealizePointCloudTask > pointcloud_tasks
Vector< RealizeCurveTask > curve_tasks
ImplicitSharingPtr< const bke::VolumeComponent > first_volume
Vector< RealizeGreasePencilTask > grease_pencil_tasks
Array< std::optional< GVArraySpan > > attributes
Array< int > material_index_map
const GreasePencil * grease_pencil
AttributeFallbacksArray grease_pencils
AttributeFallbacksArray instances
InstanceContext(const GatherTasksInfo &gather_info)
AttributeFallbacksArray meshes
AttributeFallbacksArray pointclouds
AttributeFallbacksArray curves
Span< int > stored_vertex_ids
VArray< int > material_indices
OffsetIndices< int > faces
Array< std::optional< GVArraySpan > > attributes
Array< int > material_index_map
IndexRange index_range() const
VectorSet< StringRef > ids
Vector< AttributeKind > kinds
Array< std::optional< GVArraySpan > > attributes
const PointCloud * pointcloud
Span< float3 > custom_normal
Span< float3 > handle_left
Span< float3 > handle_right
Array< std::optional< GVArraySpan > > attributes
Span< float > nurbs_weight
const RealizeCurveInfo * curve_info
AttributeFallbacksArray attribute_fallbacks
CurvesElementStartIndices start_indices
const bke::GeometryComponentEditData * edit_data
AttributeFallbacksArray attribute_fallbacks
const GreasePencilRealizeInfo * grease_pencil_info
AttributeFallbacksArray attribute_fallbacks
const MeshRealizeInfo * mesh_info
MeshElementStartIndices start_indices
AttributeFallbacksArray attribute_fallbacks
const PointCloudRealizeInfo * pointcloud_info