Blender V4.3
realize_instances.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
7
9
10#include "BLI_array_utils.hh"
11#include "BLI_noise.hh"
12
13#include "BKE_curves.hh"
14#include "BKE_customdata.hh"
15#include "BKE_deform.hh"
18#include "BKE_grease_pencil.hh"
19#include "BKE_instances.hh"
20#include "BKE_material.h"
21#include "BKE_mesh.hh"
22#include "BKE_pointcloud.hh"
24
25namespace blender::geometry {
26
28using blender::bke::AttributeKind;
29using blender::bke::AttributeMetaData;
30using blender::bke::GSpanAttributeWriter;
31using blender::bke::InstanceReference;
32using blender::bke::Instances;
33using blender::bke::SpanAttributeWriter;
34
42
43 int size() const
44 {
45 return this->kinds.size();
46 }
47
49 {
50 return this->kinds.index_range();
51 }
52};
53
65
75
87
90 int vertex = 0;
91 int edge = 0;
92 int face = 0;
93 int loop = 0;
94};
95
112
122
162
165 int point = 0;
166 int curve = 0;
167};
168
179
187
195
200
211
229
244
255
264
277
285
316
332 uint32_t id = 0;
333
335 : pointclouds(gather_info.pointclouds.attributes.size()),
336 meshes(gather_info.meshes.attributes.size()),
337 curves(gather_info.curves.attributes.size()),
338 grease_pencils(gather_info.grease_pencils.attributes.size()),
339 instances(gather_info.instances_attriubutes.size())
340 {
341 // empty
342 }
343};
344
346{
347 int64_t points_num = 0;
348 if (!tasks.pointcloud_tasks.is_empty()) {
349 const RealizePointCloudTask &task = tasks.pointcloud_tasks.last();
350 points_num += task.start_index + task.pointcloud_info->pointcloud->totpoint;
351 }
352 if (!tasks.mesh_tasks.is_empty()) {
353 const RealizeMeshTask &task = tasks.mesh_tasks.last();
354 points_num += task.start_indices.vertex + task.mesh_info->mesh->verts_num;
355 }
356 if (!tasks.curve_tasks.is_empty()) {
357 const RealizeCurveTask &task = tasks.curve_tasks.last();
358 points_num += task.start_indices.point + task.curve_info->curves->geometry.point_num;
359 }
360 return points_num;
361}
362
364{
366}
367
369 const float4x4 &transform,
371{
373 dst.copy_from(src);
374 }
375 else {
376 threading::parallel_for(src.index_range(), 1024, [&](const IndexRange range) {
377 for (const int i : range) {
378 dst[i] = math::transform_point(transform, src[i]);
379 }
380 });
381 }
382}
383
385{
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]);
389 }
390 });
391}
392
394 const float4x4 &transform,
396{
397 const float3x3 normal_transform = math::transpose(math::invert(float3x3(transform)));
398 if (math::is_equal(normal_transform, float3x3::identity(), 1e-6f)) {
399 dst.copy_from(src);
400 }
401 else {
402 threading::parallel_for(src.index_range(), 1024, [&](const IndexRange range) {
403 for (const int i : range) {
404 dst[i] = normal_transform * src[i];
405 }
406 });
407 }
408}
409
410static void threaded_copy(const GSpan src, GMutableSpan dst)
411{
412 BLI_assert(src.size() == dst.size());
413 BLI_assert(src.type() == dst.type());
414 threading::parallel_for(IndexRange(src.size()), 1024, [&](const IndexRange range) {
415 src.type().copy_construct_n(src.slice(range).data(), dst.slice(range).data(), range.size());
416 });
417}
418
419static void threaded_fill(const GPointer value, GMutableSpan dst)
420{
421 BLI_assert(*value.type() == dst.type());
422 threading::parallel_for(IndexRange(dst.size()), 1024, [&](const IndexRange range) {
423 value.type()->fill_construct_n(value.get(), dst.slice(range).data(), range.size());
424 });
425}
426
428 const Span<std::optional<GVArraySpan>> src_attributes,
429 const AttributeFallbacksArray &attribute_fallbacks,
430 const OrderedAttributes &ordered_attributes,
431 const FunctionRef<IndexRange(bke::AttrDomain)> &range_fn,
432 MutableSpan<GSpanAttributeWriter> dst_attribute_writers)
433{
435 dst_attribute_writers.index_range(), 10, [&](const IndexRange attribute_range) {
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);
439
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);
443 }
444 else {
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);
450 }
451 }
452 });
453}
454
456 const Span<int> stored_ids,
457 const int task_id,
458 MutableSpan<int> dst_ids)
459{
460 if (options.keep_original_ids) {
461 if (stored_ids.is_empty()) {
462 dst_ids.fill(0);
463 }
464 else {
465 dst_ids.copy_from(stored_ids);
466 }
467 }
468 else {
469 if (stored_ids.is_empty()) {
470 threading::parallel_for(dst_ids.index_range(), 1024, [&](const IndexRange range) {
471 for (const int i : range) {
472 dst_ids[i] = noise::hash(task_id, i);
473 }
474 });
475 }
476 else {
477 threading::parallel_for(dst_ids.index_range(), 1024, [&](const IndexRange range) {
478 for (const int i : range) {
479 dst_ids[i] = noise::hash(task_id, stored_ids[i]);
480 }
481 });
482 }
483 }
484}
485
486/* -------------------------------------------------------------------- */
489
490/* Forward declaration. */
491static void gather_realize_tasks_recursive(GatherTasksInfo &gather_info,
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);
497
504 GatherTasksInfo &gather_info,
505 const Instances &instances,
506 const OrderedAttributes &ordered_attributes)
507{
508 Vector<std::pair<int, GSpan>> attributes_to_override;
509 const bke::AttributeAccessor attributes = instances.attributes();
510 attributes.foreach_attribute([&](const bke::AttributeIter &iter) {
511 const int attribute_index = ordered_attributes.ids.index_of_try(iter.name);
512 if (attribute_index == -1) {
513 /* The attribute is not propagated to the final geometry. */
514 return;
515 }
516 const bke::GAttributeReader attribute = iter.get();
517 if (!attribute || !attribute.varray.is_span()) {
518 return;
519 }
520 GSpan span = attribute.varray.get_internal_span();
521 const eCustomDataType expected_type = ordered_attributes.kinds[attribute_index].data_type;
522 if (iter.data_type != expected_type) {
523 const CPPType &from_type = span.type();
524 const CPPType &to_type = *bke::custom_data_type_to_cpp_type(expected_type);
526 if (!conversions.is_convertible(from_type, to_type)) {
527 /* Ignore the attribute because it can not be converted to the desired type. */
528 return;
529 }
530 /* Convert the attribute on the instances component to the expected attribute type. */
531 std::unique_ptr<GArray<>> temporary_array = std::make_unique<GArray<>>(
532 to_type, instances.instances_num());
533 conversions.convert_to_initialized_n(span, temporary_array->as_mutable_span());
534 span = temporary_array->as_span();
535 gather_info.r_temporary_arrays.append(std::move(temporary_array));
536 }
537 attributes_to_override.append({attribute_index, span});
538 });
539 return attributes_to_override;
540}
541
547 const InstanceReference &reference,
548 const float4x4 &base_transform,
549 const uint32_t id,
550 FunctionRef<void(const bke::GeometrySet &geometry_set, const float4x4 &transform, uint32_t id)>
551 fn)
552{
553 bke::GeometrySet geometry_set;
554 reference.to_geometry_set(geometry_set);
555 fn(geometry_set, base_transform, id);
556}
557
559 const int current_depth,
560 const int target_depth,
561 const Instances &instances,
562 const float4x4 &base_transform,
563 const InstanceContext &base_instance_context)
564{
565 const Span<InstanceReference> references = instances.references();
566 const Span<int> handles = instances.reference_handles();
567 const Span<float4x4> transforms = instances.transforms();
568
569 Span<int> stored_instance_ids;
570 if (gather_info.create_id_attribute_on_any_component) {
571 bke::AttributeReader ids = instances.attributes().lookup<int>("id");
572 if (ids) {
573 stored_instance_ids = ids.varray.get_internal_span();
574 }
575 }
576
577 /* Prepare attribute fallbacks. */
578 InstanceContext instance_context = base_instance_context;
579 Vector<std::pair<int, GSpan>> pointcloud_attributes_to_override = prepare_attribute_fallbacks(
580 gather_info, instances, gather_info.pointclouds.attributes);
581 Vector<std::pair<int, GSpan>> mesh_attributes_to_override = prepare_attribute_fallbacks(
582 gather_info, instances, gather_info.meshes.attributes);
583 Vector<std::pair<int, GSpan>> curve_attributes_to_override = prepare_attribute_fallbacks(
584 gather_info, instances, gather_info.curves.attributes);
585 Vector<std::pair<int, GSpan>> grease_pencil_attributes_to_override = prepare_attribute_fallbacks(
586 gather_info, instances, gather_info.grease_pencils.attributes);
587 Vector<std::pair<int, GSpan>> instance_attributes_to_override = prepare_attribute_fallbacks(
588 gather_info, instances, gather_info.instances_attriubutes);
589
590 const bool is_top_level = current_depth == 0;
591 /* If at top level, get instance indices from selection field, else use all instances. */
592 const IndexMask indices = is_top_level ? gather_info.selection :
593 IndexMask(IndexRange(instances.instances_num()));
594 indices.foreach_index([&](const int i) {
595 /* If at top level, retrieve depth from gather_info, else continue with target_depth. */
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];
599 const InstanceReference &reference = references[handle];
600 const float4x4 new_base_transform = base_transform * transform;
601
602 /* Update attribute fallbacks for the current instance. */
603 for (const std::pair<int, GSpan> &pair : pointcloud_attributes_to_override) {
604 instance_context.pointclouds.array[pair.first] = pair.second[i];
605 }
606 for (const std::pair<int, GSpan> &pair : mesh_attributes_to_override) {
607 instance_context.meshes.array[pair.first] = pair.second[i];
608 }
609 for (const std::pair<int, GSpan> &pair : curve_attributes_to_override) {
610 instance_context.curves.array[pair.first] = pair.second[i];
611 }
612 for (const std::pair<int, GSpan> &pair : grease_pencil_attributes_to_override) {
613 instance_context.grease_pencils.array[pair.first] = pair.second[i];
614 }
615 for (const std::pair<int, GSpan> &pair : instance_attributes_to_override) {
616 instance_context.instances.array[pair.first] = pair.second[i];
617 }
618
619 uint32_t local_instance_id = 0;
620 if (gather_info.create_id_attribute_on_any_component) {
621 if (stored_instance_ids.is_empty()) {
622 local_instance_id = uint32_t(i);
623 }
624 else {
625 local_instance_id = uint32_t(stored_instance_ids[i]);
626 }
627 }
628 const uint32_t instance_id = noise::hash(base_instance_context.id, local_instance_id);
629
630 /* Add realize tasks for all referenced geometry sets recursively. */
632 new_base_transform,
633 instance_id,
634 [&](const bke::GeometrySet &instance_geometry_set,
635 const float4x4 &transform,
636 const uint32_t id) {
637 instance_context.id = id;
639 current_depth + 1,
640 child_target_depth,
641 instance_geometry_set,
642 transform,
643 instance_context);
644 });
645 });
646}
647
652 const int current_depth,
653 const int target_depth,
654 const bke::GeometrySet &geometry_set,
655 const float4x4 &base_transform,
656 const InstanceContext &base_instance_context)
657{
658 for (const bke::GeometryComponent *component : geometry_set.get_components()) {
659 const bke::GeometryComponent::Type type = component->type();
660 switch (type) {
662 const Mesh *mesh = (*static_cast<const bke::MeshComponent *>(component)).get();
663 if (mesh != nullptr && mesh->verts_num > 0) {
664 const int mesh_index = gather_info.meshes.order.index_of(mesh);
665 const MeshRealizeInfo &mesh_info = gather_info.meshes.realize_info[mesh_index];
666 gather_info.r_tasks.mesh_tasks.append({gather_info.r_offsets.mesh_offsets,
667 &mesh_info,
668 base_transform,
669 base_instance_context.meshes,
670 base_instance_context.id});
671 gather_info.r_offsets.mesh_offsets.vertex += mesh->verts_num;
672 gather_info.r_offsets.mesh_offsets.edge += mesh->edges_num;
673 gather_info.r_offsets.mesh_offsets.loop += mesh->corners_num;
674 gather_info.r_offsets.mesh_offsets.face += mesh->faces_num;
675 }
676 break;
677 }
679 const auto &pointcloud_component = *static_cast<const bke::PointCloudComponent *>(
680 component);
681 const PointCloud *pointcloud = pointcloud_component.get();
682 if (pointcloud != nullptr && pointcloud->totpoint > 0) {
683 const int pointcloud_index = gather_info.pointclouds.order.index_of(pointcloud);
684 const PointCloudRealizeInfo &pointcloud_info =
685 gather_info.pointclouds.realize_info[pointcloud_index];
686 gather_info.r_tasks.pointcloud_tasks.append({gather_info.r_offsets.pointcloud_offset,
687 &pointcloud_info,
688 base_transform,
689 base_instance_context.pointclouds,
690 base_instance_context.id});
691 gather_info.r_offsets.pointcloud_offset += pointcloud->totpoint;
692 }
693 break;
694 }
696 const auto &curve_component = *static_cast<const bke::CurveComponent *>(component);
697 const Curves *curves = curve_component.get();
698 if (curves != nullptr && curves->geometry.curve_num > 0) {
699 const int curve_index = gather_info.curves.order.index_of(curves);
700 const RealizeCurveInfo &curve_info = gather_info.curves.realize_info[curve_index];
701 gather_info.r_tasks.curve_tasks.append({gather_info.r_offsets.curves_offsets,
702 &curve_info,
703 base_transform,
704 base_instance_context.curves,
705 base_instance_context.id});
706 gather_info.r_offsets.curves_offsets.point += curves->geometry.point_num;
707 gather_info.r_offsets.curves_offsets.curve += curves->geometry.curve_num;
708 }
709 break;
710 }
712 const auto &grease_pencil_component = *static_cast<const bke::GreasePencilComponent *>(
713 component);
714 const GreasePencil *grease_pencil = grease_pencil_component.get();
715 if (grease_pencil != nullptr && !grease_pencil->layers().is_empty()) {
716 const int grease_pencil_index = gather_info.grease_pencils.order.index_of(grease_pencil);
717 const GreasePencilRealizeInfo &grease_pencil_info =
718 gather_info.grease_pencils.realize_info[grease_pencil_index];
719 gather_info.r_tasks.grease_pencil_tasks.append(
721 &grease_pencil_info,
722 base_transform,
723 base_instance_context.grease_pencils});
724 gather_info.r_offsets.grease_pencil_layer_offset += grease_pencil->layers().size();
725 }
726 break;
727 }
729 if (current_depth == target_depth) {
730 gather_info.instances.attribute_fallback.append(base_instance_context.instances);
731 gather_info.instances.instances_components_to_merge.append(component->copy());
732 gather_info.instances.instances_components_transforms.append(base_transform);
733 }
734 else {
735 const Instances *instances =
736 (*static_cast<const bke::InstancesComponent *>(component)).get();
737 if (instances != nullptr && instances->instances_num() > 0) {
739 current_depth,
740 target_depth,
741 *instances,
742 base_transform,
743 base_instance_context);
744 }
745 }
746 break;
747 }
749 if (!gather_info.r_tasks.first_volume) {
750 const bke::VolumeComponent *volume_component = static_cast<const bke::VolumeComponent *>(
751 component);
752 volume_component->add_user();
754 volume_component);
755 }
756 break;
757 }
759 const auto *edit_component = static_cast<const bke::GeometryComponentEditData *>(
760 component);
761 if (edit_component->gizmo_edit_hints_ || edit_component->curves_edit_hints_) {
762 gather_info.r_tasks.edit_data_tasks.append({edit_component, base_transform});
763 }
764 break;
765 }
766 }
767 }
768}
769
772 const bke::GeometryComponent::Type component_type,
774 const int current_depth,
775 const std::optional<int> max_depth,
776 Set<bke::GeometryComponentPtr> &r_components)
777{
778 if (const bke::GeometryComponent *component = geometry.get_component(component_type)) {
779 if (r_components.add_as(component)) {
780 component->add_user();
781 }
782 }
783 if (current_depth == max_depth) {
784 return;
785 }
786 const auto *instances_component = geometry.get_component<bke::InstancesComponent>();
787 if (!instances_component) {
788 return;
789 }
790 const bke::Instances *instances = instances_component->get();
791 if (!instances) {
792 return;
793 }
794 if (options.realize_instance_attributes) {
795 if (r_components.add_as(instances_component)) {
796 instances_component->add_user();
797 }
798 }
799 for (const bke::InstanceReference &reference : instances->references()) {
800 bke::GeometrySet reference_geometry;
801 reference.to_geometry_set(reference_geometry);
803 reference_geometry, component_type, options, current_depth + 1, max_depth, r_components);
804 }
805}
806
809 const bke::GeometryComponent::Type component_type,
811 const VariedDepthOptions &varied_depth_option,
812 Set<bke::GeometryComponentPtr> &r_components)
813{
814 if (const bke::GeometryComponent *component = geometry.get_component(component_type)) {
815 if (r_components.add_as(component)) {
816 component->add_user();
817 }
818 }
819 const auto *instances_component = geometry.get_component<bke::InstancesComponent>();
820 if (!instances_component) {
821 return;
822 }
823 const bke::Instances *instances = instances_component->get();
824 if (!instances) {
825 return;
826 }
827
828 const Span<bke::InstanceReference> references = instances->references();
829 const Span<int> handles = instances->reference_handles();
830 const int references_num = references.size();
831 Array<std::optional<int>> max_reference_depth(references_num, 0);
832
833 varied_depth_option.selection.foreach_index([&](const int instance_i) {
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()) {
838 /* Is already at max depth. */
839 return;
840 }
841 if (instance_depth == VariedDepthOptions::MAX_DEPTH) {
842 max_depth.reset();
843 return;
844 }
845 max_depth = std::max<int>(*max_depth, instance_depth);
846 });
847
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) {
852 continue;
853 }
854 const bke::InstanceReference &reference = references[reference_i];
855 bke::GeometrySet reference_geometry;
856 reference.to_geometry_set(reference_geometry);
858 reference_geometry, component_type, options, 1, max_depth, r_components);
859 is_anything_realized = true;
860 }
861
862 if (is_anything_realized) {
863 if (options.realize_instance_attributes) {
864 if (r_components.add_as(instances_component)) {
865 instances_component->add_user();
866 }
867 }
868 }
869}
870
873 const bke::GeometryComponent::Type component_type,
875 const VariedDepthOptions &varied_depth_option)
876{
877 const bke::AttributeFilter &attribute_filter = options.attribute_filter;
878
879 const bke::InstancesComponent *top_level_instances_component =
880 geometry.get_component<bke::InstancesComponent>();
881 const int top_level_instances_num = top_level_instances_component ?
882 top_level_instances_component->attribute_domain_size(
883 AttrDomain::Instance) :
884 0;
885
886 /* Needs to take ownership because some components are only temporary otherwise. */
888 if (varied_depth_option.depths.get_if_single() == VariedDepthOptions::MAX_DEPTH &&
889 varied_depth_option.selection.size() == top_level_instances_num)
890 {
891 /* In this case we don't have to iterate over all instances, just over the references. */
893 geometry, component_type, options, 0, std::nullopt, components);
894 }
895 else {
897 geometry, component_type, options, varied_depth_option, components);
898 }
899
900 /* Actually gather the attributes to propagate from the found components. */
901 Map<StringRef, AttributeKind> attributes_to_propagate;
902 for (const bke::GeometryComponentPtr &component : components) {
903 const bke::AttributeAccessor attributes = *component->attributes();
904 attributes.foreach_attribute([&](const bke::AttributeIter &iter) {
905 if (iter.is_builtin) {
906 if (!bke::attribute_is_builtin_on_component_type(component_type, iter.name)) {
907 /* Don't propagate built-in attributes that are not built-in on the
908 * destination component. */
909 return;
910 }
911 }
912 if (iter.data_type == CD_PROP_STRING) {
913 /* Propagating string attributes is not supported yet. */
914 return;
915 }
916 if (attribute_filter.allow_skip(iter.name)) {
917 return;
918 }
919 AttrDomain dst_domain = iter.domain;
920 if (component_type != bke::GeometryComponent::Type::Instance &&
921 dst_domain == AttrDomain::Instance)
922 {
923 /* Instance attributes are realized on the point domain currently. */
924 dst_domain = AttrDomain::Point;
925 }
926 auto add = [&](AttributeKind *kind) {
927 kind->domain = dst_domain;
928 kind->data_type = iter.data_type;
929 };
930 auto modify = [&](AttributeKind *kind) {
931 kind->domain = bke::attribute_domain_highest_priority({kind->domain, dst_domain});
933 {kind->data_type, iter.data_type});
934 };
935 attributes_to_propagate.add_or_modify(iter.name, add, modify);
936 });
937 }
938
939 return attributes_to_propagate;
940}
941
943
944/* -------------------------------------------------------------------- */
947
949 const bke::GeometrySet &in_geometry_set,
951 const VariedDepthOptions &varied_depth_option)
952{
954 in_geometry_set, bke::GeometryComponent::Type::Instance, options, varied_depth_option);
955 attributes_to_propagate.pop_try("id");
956 OrderedAttributes ordered_attributes;
957 for (const auto item : attributes_to_propagate.items()) {
958 ordered_attributes.ids.add_new(item.key);
959 ordered_attributes.kinds.append(item.value);
960 }
961 return ordered_attributes;
962}
963
965 const Span<bke::GeometryComponentPtr> src_components,
966 Span<blender::float4x4> src_base_transforms,
967 OrderedAttributes all_instances_attributes,
969 bke::GeometrySet &r_realized_geometry)
970{
971 BLI_assert(src_components.size() == src_base_transforms.size() &&
972 src_components.size() == attribute_fallback.size());
973 if (src_components.is_empty()) {
974 return;
975 }
976
977 Array<int> offsets_data(src_components.size() + 1);
978 for (const int component_index : src_components.index_range()) {
979 const bke::InstancesComponent &src_component = static_cast<const bke::InstancesComponent &>(
980 *src_components[component_index]);
981 offsets_data[component_index] = src_component.get()->instances_num();
982 }
984
985 std::unique_ptr<bke::Instances> dst_instances = std::make_unique<bke::Instances>();
986 dst_instances->resize(offsets.total_size());
987
988 /* Makes sure generic output attributes exists. */
989 for (const int attribute_index : all_instances_attributes.index_range()) {
991 const StringRef id = all_instances_attributes.ids[attribute_index];
992 const eCustomDataType type = all_instances_attributes.kinds[attribute_index].data_type;
993 dst_instances->attributes_for_write()
994 .lookup_or_add_for_write_only_span(id, domain, type)
995 .finish();
996 }
997
998 MutableSpan<float4x4> all_transforms = dst_instances->transforms_for_write();
999 MutableSpan<int> all_handles = dst_instances->reference_handles_for_write();
1000
1001 for (const int component_index : src_components.index_range()) {
1002 const bke::InstancesComponent &src_component = static_cast<const bke::InstancesComponent &>(
1003 *src_components[component_index]);
1004 const bke::Instances &src_instances = *src_component.get();
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;
1007 const Span<bke::InstanceReference> src_references = src_instances.references();
1008 Array<int> handle_map(src_references.size());
1009
1010 for (const int src_handle : src_references.index_range()) {
1011 handle_map[src_handle] = dst_instances->add_reference(src_references[src_handle]);
1012 }
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];
1016 const eCustomDataType type = all_instances_attributes.kinds[attribute_index].data_type;
1017 const CPPType *cpp_type = bke::custom_data_type_to_cpp_type(type);
1018 BLI_assert(cpp_type != nullptr);
1019 bke::GSpanAttributeWriter write_attribute =
1020 dst_instances->attributes_for_write().lookup_for_write_span(id);
1021 GMutableSpan dst_span = write_attribute.span;
1022
1023 const void *attribute_ptr;
1024 if (attribute_fallback_array[attribute_index] != nullptr) {
1025 attribute_ptr = attribute_fallback_array[attribute_index];
1026 }
1027 else {
1028 attribute_ptr = cpp_type->default_value();
1029 }
1030
1031 cpp_type->fill_assign_n(attribute_ptr, dst_span.slice(dst_range).data(), dst_range.size());
1032 write_attribute.finish();
1033 }
1034
1035 const Span<int> src_handles = src_instances.reference_handles();
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));
1038
1039 for (blender::float4x4 &transform : all_transforms.slice(dst_range)) {
1040 transform = src_base_transform * transform;
1041 }
1042 }
1043
1044 r_realized_geometry.replace_instances(dst_instances.release());
1045 auto &dst_component = r_realized_geometry.get_component_for_write<bke::InstancesComponent>();
1046
1047 Vector<const bke::GeometryComponent *> for_join_attributes;
1048 for (bke::GeometryComponentPtr component : src_components) {
1049 for_join_attributes.append(component.get());
1050 }
1051 /* Join attribute values from the 'unselected' instances, as they aren't included otherwise.
1052 * Omit instance_transform and .reference_index to prevent them from overwriting the correct
1053 * attributes of the realized instances. */
1054 join_attributes(for_join_attributes, dst_component, {".reference_index", "instance_transform"});
1055}
1056
1058
1059/* -------------------------------------------------------------------- */
1062
1064 const bke::GeometrySet &in_geometry_set,
1066 const VariedDepthOptions &varied_depth_option,
1067 bool &r_create_radii,
1068 bool &r_create_id)
1069{
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();
1075 OrderedAttributes ordered_attributes;
1076 for (const auto item : attributes_to_propagate.items()) {
1077 ordered_attributes.ids.add_new(item.key);
1078 ordered_attributes.kinds.append(item.value);
1079 }
1080 return ordered_attributes;
1081}
1082
1083static void gather_pointclouds_to_realize(const bke::GeometrySet &geometry_set,
1084 VectorSet<const PointCloud *> &r_pointclouds)
1085{
1086 if (const PointCloud *pointcloud = geometry_set.get_pointcloud()) {
1087 if (pointcloud->totpoint > 0) {
1088 r_pointclouds.add(pointcloud);
1089 }
1090 }
1091 if (const Instances *instances = geometry_set.get_instances()) {
1092 instances->foreach_referenced_geometry([&](const bke::GeometrySet &instance_geometry_set) {
1093 gather_pointclouds_to_realize(instance_geometry_set, r_pointclouds);
1094 });
1095 }
1096}
1097
1100 const VariedDepthOptions &varied_depth_option)
1101{
1102 AllPointCloudsInfo info;
1104 options,
1105 varied_depth_option,
1107 info.create_id_attribute);
1108
1109 gather_pointclouds_to_realize(geometry_set, info.order);
1110 info.realize_info.reinitialize(info.order.size());
1111 for (const int pointcloud_index : info.realize_info.index_range()) {
1112 PointCloudRealizeInfo &pointcloud_info = info.realize_info[pointcloud_index];
1113 const PointCloud *pointcloud = info.order[pointcloud_index];
1114 pointcloud_info.pointcloud = pointcloud;
1115
1116 /* Access attributes. */
1117 bke::AttributeAccessor attributes = pointcloud->attributes();
1118 pointcloud_info.attributes.reinitialize(info.attributes.size());
1119 for (const int attribute_index : info.attributes.index_range()) {
1120 const StringRef attribute_id = info.attributes.ids[attribute_index];
1121 const eCustomDataType data_type = info.attributes.kinds[attribute_index].data_type;
1122 const bke::AttrDomain domain = info.attributes.kinds[attribute_index].domain;
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));
1126 }
1127 }
1128 if (info.create_id_attribute) {
1129 bke::GAttributeReader ids_attribute = attributes.lookup("id");
1130 if (ids_attribute) {
1131 pointcloud_info.stored_ids = ids_attribute.varray.get_internal_span().typed<int>();
1132 }
1133 }
1134 if (info.create_radius_attribute) {
1135 pointcloud_info.radii = *attributes.lookup_or_default(
1136 "radius", bke::AttrDomain::Point, 0.01f);
1137 }
1138 const VArray<float3> position_attribute = *attributes.lookup_or_default<float3>(
1139 "position", bke::AttrDomain::Point, float3(0));
1140 pointcloud_info.positions = position_attribute.get_internal_span();
1141 }
1142 return info;
1143}
1144
1147 const RealizePointCloudTask &task,
1148 const OrderedAttributes &ordered_attributes,
1149 MutableSpan<GSpanAttributeWriter> dst_attribute_writers,
1150 MutableSpan<float> all_dst_radii,
1151 MutableSpan<int> all_dst_ids,
1152 MutableSpan<float3> all_dst_positions)
1153{
1154 const PointCloudRealizeInfo &pointcloud_info = *task.pointcloud_info;
1155 const PointCloud &pointcloud = *pointcloud_info.pointcloud;
1156 const IndexRange point_slice{task.start_index, pointcloud.totpoint};
1157
1159 pointcloud_info.positions, task.transform, all_dst_positions.slice(point_slice));
1160
1161 /* Create point ids. */
1162 if (!all_dst_ids.is_empty()) {
1164 options, pointcloud_info.stored_ids, task.id, all_dst_ids.slice(point_slice));
1165 }
1166 if (!all_dst_radii.is_empty()) {
1167 pointcloud_info.radii.materialize(all_dst_radii.slice(point_slice));
1168 }
1169
1171 pointcloud_info.attributes,
1172 task.attribute_fallbacks,
1173 ordered_attributes,
1174 [&](const bke::AttrDomain domain) {
1175 BLI_assert(domain == bke::AttrDomain::Point);
1176 UNUSED_VARS_NDEBUG(domain);
1177 return point_slice;
1178 },
1179 dst_attribute_writers);
1180}
1181
1183 const OrderedAttributes &ordered_attributes,
1184 const AttributeFallbacksArray &attribute_fallbacks,
1186{
1187 for (const int attribute_index : ordered_attributes.index_range()) {
1188 const void *value = attribute_fallbacks.array[attribute_index];
1189 if (!value) {
1190 continue;
1191 }
1192 const bke::AttrDomain domain = ordered_attributes.kinds[attribute_index].domain;
1193 const eCustomDataType data_type = ordered_attributes.kinds[attribute_index].data_type;
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],
1197 domain,
1198 data_type,
1199 bke::AttributeInitVArray(std::move(gvaray)));
1200 }
1201}
1203 const AllPointCloudsInfo &all_pointclouds_info,
1204 const Span<RealizePointCloudTask> tasks,
1205 const OrderedAttributes &ordered_attributes,
1206 bke::GeometrySet &r_realized_geometry)
1207{
1208 if (tasks.is_empty()) {
1209 return;
1210 }
1211
1212 if (tasks.size() == 1) {
1213 const RealizePointCloudTask &task = tasks.first();
1214 PointCloud *new_points = BKE_pointcloud_copy_for_eval(task.pointcloud_info->pointcloud);
1215 if (!skip_transform(task.transform)) {
1216 transform_positions(task.transform, new_points->positions_for_write());
1217 new_points->tag_positions_changed();
1218 }
1220 ordered_attributes, task.attribute_fallbacks, new_points->attributes_for_write());
1221 r_realized_geometry.replace_pointcloud(new_points);
1222 return;
1223 }
1224
1225 const RealizePointCloudTask &last_task = tasks.last();
1226 const PointCloud &last_pointcloud = *last_task.pointcloud_info->pointcloud;
1227 const int tot_points = last_task.start_index + last_pointcloud.totpoint;
1228
1229 /* Allocate new point cloud. */
1230 PointCloud *dst_pointcloud = BKE_pointcloud_new_nomain(tot_points);
1231 r_realized_geometry.replace_pointcloud(dst_pointcloud);
1232 bke::MutableAttributeAccessor dst_attributes = dst_pointcloud->attributes_for_write();
1233
1234 const RealizePointCloudTask &first_task = tasks.first();
1235 const PointCloud &first_pointcloud = *first_task.pointcloud_info->pointcloud;
1236 dst_pointcloud->mat = static_cast<Material **>(MEM_dupallocN(first_pointcloud.mat));
1237 dst_pointcloud->totcol = first_pointcloud.totcol;
1238
1240 "position", bke::AttrDomain::Point);
1241
1242 /* Prepare id attribute. */
1243 SpanAttributeWriter<int> point_ids;
1244 if (all_pointclouds_info.create_id_attribute) {
1245 point_ids = dst_attributes.lookup_or_add_for_write_only_span<int>("id",
1247 }
1248 SpanAttributeWriter<float> point_radii;
1249 if (all_pointclouds_info.create_radius_attribute) {
1250 point_radii = dst_attributes.lookup_or_add_for_write_only_span<float>("radius",
1252 }
1253
1254 /* Prepare generic output attributes. */
1255 Vector<GSpanAttributeWriter> dst_attribute_writers;
1256 for (const int attribute_index : ordered_attributes.index_range()) {
1257 const StringRef attribute_id = ordered_attributes.ids[attribute_index];
1258 const eCustomDataType data_type = ordered_attributes.kinds[attribute_index].data_type;
1259 dst_attribute_writers.append(dst_attributes.lookup_or_add_for_write_only_span(
1260 attribute_id, bke::AttrDomain::Point, data_type));
1261 }
1262
1263 /* Actually execute all tasks. */
1264 threading::parallel_for(tasks.index_range(), 100, [&](const IndexRange task_range) {
1265 for (const int task_index : task_range) {
1266 const RealizePointCloudTask &task = tasks[task_index];
1267 execute_realize_pointcloud_task(options,
1268 task,
1269 ordered_attributes,
1270 dst_attribute_writers,
1271 point_radii.span,
1272 point_ids.span,
1273 positions.span);
1274 }
1275 });
1276
1277 /* Tag modified attributes. */
1278 for (GSpanAttributeWriter &dst_attribute : dst_attribute_writers) {
1279 dst_attribute.finish();
1280 }
1281 positions.finish();
1282 point_radii.finish();
1283 point_ids.finish();
1284}
1285
1287
1288/* -------------------------------------------------------------------- */
1291
1293 const bke::GeometrySet &in_geometry_set,
1295 const VariedDepthOptions &varied_depth_option,
1296 bool &r_create_id,
1297 bool &r_create_material_index)
1298{
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();
1307 OrderedAttributes ordered_attributes;
1308 for (const auto item : attributes_to_propagate.items()) {
1309 ordered_attributes.ids.add_new(item.key);
1310 ordered_attributes.kinds.append(item.value);
1311 }
1312 return ordered_attributes;
1313}
1314
1315static void gather_meshes_to_realize(const bke::GeometrySet &geometry_set,
1316 VectorSet<const Mesh *> &r_meshes)
1317{
1318 if (const Mesh *mesh = geometry_set.get_mesh()) {
1319 if (mesh->verts_num > 0) {
1320 r_meshes.add(mesh);
1321 }
1322 }
1323 if (const Instances *instances = geometry_set.get_instances()) {
1324 instances->foreach_referenced_geometry([&](const bke::GeometrySet &instance_geometry_set) {
1325 gather_meshes_to_realize(instance_geometry_set, r_meshes);
1326 });
1327 }
1328}
1329
1332 const VariedDepthOptions &varied_depth_option)
1333{
1334 AllMeshesInfo info;
1336 geometry_set,
1337 options,
1338 varied_depth_option,
1341
1342 gather_meshes_to_realize(geometry_set, info.order);
1343 for (const Mesh *mesh : info.order) {
1344 if (mesh->totcol == 0) {
1345 /* Add an empty material slot for the default material. */
1346 info.materials.add(nullptr);
1347 }
1348 else {
1349 for (const int slot_index : IndexRange(mesh->totcol)) {
1350 Material *material = mesh->mat[slot_index];
1351 info.materials.add(material);
1352 }
1353 }
1354 }
1356 info.realize_info.reinitialize(info.order.size());
1357 for (const int mesh_index : info.realize_info.index_range()) {
1358 MeshRealizeInfo &mesh_info = info.realize_info[mesh_index];
1359 const Mesh *mesh = info.order[mesh_index];
1360 mesh_info.mesh = mesh;
1361 mesh_info.positions = mesh->vert_positions();
1362 mesh_info.edges = mesh->edges();
1363 mesh_info.faces = mesh->faces();
1364 mesh_info.corner_verts = mesh->corner_verts();
1365 mesh_info.corner_edges = mesh->corner_edges();
1366
1367 /* Create material index mapping. */
1368 mesh_info.material_index_map.reinitialize(std::max<int>(mesh->totcol, 1));
1369 if (mesh->totcol == 0) {
1370 mesh_info.material_index_map.first() = info.materials.index_of(nullptr);
1371 }
1372 else {
1373 for (const int old_slot_index : IndexRange(mesh->totcol)) {
1374 Material *material = mesh->mat[old_slot_index];
1375 const int new_slot_index = info.materials.index_of(material);
1376 mesh_info.material_index_map[old_slot_index] = new_slot_index;
1377 }
1378 }
1379
1380 /* Access attributes. */
1381 bke::AttributeAccessor attributes = mesh->attributes();
1382 mesh_info.attributes.reinitialize(info.attributes.size());
1383 for (const int attribute_index : info.attributes.index_range()) {
1384 const StringRef attribute_id = info.attributes.ids[attribute_index];
1385 const eCustomDataType data_type = info.attributes.kinds[attribute_index].data_type;
1386 const bke::AttrDomain domain = info.attributes.kinds[attribute_index].domain;
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));
1390 }
1391 }
1392 if (info.create_id_attribute) {
1393 bke::GAttributeReader ids_attribute = attributes.lookup("id");
1394 if (ids_attribute) {
1395 mesh_info.stored_vertex_ids = ids_attribute.varray.get_internal_span().typed<int>();
1396 }
1397 }
1398 mesh_info.material_indices = *attributes.lookup_or_default<int>(
1399 "material_index", bke::AttrDomain::Face, 0);
1400 }
1401
1402 info.no_loose_edges_hint = std::all_of(
1403 info.order.begin(), info.order.end(), [](const Mesh *mesh) {
1404 return mesh->runtime->loose_edges_cache.is_cached() && mesh->loose_edges().count == 0;
1405 });
1406 info.no_loose_verts_hint = std::all_of(
1407 info.order.begin(), info.order.end(), [](const Mesh *mesh) {
1408 return mesh->runtime->loose_verts_cache.is_cached() && mesh->loose_verts().count == 0;
1409 });
1410 info.no_overlapping_hint = std::all_of(
1411 info.order.begin(), info.order.end(), [](const Mesh *mesh) {
1412 return mesh->no_overlapping_topology();
1413 });
1414
1415 return info;
1416}
1417
1419 const RealizeMeshTask &task,
1420 const OrderedAttributes &ordered_attributes,
1421 MutableSpan<GSpanAttributeWriter> dst_attribute_writers,
1422 MutableSpan<float3> all_dst_positions,
1423 MutableSpan<int2> all_dst_edges,
1424 MutableSpan<int> all_dst_face_offsets,
1425 MutableSpan<int> all_dst_corner_verts,
1426 MutableSpan<int> all_dst_corner_edges,
1427 MutableSpan<int> all_dst_vertex_ids,
1428 MutableSpan<int> all_dst_material_indices)
1429{
1430 const MeshRealizeInfo &mesh_info = *task.mesh_info;
1431 const Mesh &mesh = *mesh_info.mesh;
1432
1433 const Span<float3> src_positions = mesh_info.positions;
1434 const Span<int2> src_edges = mesh_info.edges;
1435 const OffsetIndices src_faces = mesh_info.faces;
1436 const Span<int> src_corner_verts = mesh_info.corner_verts;
1437 const Span<int> src_corner_edges = mesh_info.corner_edges;
1438
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());
1443
1444 MutableSpan<float3> dst_positions = all_dst_positions.slice(dst_vert_range);
1445 MutableSpan<int2> dst_edges = all_dst_edges.slice(dst_edge_range);
1446 MutableSpan<int> dst_face_offsets = all_dst_face_offsets.slice(dst_face_range);
1447 MutableSpan<int> dst_corner_verts = all_dst_corner_verts.slice(dst_loop_range);
1448 MutableSpan<int> dst_corner_edges = all_dst_corner_edges.slice(dst_loop_range);
1449
1450 threading::parallel_for(src_positions.index_range(), 1024, [&](const IndexRange vert_range) {
1451 for (const int i : vert_range) {
1452 dst_positions[i] = math::transform_point(task.transform, src_positions[i]);
1453 }
1454 });
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;
1458 }
1459 });
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;
1463 }
1464 });
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;
1468 }
1469 });
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;
1473 }
1474 });
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) {
1479 /* The material index map contains the index of the null material in the result. */
1480 dst_material_indices.fill(material_index_map.first());
1481 }
1482 else {
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);
1487 }
1488 else {
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;
1495 }
1496 });
1497 }
1498 }
1499 }
1500
1501 if (!all_dst_vertex_ids.is_empty()) {
1503 mesh_info.stored_vertex_ids,
1504 task.id,
1505 all_dst_vertex_ids.slice(task.start_indices.vertex, mesh.verts_num));
1506 }
1507
1509 mesh_info.attributes,
1510 task.attribute_fallbacks,
1511 ordered_attributes,
1512 [&](const bke::AttrDomain domain) {
1513 switch (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;
1522 default:
1523 BLI_assert_unreachable();
1524 return IndexRange();
1525 }
1526 },
1527 dst_attribute_writers);
1528}
1529
1531 const AllMeshesInfo &all_meshes_info,
1532 const Span<RealizeMeshTask> tasks,
1533 const OrderedAttributes &ordered_attributes,
1534 const VectorSet<Material *> &ordered_materials,
1535 bke::GeometrySet &r_realized_geometry)
1536{
1537 if (tasks.is_empty()) {
1538 return;
1539 }
1540
1541 if (tasks.size() == 1) {
1542 const RealizeMeshTask &task = tasks.first();
1543 Mesh *new_mesh = BKE_mesh_copy_for_eval(*task.mesh_info->mesh);
1544 if (!skip_transform(task.transform)) {
1545 transform_positions(task.transform, new_mesh->vert_positions_for_write());
1546 new_mesh->tag_positions_changed();
1547 }
1549 ordered_attributes, task.attribute_fallbacks, new_mesh->attributes_for_write());
1550 r_realized_geometry.replace_mesh(new_mesh);
1551 return;
1552 }
1553
1554 const RealizeMeshTask &last_task = tasks.last();
1555 const Mesh &last_mesh = *last_task.mesh_info->mesh;
1556 const int tot_vertices = last_task.start_indices.vertex + last_mesh.verts_num;
1557 const int tot_edges = last_task.start_indices.edge + last_mesh.edges_num;
1558 const int tot_loops = last_task.start_indices.loop + last_mesh.corners_num;
1559 const int tot_faces = last_task.start_indices.face + last_mesh.faces_num;
1560
1561 Mesh *dst_mesh = BKE_mesh_new_nomain(tot_vertices, tot_edges, tot_faces, tot_loops);
1562 r_realized_geometry.replace_mesh(dst_mesh);
1563 bke::MutableAttributeAccessor dst_attributes = dst_mesh->attributes_for_write();
1564 MutableSpan<float3> dst_positions = dst_mesh->vert_positions_for_write();
1565 MutableSpan<int2> dst_edges = dst_mesh->edges_for_write();
1566 MutableSpan<int> dst_face_offsets = dst_mesh->face_offsets_for_write();
1567 MutableSpan<int> dst_corner_verts = dst_mesh->corner_verts_for_write();
1568 MutableSpan<int> dst_corner_edges = dst_mesh->corner_edges_for_write();
1569
1570 /* Copy settings from the first input geometry set with a mesh. */
1571 const RealizeMeshTask &first_task = tasks.first();
1572 const Mesh &first_mesh = *first_task.mesh_info->mesh;
1573 BKE_mesh_copy_parameters_for_eval(dst_mesh, &first_mesh);
1574 /* The above line also copies vertex group names. We don't want that here because the new
1575 * attributes are added explicitly below. */
1577
1578 /* Add materials. */
1579 for (const int i : IndexRange(ordered_materials.size())) {
1580 Material *material = ordered_materials[i];
1581 BKE_id_material_eval_assign(&dst_mesh->id, i + 1, material);
1582 }
1583
1584 /* Prepare id attribute. */
1585 SpanAttributeWriter<int> vertex_ids;
1586 if (all_meshes_info.create_id_attribute) {
1587 vertex_ids = dst_attributes.lookup_or_add_for_write_only_span<int>("id",
1589 }
1590 /* Prepare material indices. */
1591 SpanAttributeWriter<int> material_indices;
1592 if (all_meshes_info.create_material_index_attribute) {
1593 material_indices = dst_attributes.lookup_or_add_for_write_only_span<int>(
1594 "material_index", bke::AttrDomain::Face);
1595 }
1596
1597 /* Prepare generic output attributes. */
1598 Vector<GSpanAttributeWriter> dst_attribute_writers;
1599 for (const int attribute_index : ordered_attributes.index_range()) {
1600 const StringRef attribute_id = ordered_attributes.ids[attribute_index];
1601 const bke::AttrDomain domain = ordered_attributes.kinds[attribute_index].domain;
1602 const eCustomDataType data_type = ordered_attributes.kinds[attribute_index].data_type;
1603 dst_attribute_writers.append(
1604 dst_attributes.lookup_or_add_for_write_only_span(attribute_id, domain, data_type));
1605 }
1606 const char *active_layer = CustomData_get_active_layer_name(&first_mesh.corner_data,
1608 if (active_layer != nullptr) {
1609 int id = CustomData_get_named_layer(&dst_mesh->corner_data, CD_PROP_FLOAT2, active_layer);
1610 if (id >= 0) {
1612 }
1613 }
1614 const char *render_layer = CustomData_get_render_layer_name(&first_mesh.corner_data,
1616 if (render_layer != nullptr) {
1617 int id = CustomData_get_named_layer(&dst_mesh->corner_data, CD_PROP_FLOAT2, render_layer);
1618 if (id >= 0) {
1620 }
1621 }
1622 /* Actually execute all tasks. */
1623 threading::parallel_for(tasks.index_range(), 100, [&](const IndexRange task_range) {
1624 for (const int task_index : task_range) {
1625 const RealizeMeshTask &task = tasks[task_index];
1626 execute_realize_mesh_task(options,
1627 task,
1628 ordered_attributes,
1629 dst_attribute_writers,
1630 dst_positions,
1631 dst_edges,
1632 dst_face_offsets,
1633 dst_corner_verts,
1634 dst_corner_edges,
1635 vertex_ids.span,
1636 material_indices.span);
1637 }
1638 });
1639
1640 /* Tag modified attributes. */
1641 for (GSpanAttributeWriter &dst_attribute : dst_attribute_writers) {
1642 dst_attribute.finish();
1643 }
1644 vertex_ids.finish();
1645 material_indices.finish();
1646
1647 if (all_meshes_info.no_loose_edges_hint) {
1648 dst_mesh->tag_loose_edges_none();
1649 }
1650 if (all_meshes_info.no_loose_verts_hint) {
1651 dst_mesh->tag_loose_verts_none();
1652 }
1653 if (all_meshes_info.no_overlapping_hint) {
1654 dst_mesh->tag_overlapping_none();
1655 }
1656}
1657
1659
1660/* -------------------------------------------------------------------- */
1663
1665 const bke::GeometrySet &in_geometry_set,
1667 const VariedDepthOptions &varied_depth_option,
1668 bool &r_create_id)
1669{
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();
1680 OrderedAttributes ordered_attributes;
1681 for (const auto item : attributes_to_propagate.items()) {
1682 ordered_attributes.ids.add_new(item.key);
1683 ordered_attributes.kinds.append(item.value);
1684 }
1685 return ordered_attributes;
1686}
1687
1688static void gather_curves_to_realize(const bke::GeometrySet &geometry_set,
1689 VectorSet<const Curves *> &r_curves)
1690{
1691 if (const Curves *curves = geometry_set.get_curves()) {
1692 if (curves->geometry.curve_num != 0) {
1693 r_curves.add(curves);
1694 }
1695 }
1696 if (const Instances *instances = geometry_set.get_instances()) {
1697 instances->foreach_referenced_geometry([&](const bke::GeometrySet &instance_geometry_set) {
1698 gather_curves_to_realize(instance_geometry_set, r_curves);
1699 });
1700 }
1701}
1702
1705 const VariedDepthOptions &varied_depth_option)
1706{
1707 AllCurvesInfo info;
1709 geometry_set, options, varied_depth_option, info.create_id_attribute);
1710
1711 gather_curves_to_realize(geometry_set, info.order);
1712 info.realize_info.reinitialize(info.order.size());
1713 for (const int curve_index : info.realize_info.index_range()) {
1714 RealizeCurveInfo &curve_info = info.realize_info[curve_index];
1715 const Curves *curves_id = info.order[curve_index];
1716 const bke::CurvesGeometry &curves = curves_id->geometry.wrap();
1717 curve_info.curves = curves_id;
1718
1719 /* Access attributes. */
1720 bke::AttributeAccessor attributes = curves.attributes();
1721 curve_info.attributes.reinitialize(info.attributes.size());
1722 for (const int attribute_index : info.attributes.index_range()) {
1723 const bke::AttrDomain domain = info.attributes.kinds[attribute_index].domain;
1724 const StringRef attribute_id = info.attributes.ids[attribute_index];
1725 const eCustomDataType data_type = info.attributes.kinds[attribute_index].data_type;
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));
1729 }
1730 }
1731 if (info.create_id_attribute) {
1732 bke::GAttributeReader id_attribute = attributes.lookup("id");
1733 if (id_attribute) {
1734 curve_info.stored_ids = id_attribute.varray.get_internal_span().typed<int>();
1735 }
1736 }
1737
1738 if (attributes.contains("radius")) {
1739 curve_info.radius =
1740 attributes.lookup<float>("radius", bke::AttrDomain::Point).varray.get_internal_span();
1741 info.create_radius_attribute = true;
1742 }
1743 if (attributes.contains("nurbs_weight")) {
1744 curve_info.nurbs_weight = attributes.lookup<float>("nurbs_weight", bke::AttrDomain::Point)
1745 .varray.get_internal_span();
1747 }
1748 curve_info.resolution = curves.resolution();
1749 if (attributes.contains("resolution")) {
1750 info.create_resolution_attribute = true;
1751 }
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();
1758 }
1759 if (attributes.contains("custom_normal")) {
1760 curve_info.custom_normal = attributes.lookup<float3>("custom_normal", bke::AttrDomain::Point)
1761 .varray.get_internal_span();
1763 }
1764 }
1765 return info;
1766}
1767
1769 const AllCurvesInfo &all_curves_info,
1770 const RealizeCurveTask &task,
1771 const OrderedAttributes &ordered_attributes,
1772 bke::CurvesGeometry &dst_curves,
1773 MutableSpan<GSpanAttributeWriter> dst_attribute_writers,
1774 MutableSpan<int> all_dst_ids,
1775 MutableSpan<float3> all_handle_left,
1776 MutableSpan<float3> all_handle_right,
1777 MutableSpan<float> all_radii,
1778 MutableSpan<float> all_nurbs_weights,
1779 MutableSpan<int> all_resolutions,
1780 MutableSpan<float3> all_custom_normals)
1781{
1782 const RealizeCurveInfo &curves_info = *task.curve_info;
1783 const Curves &curves_id = *curves_info.curves;
1784 const bke::CurvesGeometry &curves = curves_id.geometry.wrap();
1785
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()};
1788
1790 curves.positions(), task.transform, dst_curves.positions_for_write().slice(dst_point_range));
1791
1792 /* Copy and transform handle positions if necessary. */
1793 if (all_curves_info.create_handle_postion_attributes) {
1794 if (curves_info.handle_left.is_empty()) {
1795 all_handle_left.slice(dst_point_range).fill(float3(0));
1796 }
1797 else {
1799 curves_info.handle_left, task.transform, all_handle_left.slice(dst_point_range));
1800 }
1801 if (curves_info.handle_right.is_empty()) {
1802 all_handle_right.slice(dst_point_range).fill(float3(0));
1803 }
1804 else {
1806 curves_info.handle_right, task.transform, all_handle_right.slice(dst_point_range));
1807 }
1808 }
1809
1810 auto copy_point_span_with_default =
1811 [&](const Span<float> src, MutableSpan<float> all_dst, const float value) {
1812 if (src.is_empty()) {
1813 all_dst.slice(dst_point_range).fill(value);
1814 }
1815 else {
1816 all_dst.slice(dst_point_range).copy_from(src);
1817 }
1818 };
1819 if (all_curves_info.create_radius_attribute) {
1820 copy_point_span_with_default(curves_info.radius, all_radii, 1.0f);
1821 }
1822 if (all_curves_info.create_nurbs_weight_attribute) {
1823 copy_point_span_with_default(curves_info.nurbs_weight, all_nurbs_weights, 1.0f);
1824 }
1825
1826 if (all_curves_info.create_resolution_attribute) {
1827 curves_info.resolution.materialize(all_resolutions.slice(dst_curve_range));
1828 }
1829
1830 if (all_curves_info.create_custom_normal_attribute) {
1831 if (curves_info.custom_normal.is_empty()) {
1832 all_custom_normals.slice(dst_point_range).fill(float3(0, 0, 1));
1833 }
1834 else {
1836 curves_info.custom_normal, task.transform, all_custom_normals.slice(dst_point_range));
1837 }
1838 }
1839
1840 /* Copy curve offsets. */
1841 const Span<int> src_offsets = curves.offsets();
1842 const MutableSpan<int> dst_offsets = dst_curves.offsets_for_write().slice(dst_curve_range);
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];
1846 }
1847 });
1848
1849 if (!all_dst_ids.is_empty()) {
1850 create_result_ids(
1851 options, curves_info.stored_ids, task.id, all_dst_ids.slice(dst_point_range));
1852 }
1853
1854 copy_generic_attributes_to_result(
1855 curves_info.attributes,
1856 task.attribute_fallbacks,
1857 ordered_attributes,
1858 [&](const bke::AttrDomain domain) {
1859 switch (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());
1864 default:
1865 BLI_assert_unreachable();
1866 return IndexRange();
1867 }
1868 },
1869 dst_attribute_writers);
1870}
1871
1873 const AllCurvesInfo &all_curves_info,
1874 const Span<RealizeCurveTask> tasks,
1875 const OrderedAttributes &ordered_attributes,
1876 bke::GeometrySet &r_realized_geometry)
1877{
1878 if (tasks.is_empty()) {
1879 return;
1880 }
1881
1882 if (tasks.size() == 1) {
1883 const RealizeCurveTask &task = tasks.first();
1884 Curves *new_curves = BKE_curves_copy_for_eval(task.curve_info->curves);
1885 if (!skip_transform(task.transform)) {
1886 new_curves->geometry.wrap().transform(task.transform);
1887 }
1889 task.attribute_fallbacks,
1890 new_curves->geometry.wrap().attributes_for_write());
1891 r_realized_geometry.replace_curves(new_curves);
1892 return;
1893 }
1894
1895 const RealizeCurveTask &last_task = tasks.last();
1896 const Curves &last_curves = *last_task.curve_info->curves;
1897 const int points_num = last_task.start_indices.point + last_curves.geometry.point_num;
1898 const int curves_num = last_task.start_indices.curve + last_curves.geometry.curve_num;
1899
1900 /* Allocate new curves data-block. */
1901 Curves *dst_curves_id = bke::curves_new_nomain(points_num, curves_num);
1902 bke::CurvesGeometry &dst_curves = dst_curves_id->geometry.wrap();
1903 dst_curves.offsets_for_write().last() = points_num;
1904 r_realized_geometry.replace_curves(dst_curves_id);
1905 bke::MutableAttributeAccessor dst_attributes = dst_curves.attributes_for_write();
1906
1907 /* Copy settings from the first input geometry set with curves. */
1908 const RealizeCurveTask &first_task = tasks.first();
1909 const Curves &first_curves_id = *first_task.curve_info->curves;
1910 bke::curves_copy_parameters(first_curves_id, *dst_curves_id);
1911
1912 /* Prepare id attribute. */
1913 SpanAttributeWriter<int> point_ids;
1914 if (all_curves_info.create_id_attribute) {
1915 point_ids = dst_attributes.lookup_or_add_for_write_only_span<int>("id",
1917 }
1918
1919 /* Prepare generic output attributes. */
1920 Vector<GSpanAttributeWriter> dst_attribute_writers;
1921 for (const int attribute_index : ordered_attributes.index_range()) {
1922 const StringRef attribute_id = ordered_attributes.ids[attribute_index];
1923 const bke::AttrDomain domain = ordered_attributes.kinds[attribute_index].domain;
1924 const eCustomDataType data_type = ordered_attributes.kinds[attribute_index].data_type;
1925 dst_attribute_writers.append(
1926 dst_attributes.lookup_or_add_for_write_only_span(attribute_id, domain, data_type));
1927 }
1928
1929 /* Prepare handle position attributes if necessary. */
1930 SpanAttributeWriter<float3> handle_left;
1931 SpanAttributeWriter<float3> handle_right;
1932 if (all_curves_info.create_handle_postion_attributes) {
1933 handle_left = dst_attributes.lookup_or_add_for_write_only_span<float3>("handle_left",
1935 handle_right = dst_attributes.lookup_or_add_for_write_only_span<float3>(
1936 "handle_right", bke::AttrDomain::Point);
1937 }
1938
1940 if (all_curves_info.create_radius_attribute) {
1941 radius = dst_attributes.lookup_or_add_for_write_only_span<float>("radius",
1943 }
1944 SpanAttributeWriter<float> nurbs_weight;
1945 if (all_curves_info.create_nurbs_weight_attribute) {
1946 nurbs_weight = dst_attributes.lookup_or_add_for_write_only_span<float>("nurbs_weight",
1948 }
1949 SpanAttributeWriter<int> resolution;
1950 if (all_curves_info.create_resolution_attribute) {
1951 resolution = dst_attributes.lookup_or_add_for_write_only_span<int>("resolution",
1953 }
1954 SpanAttributeWriter<float3> custom_normal;
1955 if (all_curves_info.create_custom_normal_attribute) {
1956 custom_normal = dst_attributes.lookup_or_add_for_write_only_span<float3>(
1957 "custom_normal", bke::AttrDomain::Point);
1958 }
1959
1960 /* Actually execute all tasks. */
1961 threading::parallel_for(tasks.index_range(), 100, [&](const IndexRange task_range) {
1962 for (const int task_index : task_range) {
1963 const RealizeCurveTask &task = tasks[task_index];
1964 execute_realize_curve_task(options,
1965 all_curves_info,
1966 task,
1967 ordered_attributes,
1968 dst_curves,
1969 dst_attribute_writers,
1970 point_ids.span,
1971 handle_left.span,
1972 handle_right.span,
1973 radius.span,
1974 nurbs_weight.span,
1975 resolution.span,
1976 custom_normal.span);
1977 }
1978 });
1979
1980 /* Type counts have to be updated eagerly. */
1981 dst_curves.runtime->type_counts.fill(0);
1982 for (const RealizeCurveTask &task : tasks) {
1983 for (const int i : IndexRange(CURVE_TYPES_NUM)) {
1984 dst_curves.runtime->type_counts[i] +=
1985 task.curve_info->curves->geometry.runtime->type_counts[i];
1986 }
1987 }
1988
1989 /* Tag modified attributes. */
1990 for (GSpanAttributeWriter &dst_attribute : dst_attribute_writers) {
1991 dst_attribute.finish();
1992 }
1993 point_ids.finish();
1994 radius.finish();
1995 resolution.finish();
1996 nurbs_weight.finish();
1997 handle_left.finish();
1998 handle_right.finish();
1999 custom_normal.finish();
2000}
2001
2003
2004/* -------------------------------------------------------------------- */
2007
2009 const bke::GeometrySet &in_geometry_set,
2011 const VariedDepthOptions &varied_depth_options)
2012{
2014 in_geometry_set, bke::GeometryComponent::Type::GreasePencil, options, varied_depth_options);
2015 OrderedAttributes ordered_attributes;
2016 for (auto &&item : attributes_to_propagate.items()) {
2017 ordered_attributes.ids.add_new(item.key);
2018 ordered_attributes.kinds.append(item.value);
2019 }
2020 return ordered_attributes;
2021}
2022
2024 VectorSet<const GreasePencil *> &r_grease_pencils)
2025{
2026 if (const GreasePencil *grease_pencil = geometry_set.get_grease_pencil()) {
2027 if (!grease_pencil->layers().is_empty()) {
2028 r_grease_pencils.add(grease_pencil);
2029 }
2030 }
2031 if (const Instances *instances = geometry_set.get_instances()) {
2032 instances->foreach_referenced_geometry([&](const bke::GeometrySet &instance_geometry_set) {
2033 gather_grease_pencils_to_realize(instance_geometry_set, r_grease_pencils);
2034 });
2035 }
2036}
2037
2039 const bke::GeometrySet &geometry_set,
2041 const VariedDepthOptions &varied_depth_options)
2042{
2045 geometry_set, options, varied_depth_options);
2046
2047 gather_grease_pencils_to_realize(geometry_set, info.order);
2048 info.realize_info.reinitialize(info.order.size());
2049 for (const int grease_pencil_index : info.realize_info.index_range()) {
2050 GreasePencilRealizeInfo &grease_pencil_info = info.realize_info[grease_pencil_index];
2051 const GreasePencil *grease_pencil = info.order[grease_pencil_index];
2052 grease_pencil_info.grease_pencil = grease_pencil;
2053
2054 bke::AttributeAccessor attributes = grease_pencil->attributes();
2055 grease_pencil_info.attributes.reinitialize(info.attributes.size());
2056 for (const int attribute_index : info.attributes.index_range()) {
2057 const StringRef attribute_id = info.attributes.ids[attribute_index];
2058 const eCustomDataType data_type = info.attributes.kinds[attribute_index].data_type;
2059 const bke::AttrDomain domain = info.attributes.kinds[attribute_index].domain;
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));
2063 }
2064 }
2065
2066 grease_pencil_info.material_index_map.reinitialize(grease_pencil->material_array_num);
2067 for (const int i : IndexRange(grease_pencil->material_array_num)) {
2068 Material *material = grease_pencil->material_array[i];
2069 grease_pencil_info.material_index_map[i] = info.materials.index_of_or_add(material);
2070 }
2071 }
2072 return info;
2073}
2074
2076 const RealizeGreasePencilTask &task,
2077 const OrderedAttributes &ordered_attributes,
2078 GreasePencil &dst_grease_pencil,
2079 MutableSpan<GSpanAttributeWriter> dst_attribute_writers)
2080{
2081 const GreasePencilRealizeInfo &grease_pencil_info = *task.grease_pencil_info;
2082 const GreasePencil &src_grease_pencil = *grease_pencil_info.grease_pencil;
2083 const Span<const bke::greasepencil::Layer *> src_layers = src_grease_pencil.layers();
2084 const IndexRange dst_layers_slice{task.start_index, src_layers.size()};
2085 const Span<bke::greasepencil::Layer *> dst_layers = dst_grease_pencil.layers_for_write().slice(
2086 dst_layers_slice);
2087
2088 for (const int layer_i : src_layers.index_range()) {
2089 const bke::greasepencil::Layer &src_layer = *src_layers[layer_i];
2090 bke::greasepencil::Layer &dst_layer = *dst_layers[layer_i];
2091 BKE_grease_pencil_copy_layer_parameters(src_layer, dst_layer);
2092
2093 dst_layer.set_name(src_layer.name());
2094 dst_layer.set_local_transform(task.transform * src_layer.local_transform());
2095
2096 const bke::greasepencil::Drawing *src_drawing = src_grease_pencil.get_eval_drawing(src_layer);
2097 if (!src_drawing) {
2098 continue;
2099 }
2100 bke::greasepencil::Drawing &dst_drawing = *dst_grease_pencil.get_eval_drawing(dst_layer);
2101
2102 const bke::CurvesGeometry &src_curves = src_drawing->strokes();
2103 bke::CurvesGeometry &dst_curves = dst_drawing.strokes_for_write();
2104 dst_curves = src_curves;
2105
2106 /* Remap materials. */
2107 bke::MutableAttributeAccessor dst_attributes = dst_curves.attributes_for_write();
2108 bke::SpanAttributeWriter<int> material_indices =
2109 dst_attributes.lookup_or_add_for_write_span<int>("material_index", bke::AttrDomain::Curve);
2110 for (int &material_index : material_indices.span) {
2111 if (material_index >= 0 && material_index < src_grease_pencil.material_array_num) {
2112 material_index = grease_pencil_info.material_index_map[material_index];
2113 }
2114 }
2115 material_indices.finish();
2116 }
2117
2119 grease_pencil_info.attributes,
2120 task.attribute_fallbacks,
2121 ordered_attributes,
2122 [&](const bke::AttrDomain domain) {
2123 BLI_assert(domain == bke::AttrDomain::Layer);
2124 UNUSED_VARS_NDEBUG(domain);
2125 return dst_layers_slice;
2126 },
2127 dst_attribute_writers);
2128}
2129
2131 const float4x4 &transform)
2132{
2133 for (bke::greasepencil::Layer *layer : layers) {
2134 layer->set_local_transform(transform * layer->local_transform());
2135 }
2136}
2137
2139 const AllGreasePencilsInfo &all_grease_pencils_info,
2141 const OrderedAttributes &ordered_attributes,
2142 bke::GeometrySet &r_realized_geometry)
2143{
2144 if (tasks.is_empty()) {
2145 return;
2146 }
2147
2148 if (tasks.size() == 1) {
2149 const RealizeGreasePencilTask &task = tasks.first();
2150 GreasePencil *new_gp = BKE_grease_pencil_copy_for_eval(task.grease_pencil_info->grease_pencil);
2151 if (!skip_transform(task.transform)) {
2152 transform_grease_pencil_layers(new_gp->layers_for_write(), task.transform);
2153 }
2155 ordered_attributes, task.attribute_fallbacks, new_gp->attributes_for_write());
2156 r_realized_geometry.replace_grease_pencil(new_gp);
2157 return;
2158 }
2159
2160 const RealizeGreasePencilTask &last_task = tasks.last();
2161 const int new_layers_num = last_task.start_index +
2162 last_task.grease_pencil_info->grease_pencil->layers().size();
2163
2164 /* Allocate new grease pencil. */
2165 GreasePencil *dst_grease_pencil = BKE_grease_pencil_new_nomain();
2166 BKE_grease_pencil_copy_parameters(*tasks.first().grease_pencil_info->grease_pencil,
2167 *dst_grease_pencil);
2168 r_realized_geometry.replace_grease_pencil(dst_grease_pencil);
2169
2170 /* Allocate all layers. */
2171 dst_grease_pencil->add_layers_with_empty_drawings_for_eval(new_layers_num);
2172
2173 /* Transfer material pointers. The material indices are updated for each task separately. */
2174 if (!all_grease_pencils_info.materials.is_empty()) {
2175 MEM_SAFE_FREE(dst_grease_pencil->material_array);
2176 dst_grease_pencil->material_array_num = all_grease_pencils_info.materials.size();
2177 dst_grease_pencil->material_array = MEM_cnew_array<Material *>(
2178 dst_grease_pencil->material_array_num, __func__);
2179 uninitialized_copy_n(all_grease_pencils_info.materials.data(),
2180 dst_grease_pencil->material_array_num,
2181 dst_grease_pencil->material_array);
2182 }
2183
2184 /* Prepare generic output attributes. */
2185 bke::MutableAttributeAccessor dst_attributes = dst_grease_pencil->attributes_for_write();
2186 Vector<GSpanAttributeWriter> dst_attribute_writers;
2187 for (const int attribute_index : ordered_attributes.index_range()) {
2188 const StringRef attribute_id = ordered_attributes.ids[attribute_index];
2189 const eCustomDataType data_type = ordered_attributes.kinds[attribute_index].data_type;
2190 dst_attribute_writers.append(dst_attributes.lookup_or_add_for_write_only_span(
2191 attribute_id, bke::AttrDomain::Layer, data_type));
2192 }
2193
2194 /* Actually execute all tasks. */
2195 threading::parallel_for(tasks.index_range(), 100, [&](const IndexRange task_range) {
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);
2200 }
2201 });
2202
2203 /* Tag modified attributes. */
2204 for (GSpanAttributeWriter &dst_attribute : dst_attribute_writers) {
2205 dst_attribute.finish();
2206 }
2207}
2208/* -------------------------------------------------------------------- */
2211
2213 bke::GeometrySet &r_realized_geometry)
2214{
2215 if (tasks.is_empty()) {
2216 return;
2217 }
2218
2219 auto &component = r_realized_geometry.get_component_for_write<bke::GeometryComponentEditData>();
2220 for (const RealizeEditDataTask &task : tasks) {
2221 if (!component.curves_edit_hints_) {
2222 if (task.edit_data->curves_edit_hints_) {
2223 component.curves_edit_hints_ = std::make_unique<bke::CurvesEditHints>(
2224 *task.edit_data->curves_edit_hints_);
2225 }
2226 }
2227 if (const bke::GizmoEditHints *src_gizmo_edit_hints = task.edit_data->gizmo_edit_hints_.get())
2228 {
2229 if (!component.gizmo_edit_hints_) {
2230 component.gizmo_edit_hints_ = std::make_unique<bke::GizmoEditHints>();
2231 }
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);
2234 }
2235 }
2236 }
2237}
2238
2240
2241/* -------------------------------------------------------------------- */
2244
2246{
2247 geometry_set.modify_geometry_sets([&](bke::GeometrySet &sub_geometry) {
2248 if (Instances *instances = sub_geometry.get_instances_for_write()) {
2249 instances->attributes_for_write().remove("id");
2250 }
2251 });
2252}
2253
2257static void propagate_instances_to_keep(const bke::GeometrySet &geometry_set,
2258 const IndexMask &selection,
2259 bke::GeometrySet &new_geometry_set,
2260 const bke::AttributeFilter &attribute_filter)
2261{
2262 const Instances &instances = *geometry_set.get_instances();
2263 IndexMaskMemory inverse_selection_indices;
2264 const IndexMask inverse_selection = selection.complement(IndexRange(instances.instances_num()),
2265 inverse_selection_indices);
2266 /* Check not all instances are being realized. */
2267 if (inverse_selection.is_empty()) {
2268 return;
2269 }
2270
2271 std::unique_ptr<Instances> new_instances = std::make_unique<Instances>(instances);
2272 new_instances->remove(inverse_selection, attribute_filter);
2273
2274 bke::InstancesComponent &new_instances_components =
2276 new_instances_components.replace(new_instances.release(), bke::GeometryOwnershipType::Owned);
2277}
2278
2281{
2282 if (!geometry_set.has_instances()) {
2283 return geometry_set;
2284 }
2285
2286 VariedDepthOptions all_instances;
2288 geometry_set.get_instances()->instances_num());
2289 all_instances.selection = IndexMask(geometry_set.get_instances()->instances_num());
2290 return realize_instances(geometry_set, options, all_instances);
2291}
2292
2295 const VariedDepthOptions &varied_depth_option)
2296{
2297 /* The algorithm works in three steps:
2298 * 1. Preprocess each unique geometry that is instanced (e.g. each `Mesh`).
2299 * 2. Gather "tasks" that need to be executed to realize the instances. Each task corresponds
2300 * to instances of the previously preprocessed geometry.
2301 * 3. Execute all tasks in parallel.
2302 */
2303
2304 if (!geometry_set.has_instances()) {
2305 return geometry_set;
2306 }
2307
2308 bke::GeometrySet not_to_realize_set;
2310 geometry_set, varied_depth_option.selection, not_to_realize_set, options.attribute_filter);
2311
2312 if (options.keep_original_ids) {
2314 }
2315
2316 AllPointCloudsInfo all_pointclouds_info = preprocess_pointclouds(
2317 geometry_set, options, varied_depth_option);
2318 AllMeshesInfo all_meshes_info = preprocess_meshes(geometry_set, options, varied_depth_option);
2319 AllCurvesInfo all_curves_info = preprocess_curves(geometry_set, options, varied_depth_option);
2320 AllGreasePencilsInfo all_grease_pencils_info = preprocess_grease_pencils(
2321 geometry_set, options, varied_depth_option);
2323 geometry_set, options, varied_depth_option);
2324
2325 const bool create_id_attribute = all_pointclouds_info.create_id_attribute ||
2326 all_meshes_info.create_id_attribute ||
2327 all_curves_info.create_id_attribute;
2328 Vector<std::unique_ptr<GArray<>>> temporary_arrays;
2329 GatherTasksInfo gather_info = {all_pointclouds_info,
2330 all_meshes_info,
2331 all_curves_info,
2332 all_grease_pencils_info,
2333 all_instance_attributes,
2334 create_id_attribute,
2335 varied_depth_option.selection,
2336 varied_depth_option.depths,
2337 temporary_arrays};
2338
2339 if (not_to_realize_set.has_instances()) {
2340 gather_info.instances.instances_components_to_merge.append(
2341 not_to_realize_set.get_component_for_write<bke::InstancesComponent>().copy());
2343 gather_info.instances.attribute_fallback.append(gather_info.instances_attriubutes.size());
2344 }
2345
2347 InstanceContext attribute_fallbacks(gather_info);
2348
2350 gather_info, 0, VariedDepthOptions::MAX_DEPTH, geometry_set, transform, attribute_fallbacks);
2351
2352 bke::GeometrySet new_geometry_set;
2355 all_instance_attributes,
2356 gather_info.instances.attribute_fallback,
2357 new_geometry_set);
2358
2359 const int64_t total_points_num = get_final_points_num(gather_info.r_tasks);
2360 /* This doesn't have to be exact at all, it's just a rough estimate ot make decisions about
2361 * multi-threading (overhead). */
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,
2366 gather_info.r_tasks.pointcloud_tasks,
2367 all_pointclouds_info.attributes,
2368 new_geometry_set);
2370 all_meshes_info,
2371 gather_info.r_tasks.mesh_tasks,
2372 all_meshes_info.attributes,
2373 all_meshes_info.materials,
2374 new_geometry_set);
2376 all_curves_info,
2377 gather_info.r_tasks.curve_tasks,
2378 all_curves_info.attributes,
2379 new_geometry_set);
2380 execute_realize_grease_pencil_tasks(all_grease_pencils_info,
2381 gather_info.r_tasks.grease_pencil_tasks,
2382 all_grease_pencils_info.attributes,
2383 new_geometry_set);
2384 execute_realize_edit_data_tasks(gather_info.r_tasks.edit_data_tasks, new_geometry_set);
2385 });
2386 if (gather_info.r_tasks.first_volume) {
2387 new_geometry_set.add(*gather_info.r_tasks.first_volume);
2388 }
2389
2390 return new_geometry_set;
2391}
2392
2394
2395} // namespace blender::geometry
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)
support for deformation groups and hooks.
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)
#define BLI_assert(a)
Definition BLI_assert.h:50
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
Object groups, one object can be in many groups at once.
#define CURVE_TYPES_NUM
@ CD_PROP_FLOAT2
@ CD_PROP_STRING
#define MEM_SAFE_FREE(v)
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color attribute
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
VecBase< float, 3 > float3
const T & first() const
Definition BLI_array.hh:270
void reinitialize(const int64_t new_size)
Definition BLI_array.hh:388
AttributeSet attributes
constexpr bool contains(int64_t value) const
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
Definition BLI_span.hh:574
constexpr void fill(const T &value) const
Definition BLI_span.hh:518
constexpr T & last(const int64_t n=0) const
Definition BLI_span.hh:690
constexpr const T & first() const
Definition BLI_span.hh:316
static VArray ForSingle(T value, const int64_t size)
int64_t index_of(const Key &key) const
bool add(const Key &key)
int64_t size() const
const Key * data() const
bool is_empty() const
const Key * begin() const
const Key * end() const
int64_t index_of_or_add(const Key &key)
Span< T > as_span() const
Definition BLI_array.hh:232
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
Span< T > typed() const
const CPPType & type() const
int64_t size() const
static GVArray ForSingle(const CPPType &type, int64_t size, const void *value)
constexpr int64_t size() const
std::optional< Value > pop_try(const Key &key)
Definition BLI_map.hh:395
bool remove(const Key &key)
Definition BLI_map.hh:344
ItemIterator items() const
Definition BLI_map.hh:864
auto add_or_modify(const Key &key, const CreateValueF &create_value, const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
Definition BLI_map.hh:457
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
Definition BLI_span.hh:574
constexpr bool is_empty() const
Definition BLI_span.hh:510
constexpr void fill(const T &value) const
Definition BLI_span.hh:518
constexpr IndexRange index_range() const
Definition BLI_span.hh:671
constexpr void copy_from(Span< T > values) const
Definition BLI_span.hh:726
bool add_as(ForwardKey &&key)
Definition BLI_set.hh:256
constexpr Span slice(int64_t start, int64_t size) const
Definition BLI_span.hh:138
constexpr const T & first() const
Definition BLI_span.hh:316
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr const T & last(const int64_t n=0) const
Definition BLI_span.hh:326
constexpr IndexRange index_range() const
Definition BLI_span.hh:402
constexpr bool is_empty() const
Definition BLI_span.hh:261
std::optional< T > get_if_single() const
void materialize(MutableSpan< T > r_span) const
Span< T > get_internal_span() const
bool add(const Key &key)
int64_t size() const
int64_t size() const
void append(const T &value)
IndexRange index_range() const
void foreach_attribute(const FunctionRef< void(const AttributeIter &)> fn) const
GAttributeReader lookup(const StringRef attribute_id) const
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const void *default_value=nullptr) const
int domain_size(const AttrDomain domain) const
bool contains(const StringRef attribute_id) const
GAttributeReader get() const
MutableSpan< float3 > positions_for_write()
IndexRange curves_range() const
MutableAttributeAccessor attributes_for_write()
VArray< int > resolution() const
Span< float3 > positions() const
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
int attribute_domain_size(AttrDomain domain) const
void to_geometry_set(GeometrySet &r_geometry_set) const
Definition instances.cc:85
GeometryComponentPtr copy() const override
void replace(Instances *instances, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
Span< int > reference_handles() const
Definition instances.cc:207
Span< float4x4 > transforms() const
Definition instances.cc:225
Span< InstanceReference > references() const
Definition instances.cc:277
bke::AttributeAccessor attributes() const
int instances_num() const
Definition instances.cc:390
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
bool add(const StringRef attribute_id, const AttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer)
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)
void foreach_index(Fn &&fn) const
CCL_NAMESPACE_BEGIN struct Options options
static ushort indices[]
static void transform_positions(const Span< blender::float3 > src, const blender::float4x4 &transform, blender::MutableSpan< blender::float3 > dst)
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
static void add(blender::Map< std::string, std::string > &messages, Message &msg)
Definition msgfmt.cc:227
void copy(const GVArray &src, GMutableSpan dst, int64_t grain_size=4096)
void gather(const GVArray &src, const IndexMask &indices, GMutableSpan dst, int64_t grain_size=4096)
void curves_copy_parameters(const Curves &src, Curves &dst)
ImplicitSharingPtr< GeometryComponent > GeometryComponentPtr
const DataTypeConversions & get_implicit_type_conversions()
bool attribute_is_builtin_on_component_type(const GeometryComponent::Type type, StringRef name)
eCustomDataType attribute_data_type_highest_complexity(Span< eCustomDataType > data_types)
AttrDomain attribute_domain_highest_priority(Span< AttrDomain > domains)
const CPPType * custom_data_type_to_cpp_type(eCustomDataType type)
Curves * curves_new_nomain(int points_num, int curves_num)
struct blender::compositor::@345301070213251227305337367154215234324277345027::@113305264211110136200164070253045215160301331207 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))
uint32_t hash(uint32_t kx)
Definition noise.cc:72
OffsetIndices< int > accumulate_counts_to_offsets(MutableSpan< int > counts_to_offsets, int start_offset=0)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:95
void memory_bandwidth_bound_task(const int64_t approximate_bytes_touched, const Function &function)
Definition BLI_task.hh:243
MatBase< float, 4, 4 > float4x4
MatBase< float, 3, 3 > float3x3
VecBase< float, 3 > float3
void uninitialized_copy_n(const T *src, int64_t n, T *dst)
MatBase< float, 4, 4 > float4x4
GPU_SHADER_INTERFACE_INFO(overlay_edit_curve_handle_iface, "vert").flat(Type pos vertex_in(1, Type::UINT, "data") .vertex_out(overlay_edit_curve_handle_iface) .geometry_layout(PrimitiveIn Frequency::GEOMETRY storage_buf(1, Qualifier::READ, "uint", "data[]", Frequency::GEOMETRY) .push_constant(Type Frequency::GEOMETRY selection[]
unsigned int uint32_t
Definition stdint.h:80
__int64 int64_t
Definition stdint.h:89
CurvesGeometry geometry
struct Material ** material_array
int corners_num
int edges_num
struct Material ** mat
CustomData corner_data
ListBase vertex_group_names
short totcol
int faces_num
int verts_num
struct Material ** mat
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
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)
VectorSet< const Curves * > order
Array< RealizeCurveInfo > realize_info
VectorSet< const GreasePencil * > order
Array< GreasePencilRealizeInfo > realize_info
Vector< AttributeFallbacksArray > attribute_fallback
Vector< bke::GeometryComponentPtr > instances_components_to_merge
VectorSet< const Mesh * > order
Array< MeshRealizeInfo > realize_info
Array< PointCloudRealizeInfo > realize_info
VectorSet< const PointCloud * > order
MeshElementStartIndices mesh_offsets
CurvesElementStartIndices curves_offsets
const AllPointCloudsInfo & pointclouds
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
InstanceContext(const GatherTasksInfo &gather_info)
Array< std::optional< GVArraySpan > > attributes
Array< std::optional< GVArraySpan > > attributes
Array< std::optional< GVArraySpan > > attributes
AttributeFallbacksArray attribute_fallbacks
CurvesElementStartIndices start_indices
const bke::GeometryComponentEditData * edit_data
const GreasePencilRealizeInfo * grease_pencil_info
AttributeFallbacksArray attribute_fallbacks
const PointCloudRealizeInfo * pointcloud_info
ParamHandle ** handles
MatBase< float, 3, 3 > float3x3