Changeset View
Changeset View
Standalone View
Standalone View
source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc
| /* SPDX-License-Identifier: GPL-2.0-or-later */ | /* SPDX-License-Identifier: GPL-2.0-or-later */ | ||||
| #include "BLI_array_utils.hh" | |||||
| #include "BLI_task.hh" | #include "BLI_task.hh" | ||||
| #include "DNA_mesh_types.h" | #include "DNA_mesh_types.h" | ||||
| #include "DNA_pointcloud_types.h" | #include "DNA_pointcloud_types.h" | ||||
| #include "BKE_attribute_math.hh" | #include "BKE_attribute_math.hh" | ||||
| #include "BKE_pointcloud.h" | #include "BKE_pointcloud.h" | ||||
| Show All 28 Lines | |||||
| static void node_init(bNodeTree *UNUSED(tree), bNode *node) | static void node_init(bNodeTree *UNUSED(tree), bNode *node) | ||||
| { | { | ||||
| NodeGeometryMeshToPoints *data = MEM_cnew<NodeGeometryMeshToPoints>(__func__); | NodeGeometryMeshToPoints *data = MEM_cnew<NodeGeometryMeshToPoints>(__func__); | ||||
| data->mode = GEO_NODE_MESH_TO_POINTS_VERTICES; | data->mode = GEO_NODE_MESH_TO_POINTS_VERTICES; | ||||
| node->storage = data; | node->storage = data; | ||||
| } | } | ||||
| static void materialize_compressed_to_uninitialized_threaded(const GVArray &src, | |||||
| const IndexMask mask, | |||||
| GMutableSpan dst) | |||||
| { | |||||
| BLI_assert(src.type() == dst.type()); | |||||
| BLI_assert(mask.size() == dst.size()); | |||||
| threading::parallel_for(mask.index_range(), 4096, [&](IndexRange range) { | |||||
| src.materialize_compressed_to_uninitialized(mask.slice(range), dst.slice(range).data()); | |||||
| }); | |||||
| } | |||||
| static void geometry_set_mesh_to_points(GeometrySet &geometry_set, | static void geometry_set_mesh_to_points(GeometrySet &geometry_set, | ||||
| Field<float3> &position_field, | Field<float3> &position_field, | ||||
| Field<float> &radius_field, | Field<float> &radius_field, | ||||
| Field<bool> &selection_field, | Field<bool> &selection_field, | ||||
| const eAttrDomain domain) | const eAttrDomain domain) | ||||
| { | { | ||||
| const Mesh *mesh = geometry_set.get_mesh_for_read(); | const Mesh *mesh = geometry_set.get_mesh_for_read(); | ||||
| if (mesh == nullptr) { | if (mesh == nullptr) { | ||||
| Show All 17 Lines | static void geometry_set_mesh_to_points(GeometrySet &geometry_set, | ||||
| const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); | const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); | ||||
| PointCloud *pointcloud = BKE_pointcloud_new_nomain(selection.size()); | PointCloud *pointcloud = BKE_pointcloud_new_nomain(selection.size()); | ||||
| geometry_set.replace_pointcloud(pointcloud); | geometry_set.replace_pointcloud(pointcloud); | ||||
| MutableAttributeAccessor dst_attributes = pointcloud->attributes_for_write(); | MutableAttributeAccessor dst_attributes = pointcloud->attributes_for_write(); | ||||
| GSpanAttributeWriter position = dst_attributes.lookup_or_add_for_write_only_span( | GSpanAttributeWriter position = dst_attributes.lookup_or_add_for_write_only_span( | ||||
| "position", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3); | "position", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3); | ||||
| materialize_compressed_to_uninitialized_threaded( | array_utils::gather(evaluator.get_evaluated(0), selection, position.span); | ||||
| evaluator.get_evaluated(0), selection, position.span); | |||||
| position.finish(); | position.finish(); | ||||
| GSpanAttributeWriter radius = dst_attributes.lookup_or_add_for_write_only_span( | GSpanAttributeWriter radius = dst_attributes.lookup_or_add_for_write_only_span( | ||||
| "radius", ATTR_DOMAIN_POINT, CD_PROP_FLOAT); | "radius", ATTR_DOMAIN_POINT, CD_PROP_FLOAT); | ||||
| materialize_compressed_to_uninitialized_threaded( | array_utils::gather(evaluator.get_evaluated(1), selection, radius.span); | ||||
| evaluator.get_evaluated(1), selection, radius.span); | |||||
| radius.finish(); | radius.finish(); | ||||
| Map<AttributeIDRef, AttributeKind> attributes; | Map<AttributeIDRef, AttributeKind> attributes; | ||||
| geometry_set.gather_attributes_for_propagation( | geometry_set.gather_attributes_for_propagation( | ||||
| {GEO_COMPONENT_TYPE_MESH}, GEO_COMPONENT_TYPE_POINT_CLOUD, false, attributes); | {GEO_COMPONENT_TYPE_MESH}, GEO_COMPONENT_TYPE_POINT_CLOUD, false, attributes); | ||||
| attributes.remove("position"); | attributes.remove("position"); | ||||
| const AttributeAccessor src_attributes = mesh->attributes(); | const AttributeAccessor src_attributes = mesh->attributes(); | ||||
| for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { | for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { | ||||
| const AttributeIDRef attribute_id = entry.key; | const AttributeIDRef attribute_id = entry.key; | ||||
| const eCustomDataType data_type = entry.value.data_type; | const eCustomDataType data_type = entry.value.data_type; | ||||
| GVArray src = src_attributes.lookup_or_default(attribute_id, domain, data_type); | GVArray src = src_attributes.lookup_or_default(attribute_id, domain, data_type); | ||||
| GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span( | GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span( | ||||
| attribute_id, ATTR_DOMAIN_POINT, data_type); | attribute_id, ATTR_DOMAIN_POINT, data_type); | ||||
| if (dst && src) { | if (dst && src) { | ||||
| materialize_compressed_to_uninitialized_threaded(src, selection, dst.span); | array_utils::gather(src, selection, dst.span); | ||||
| dst.finish(); | dst.finish(); | ||||
| } | } | ||||
| } | } | ||||
| geometry_set.keep_only_during_modify({GEO_COMPONENT_TYPE_POINT_CLOUD}); | geometry_set.keep_only_during_modify({GEO_COMPONENT_TYPE_POINT_CLOUD}); | ||||
| } | } | ||||
| static void node_geo_exec(GeoNodeExecParams params) | static void node_geo_exec(GeoNodeExecParams params) | ||||
| ▲ Show 20 Lines • Show All 60 Lines • Show Last 20 Lines | |||||