From 93c9f1d22d8e0b0a51f015e2986422471e416dc9 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 17 Mar 2021 23:30:14 -0400 Subject: Progress on read only point separate node, doesn't work right now --- .../geometry/nodes/node_geo_point_separate.cc | 120 ++++++++++++--------- 1 file changed, 71 insertions(+), 49 deletions(-) (limited to 'source/blender') diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_separate.cc b/source/blender/nodes/geometry/nodes/node_geo_point_separate.cc index 83d7ea24f7a..51813bacaa4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_separate.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_separate.cc @@ -46,7 +46,8 @@ static void gather_positions_from_component_instances(const GeometryComponent &c const StringRef mask_attribute_name, Span transforms, MutableSpan> r_positions_a, - MutableSpan> r_positions_b) + MutableSpan> r_positions_b, + int &instance_index) { if (component.attribute_domain_size(ATTR_DOMAIN_POINT) == 0) { return; @@ -58,18 +59,22 @@ static void gather_positions_from_component_instances(const GeometryComponent &c "position", ATTR_DOMAIN_POINT, {0.0f, 0.0f, 0.0f}); Span masks = mask_attribute.get_span(); - Span component_positions = position_attribute.get_span(); + Span source_positions = position_attribute.get_span(); - for (const int instance_index : transforms.index_range()) { - const float4x4 &transform = transforms[instance_index]; + for (const int i_set_instance : transforms.index_range()) { + const float4x4 &transform = transforms[i_set_instance]; + Vector &instance_result_positions_a = r_positions_a[instance_index]; + Vector &instance_result_positions_b = r_positions_b[instance_index]; for (const int i : masks.index_range()) { if (masks[i]) { - r_positions_a[instance_index].append(transform * component_positions[i]); + instance_result_positions_b.append(transform * source_positions[i]); } else { - r_positions_b[instance_index].append(transform * component_positions[i]); + instance_result_positions_a.append(transform * source_positions[i]); } } + + instance_index++; } } @@ -81,28 +86,22 @@ static void get_positions_from_instances(Span set_groups, int instance_index = 0; for (const GeometryInstanceGroup &set_group : set_groups) { const GeometrySet &set = set_group.geometry_set; - - MutableSpan> set_instance_positions_a = r_positions_a.slice( - instance_index, set_group.transforms.size()); - MutableSpan> set_instance_positions_b = r_positions_b.slice( - instance_index, set_group.transforms.size()); - - if (set.has()) { - gather_positions_from_component_instances(*set.get_component_for_read(), + if (set.has()) { + gather_positions_from_component_instances(*set.get_component_for_read(), mask_attribute_name, set_group.transforms, - set_instance_positions_a, - set_instance_positions_b); + r_positions_a, + r_positions_b, + instance_index); } - if (set.has()) { - gather_positions_from_component_instances(*set.get_component_for_read(), + if (set.has()) { + gather_positions_from_component_instances(*set.get_component_for_read(), mask_attribute_name, set_group.transforms, - set_instance_positions_a, - set_instance_positions_b); + r_positions_a, + r_positions_b, + instance_index); } - - instance_index += set_group.transforms.size(); } } @@ -113,37 +112,39 @@ static PointCloud *create_point_cloud(Span> positions) points_len += instance_positions.size(); } PointCloud *pointcloud = BKE_pointcloud_new_nomain(points_len); - int point_index = 0; + int offset = 0; for (const Vector &instance_positions : positions) { - memcpy(pointcloud->co + point_index, positions.data(), sizeof(float3) * positions.size()); - point_index += instance_positions.size(); + memcpy(pointcloud->co + offset, positions.data(), sizeof(float3) * instance_positions.size()); + offset += instance_positions.size(); } + uninitialized_fill_n(pointcloud->radius, pointcloud->totpoint, 0.05f); + return pointcloud; } template -static void copy_from_span_and_mask(Span span, - Span mask, - MutableSpan out_span_a, - MutableSpan out_span_b, +static void copy_data_based_on_mask(Span data, + Span masks, + MutableSpan out_data_a, + MutableSpan out_data_b, int &offset_a, int &offset_b) { - for (const int i : span.index_range()) { - if (mask[i]) { - out_span_b[offset_b] = span[i]; + for (const int i : data.index_range()) { + if (masks[i]) { + out_data_b[offset_b] = data[i]; offset_b++; } else { - out_span_a[offset_a] = span[i]; + out_data_a[offset_a] = data[i]; offset_a++; } } } static void copy_attribute_from_component_instances(const GeometryComponent &component, - const int instances_len, + Span transforms, const StringRef mask_attribute_name, const StringRef attribute_name, const CustomDataType data_type, @@ -158,11 +159,25 @@ static void copy_attribute_from_component_instances(const GeometryComponent &com const BooleanReadAttribute mask_attribute = component.attribute_get_for_read( mask_attribute_name, ATTR_DOMAIN_POINT, false); + Span masks = mask_attribute.get_span(); const ReadAttributePtr attribute = component.attribute_try_get_for_read( attribute_name, ATTR_DOMAIN_POINT, data_type); - Span masks = mask_attribute.get_span(); + /* Advance offsets if the attribute doesn't exist. Note that this is inefficient since we already + * have this information, but we would need to keep track of the size of each component's result + * points. */ + if (!attribute) { + for (const int i : masks.index_range()) { + if (masks[i]) { + offset_b++; + } + else { + offset_a++; + } + } + return; + } const int start_offset_a = offset_a; const int start_offset_b = offset_b; @@ -172,10 +187,12 @@ static void copy_attribute_from_component_instances(const GeometryComponent &com Span span = attribute->get_span(); MutableSpan out_span_a = out_data_a.typed(); MutableSpan out_span_b = out_data_b.typed(); - copy_from_span_and_mask(span, masks, out_span_a, out_span_b, offset_a, offset_b); + copy_data_based_on_mask(span, masks, out_span_a, out_span_b, offset_a, offset_b); const int copied_len_a = offset_a - start_offset_a; const int copied_len_b = offset_b - start_offset_b; - for (int i = 1; i < instances_len; i++) { + + /* The data is the same for every instance of the same geometry, so just copy it. */ + for (int i = 1; i < transforms.size(); i++) { memcpy(out_span_a.data() + offset_a, out_span_a.data() + start_offset_a, sizeof(T) * copied_len_a); @@ -204,7 +221,7 @@ static void copy_attributes_to_output(Span set_groups, OutputAttributePtr attribute_out_b = out_component_b.attribute_try_get_for_output( attribute_name, ATTR_DOMAIN_POINT, output_data_type); BLI_assert(attribute_out_a && attribute_out_b); - if (!attribute_out_a || attribute_out_b) { + if (!attribute_out_a || !attribute_out_b) { continue; } @@ -215,10 +232,10 @@ static void copy_attributes_to_output(Span set_groups, int offset_b = 0; for (const GeometryInstanceGroup &set_group : set_groups) { const GeometrySet &set = set_group.geometry_set; - - if (set.has()) { - copy_attribute_from_component_instances(*set.get_component_for_read(), - set_group.transforms.size(), + Span transforms = set_group.transforms; + if (set.has()) { + copy_attribute_from_component_instances(*set.get_component_for_read(), + transforms, mask_attribute_name, attribute_name, output_data_type, @@ -227,9 +244,9 @@ static void copy_attributes_to_output(Span set_groups, offset_a, offset_b); } - if (set.has()) { - copy_attribute_from_component_instances(*set.get_component_for_read(), - set_group.transforms.size(), + if (set.has()) { + copy_attribute_from_component_instances(*set.get_component_for_read(), + transforms, mask_attribute_name, attribute_name, output_data_type, @@ -239,6 +256,9 @@ static void copy_attributes_to_output(Span set_groups, offset_b); } } + + attribute_out_a.apply_span_and_save(); + attribute_out_b.apply_span_and_save(); } } @@ -246,10 +266,6 @@ static void geo_node_point_separate_exec(GeoNodeExecParams params) { GeometrySet geometry_set = params.extract_input("Geometry"); const std::string mask_attribute_name = params.extract_input("Mask"); - if (mask_attribute_name.empty()) { - params.set_output("Geometry 1", std::move(GeometrySet())); - params.set_output("Geometry 2", std::move(GeometrySet())); - } Vector set_groups = bke::geometry_set_gather_instances(geometry_set); @@ -261,6 +277,12 @@ static void geo_node_point_separate_exec(GeoNodeExecParams params) } } + if (set_groups.is_empty()) { + params.set_output("Geometry 1", std::move(GeometrySet())); + params.set_output("Geometry 2", std::move(GeometrySet())); + return; + } + int instances_len = 0; for (const GeometryInstanceGroup &set_group : set_groups) { instances_len += set_group.transforms.size(); -- cgit v1.2.3