[Bf-blender-cvs] [a108f2462f2] temp-geometry-nodes-instances-api-v2: Rewrite point separate node to support instances (untested)
Hans Goudey
noreply at git.blender.org
Mon Feb 15 04:16:28 CET 2021
Commit: a108f2462f214cf7d4c8fda325d3e2ba92666b91
Author: Hans Goudey
Date: Sun Feb 14 21:12:04 2021 -0600
Branches: temp-geometry-nodes-instances-api-v2
https://developer.blender.org/rBa108f2462f214cf7d4c8fda325d3e2ba92666b91
Rewrite point separate node to support instances (untested)
===================================================================
M source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc
M source/blender/nodes/geometry/nodes/node_geo_point_separate.cc
===================================================================
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc
index 91b6bbdafc3..dc924ede3a1 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc
@@ -279,8 +279,6 @@ static void geo_node_random_attribute_exec(GeoNodeExecParams params)
geometry_set = geometry_set_realize_instances(geometry_set);
- geometry_set_realize_instances_for_write(geometry_set);
-
if (geometry_set.has<MeshComponent>()) {
randomize_attribute_on_component(geometry_set.get_component_for_write<MeshComponent>(),
params,
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 8bb8c5e980a..dd587b6bea9 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_point_separate.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_point_separate.cc
@@ -14,6 +14,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include "BKE_attribute_math.hh"
#include "BKE_mesh.h"
#include "BKE_persistent_data_handle.hh"
#include "BKE_pointcloud.h"
@@ -38,163 +39,240 @@ static bNodeSocketTemplate geo_node_point_instance_out[] = {
namespace blender::nodes {
-static void fill_new_attribute_from_input(const ReadAttribute &input_attribute,
- WriteAttribute &out_attribute_a,
- WriteAttribute &out_attribute_b,
- Span<bool> a_or_b)
+static void gather_positions_from_component_instances(const GeometryComponent &component,
+ const StringRef mask_attribute_name,
+ Span<float4x4> transforms,
+ MutableSpan<Vector<float3>> r_positions_a,
+ MutableSpan<Vector<float3>> r_positions_b)
{
- fn::GSpan in_span = input_attribute.get_span();
- int i_a = 0;
- int i_b = 0;
- for (int i_in = 0; i_in < in_span.size(); i_in++) {
- const bool move_to_b = a_or_b[i_in];
- if (move_to_b) {
- out_attribute_b.set(i_b, in_span[i_in]);
- i_b++;
- }
- else {
- out_attribute_a.set(i_a, in_span[i_in]);
- i_a++;
- }
+ if (component.attribute_domain_size(ATTR_DOMAIN_POINT) == 0) {
+ return;
}
-}
-/**
- * Move the original attribute values to the two output components.
- *
- * \note This assumes a consistent ordering of indices before and after the split,
- * which is true for points and a simple vertex array.
- */
-static void move_split_attributes(const GeometryComponent &in_component,
- GeometryComponent &out_component_a,
- GeometryComponent &out_component_b,
- Span<bool> a_or_b)
-{
- Set<std::string> attribute_names = in_component.attribute_names();
+ const BooleanReadAttribute mask_attribute = component.attribute_get_for_read<bool>(
+ mask_attribute_name, ATTR_DOMAIN_POINT, false);
+ const Float3ReadAttribute position_attribute = component.attribute_get_for_read<float3>(
+ "position", ATTR_DOMAIN_POINT, {0.0f, 0.0f, 0.0f});
- for (const std::string &name : attribute_names) {
- ReadAttributePtr attribute = in_component.attribute_try_get_for_read(name);
- BLI_assert(attribute);
+ Span<bool> masks = mask_attribute.get_span();
+ Span<float3> component_positions = position_attribute.get_span();
- /* Since this node only creates points and vertices, don't copy other attributes. */
- if (attribute->domain() != ATTR_DOMAIN_POINT) {
- continue;
+ for (const int instance_index : transforms.index_range()) {
+ const float4x4 &transform = transforms[instance_index];
+ for (const int i : masks.index_range()) {
+ if (masks[i]) {
+ r_positions_a[instance_index].append(transform * component_positions[i]);
+ }
+ else {
+ r_positions_b[instance_index].append(transform * component_positions[i]);
+ }
}
+ }
+}
- const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute->cpp_type());
- const AttributeDomain domain = attribute->domain();
+static void get_positions_from_instances(Span<GeometryInstanceGroup> set_groups,
+ const StringRef mask_attribute_name,
+ MutableSpan<Vector<float3>> r_positions_a,
+ MutableSpan<Vector<float3>> r_positions_b)
+{
+ int instance_index = 0;
+ for (const GeometryInstanceGroup &set_group : set_groups) {
+ const GeometrySet &set = set_group.geometry_set;
- /* Don't try to create the attribute on the new component if it already exists (i.e. has been
- * initialized by someone else). */
- if (!out_component_a.attribute_exists(name)) {
- if (!out_component_a.attribute_try_create(name, domain, data_type)) {
- continue;
- }
+ MutableSpan<Vector<float3>> set_instance_positions_a = r_positions_a.slice(
+ instance_index, set_group.transforms.size());
+ MutableSpan<Vector<float3>> set_instance_positions_b = r_positions_b.slice(
+ instance_index, set_group.transforms.size());
+
+ if (set.has<PointCloudComponent>()) {
+ gather_positions_from_component_instances(*set.get_component_for_read<PointCloudComponent>(),
+ mask_attribute_name,
+ set_group.transforms,
+ set_instance_positions_a,
+ set_instance_positions_b);
}
- if (!out_component_b.attribute_exists(name)) {
- if (!out_component_b.attribute_try_create(name, domain, data_type)) {
- continue;
- }
+ if (set.has<MeshComponent>()) {
+ gather_positions_from_component_instances(*set.get_component_for_read<MeshComponent>(),
+ mask_attribute_name,
+ set_group.transforms,
+ set_instance_positions_a,
+ set_instance_positions_b);
}
- WriteAttributePtr out_attribute_a = out_component_a.attribute_try_get_for_write(name);
- WriteAttributePtr out_attribute_b = out_component_b.attribute_try_get_for_write(name);
- if (!out_attribute_a || !out_attribute_b) {
- BLI_assert(false);
- continue;
- }
+ instance_index += set_group.transforms.size();
+ }
+}
- fill_new_attribute_from_input(*attribute, *out_attribute_a, *out_attribute_b, a_or_b);
+static PointCloud *create_point_cloud(Span<Vector<float3>> positions)
+{
+ int points_len = 0;
+ for (const Vector<float3> &instance_positions : positions) {
+ points_len += instance_positions.size();
+ }
+ PointCloud *pointcloud = BKE_pointcloud_new_nomain(points_len);
+ int point_index = 0;
+ for (const Vector<float3> &instance_positions : positions) {
+ memcpy(pointcloud->co + point_index, positions.data(), sizeof(float3) * positions.size());
+ point_index += instance_positions.size();
}
+
+ return pointcloud;
}
-/**
- * Find total in each new set and find which of the output sets each point will belong to.
- */
-static Array<bool> count_point_splits(const GeometryComponent &component,
- const GeoNodeExecParams ¶ms,
- int *r_a_total,
- int *r_b_total)
+template<typename T>
+static void copy_from_span_and_mask(Span<T> span,
+ Span<bool> mask,
+ MutableSpan<T> out_span_a,
+ MutableSpan<T> out_span_b,
+ int &offset_a,
+ int &offset_b)
{
- const BooleanReadAttribute mask_attribute = params.get_input_attribute<bool>(
- "Mask", component, ATTR_DOMAIN_POINT, false);
- Array<bool> masks = mask_attribute.get_span();
- const int in_total = masks.size();
-
- *r_b_total = 0;
- for (const bool mask : masks) {
- if (mask) {
- *r_b_total += 1;
+ for (const int i : span.index_range()) {
+ if (mask[i]) {
+ out_span_b[offset_b] = span[i];
+ offset_b++;
+ }
+ else {
+ out_span_a[offset_a] = span[i];
+ offset_a++;
}
}
- *r_a_total = in_total - *r_b_total;
-
- return masks;
}
-static void separate_mesh(const MeshComponent &in_component,
- const GeoNodeExecParams ¶ms,
- MeshComponent &out_component_a,
- MeshComponent &out_component_b)
+static void copy_attribute_from_component_instances(const GeometryComponent &component,
+ const int instances_len,
+ const StringRef mask_attribute_name,
+ const StringRef attribute_name,
+ const CustomDataType data_type,
+ fn::GMutableSpan out_data_a,
+ fn::GMutableSpan out_data_b,
+ int &offset_a,
+ int &offset_b)
{
- const int size = in_component.attribute_domain_size(ATTR_DOMAIN_POINT);
- if (size == 0) {
+ if (component.attribute_domain_size(ATTR_DOMAIN_POINT) == 0) {
return;
}
- int a_total;
- int b_total;
- Array<bool> a_or_b = count_point_splits(in_component, params, &a_total, &b_total);
+ const BooleanReadAttribute mask_attribute = component.attribute_get_for_read<bool>(
+ mask_attribute_name, ATTR_DOMAIN_POINT,
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list