Differential D12903 Diff 43610 source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc
Changeset View
Changeset View
Standalone View
Standalone View
source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc
| Show First 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | b.add_input<decl::Float>("Density Factor") | ||||
| .max(1.0f) | .max(1.0f) | ||||
| .subtype(PROP_FACTOR) | .subtype(PROP_FACTOR) | ||||
| .supports_field(); | .supports_field(); | ||||
| b.add_input<decl::Int>("Seed"); | b.add_input<decl::Int>("Seed"); | ||||
| b.add_output<decl::Geometry>("Points"); | b.add_output<decl::Geometry>("Points"); | ||||
| b.add_output<decl::Vector>("Normal").field_source(); | b.add_output<decl::Vector>("Normal").field_source(); | ||||
| b.add_output<decl::Vector>("Rotation").subtype(PROP_EULER).field_source(); | b.add_output<decl::Vector>("Rotation").subtype(PROP_EULER).field_source(); | ||||
| b.add_output<decl::Int>("Stable ID").field_source(); | |||||
| } | } | ||||
| static void geo_node_point_distribute_points_on_faces_layout(uiLayout *layout, | static void geo_node_point_distribute_points_on_faces_layout(uiLayout *layout, | ||||
| bContext *UNUSED(C), | bContext *UNUSED(C), | ||||
| PointerRNA *ptr) | PointerRNA *ptr) | ||||
| { | { | ||||
| uiItemR(layout, ptr, "distribute_method", 0, "", ICON_NONE); | uiItemR(layout, ptr, "distribute_method", 0, "", ICON_NONE); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 254 Lines • ▼ Show 20 Lines | for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { | ||||
| attribute_out.save(); | attribute_out.save(); | ||||
| } | } | ||||
| } | } | ||||
| namespace { | namespace { | ||||
| struct AttributeOutputs { | struct AttributeOutputs { | ||||
| StrongAnonymousAttributeID normal_id; | StrongAnonymousAttributeID normal_id; | ||||
| StrongAnonymousAttributeID rotation_id; | StrongAnonymousAttributeID rotation_id; | ||||
| StrongAnonymousAttributeID stable_id_id; | |||||
| }; | }; | ||||
| } // namespace | } // namespace | ||||
| BLI_NOINLINE static void compute_attribute_outputs(const MeshComponent &mesh_component, | BLI_NOINLINE static void compute_attribute_outputs(const MeshComponent &mesh_component, | ||||
| PointCloudComponent &point_component, | PointCloudComponent &point_component, | ||||
| const Span<float3> bary_coords, | const Span<float3> bary_coords, | ||||
| const Span<int> looptri_indices, | const Span<int> looptri_indices, | ||||
| const AttributeOutputs &attribute_outputs) | const AttributeOutputs &attribute_outputs) | ||||
| { | { | ||||
| OutputAttribute_Typed<int> id_attribute; | OutputAttribute_Typed<int> id_attribute = point_component.attribute_try_get_for_output_only<int>( | ||||
| "random_point_id", ATTR_DOMAIN_POINT); | |||||
| MutableSpan<int> ids = id_attribute.as_span(); | |||||
JacquesLucke: This returns null for some reason when the point cloud is empty, which is causing the crash… | |||||
Done Inline ActionsI think it might be valid to return null when the point cloud has no points, even if it didn't happen before for some reason (looked into it for a bit and didn't figure out why that changed). HooglyBoogly: I think it might be valid to return null when the point cloud has no points, even if it didn't… | |||||
| OutputAttribute_Typed<float3> normal_attribute; | OutputAttribute_Typed<float3> normal_attribute; | ||||
| OutputAttribute_Typed<float3> rotation_attribute; | OutputAttribute_Typed<float3> rotation_attribute; | ||||
| MutableSpan<int> ids; | |||||
| MutableSpan<float3> normals; | MutableSpan<float3> normals; | ||||
| MutableSpan<float3> rotations; | MutableSpan<float3> rotations; | ||||
| if (attribute_outputs.stable_id_id) { | |||||
| id_attribute = point_component.attribute_try_get_for_output_only<int>( | |||||
| attribute_outputs.stable_id_id.get(), ATTR_DOMAIN_POINT); | |||||
| ids = id_attribute.as_span(); | |||||
| } | |||||
| if (attribute_outputs.normal_id) { | if (attribute_outputs.normal_id) { | ||||
| normal_attribute = point_component.attribute_try_get_for_output_only<float3>( | normal_attribute = point_component.attribute_try_get_for_output_only<float3>( | ||||
| attribute_outputs.normal_id.get(), ATTR_DOMAIN_POINT); | attribute_outputs.normal_id.get(), ATTR_DOMAIN_POINT); | ||||
| normals = normal_attribute.as_span(); | normals = normal_attribute.as_span(); | ||||
| } | } | ||||
| if (attribute_outputs.rotation_id) { | if (attribute_outputs.rotation_id) { | ||||
| rotation_attribute = point_component.attribute_try_get_for_output_only<float3>( | rotation_attribute = point_component.attribute_try_get_for_output_only<float3>( | ||||
| attribute_outputs.rotation_id.get(), ATTR_DOMAIN_POINT); | attribute_outputs.rotation_id.get(), ATTR_DOMAIN_POINT); | ||||
| Show All 11 Lines | for (const int i : bary_coords.index_range()) { | ||||
| const int v0_index = mesh.mloop[looptri.tri[0]].v; | const int v0_index = mesh.mloop[looptri.tri[0]].v; | ||||
| const int v1_index = mesh.mloop[looptri.tri[1]].v; | const int v1_index = mesh.mloop[looptri.tri[1]].v; | ||||
| const int v2_index = mesh.mloop[looptri.tri[2]].v; | const int v2_index = mesh.mloop[looptri.tri[2]].v; | ||||
| const float3 v0_pos = float3(mesh.mvert[v0_index].co); | const float3 v0_pos = float3(mesh.mvert[v0_index].co); | ||||
| const float3 v1_pos = float3(mesh.mvert[v1_index].co); | const float3 v1_pos = float3(mesh.mvert[v1_index].co); | ||||
| const float3 v2_pos = float3(mesh.mvert[v2_index].co); | const float3 v2_pos = float3(mesh.mvert[v2_index].co); | ||||
| if (!ids.is_empty()) { | |||||
| ids[i] = noise::hash(noise::hash_float(bary_coord), looptri_index); | ids[i] = noise::hash(noise::hash_float(bary_coord), looptri_index); | ||||
| } | |||||
| float3 normal; | float3 normal; | ||||
| if (!normals.is_empty() || !rotations.is_empty()) { | if (!normals.is_empty() || !rotations.is_empty()) { | ||||
| normal_tri_v3(normal, v0_pos, v1_pos, v2_pos); | normal_tri_v3(normal, v0_pos, v1_pos, v2_pos); | ||||
| } | } | ||||
| if (!normals.is_empty()) { | if (!normals.is_empty()) { | ||||
| normals[i] = normal; | normals[i] = normal; | ||||
| } | } | ||||
| if (!rotations.is_empty()) { | if (!rotations.is_empty()) { | ||||
| rotations[i] = normal_to_euler_rotation(normal); | rotations[i] = normal_to_euler_rotation(normal); | ||||
| } | } | ||||
| } | } | ||||
| if (id_attribute) { | |||||
| id_attribute.save(); | id_attribute.save(); | ||||
| } | |||||
| if (normal_attribute) { | if (normal_attribute) { | ||||
| normal_attribute.save(); | normal_attribute.save(); | ||||
| } | } | ||||
| if (rotation_attribute) { | if (rotation_attribute) { | ||||
| rotation_attribute.save(); | rotation_attribute.save(); | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 99 Lines • ▼ Show 20 Lines | case GEO_NODE_POINT_DISTRIBUTE_POINTS_ON_FACES_POISSON: { | ||||
| seed, | seed, | ||||
| positions, | positions, | ||||
| bary_coords, | bary_coords, | ||||
| looptri_indices); | looptri_indices); | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if (positions.is_empty()) { | |||||
| return; | |||||
| } | |||||
| PointCloud *pointcloud = BKE_pointcloud_new_nomain(positions.size()); | PointCloud *pointcloud = BKE_pointcloud_new_nomain(positions.size()); | ||||
| memcpy(pointcloud->co, positions.data(), sizeof(float3) * positions.size()); | memcpy(pointcloud->co, positions.data(), sizeof(float3) * positions.size()); | ||||
| uninitialized_fill_n(pointcloud->radius, pointcloud->totpoint, 0.05f); | uninitialized_fill_n(pointcloud->radius, pointcloud->totpoint, 0.05f); | ||||
| geometry_set.replace_pointcloud(pointcloud); | geometry_set.replace_pointcloud(pointcloud); | ||||
| PointCloudComponent &point_component = | PointCloudComponent &point_component = | ||||
| geometry_set.get_component_for_write<PointCloudComponent>(); | geometry_set.get_component_for_write<PointCloudComponent>(); | ||||
| Show All 23 Lines | static void geo_node_point_distribute_points_on_faces_exec(GeoNodeExecParams params) | ||||
| AttributeOutputs attribute_outputs; | AttributeOutputs attribute_outputs; | ||||
| if (params.output_is_required("Normal")) { | if (params.output_is_required("Normal")) { | ||||
| attribute_outputs.normal_id = StrongAnonymousAttributeID("normal"); | attribute_outputs.normal_id = StrongAnonymousAttributeID("normal"); | ||||
| } | } | ||||
| if (params.output_is_required("Rotation")) { | if (params.output_is_required("Rotation")) { | ||||
| attribute_outputs.rotation_id = StrongAnonymousAttributeID("rotation"); | attribute_outputs.rotation_id = StrongAnonymousAttributeID("rotation"); | ||||
| } | } | ||||
| if (params.output_is_required("Stable ID")) { | |||||
| attribute_outputs.stable_id_id = StrongAnonymousAttributeID("stable id"); | |||||
| } | |||||
| geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { | geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { | ||||
| point_distribution_calculate( | point_distribution_calculate( | ||||
| geometry_set, selection_field, method, seed, attribute_outputs, params); | geometry_set, selection_field, method, seed, attribute_outputs, params); | ||||
| /* Keep instances because the original geometry set may contain instances that are processed as | /* Keep instances because the original geometry set may contain instances that are processed as | ||||
| * well. */ | * well. */ | ||||
| geometry_set.keep_only({GEO_COMPONENT_TYPE_POINT_CLOUD, GEO_COMPONENT_TYPE_INSTANCES}); | geometry_set.keep_only({GEO_COMPONENT_TYPE_POINT_CLOUD, GEO_COMPONENT_TYPE_INSTANCES}); | ||||
| }); | }); | ||||
| params.set_output("Points", std::move(geometry_set)); | params.set_output("Points", std::move(geometry_set)); | ||||
| if (attribute_outputs.normal_id) { | if (attribute_outputs.normal_id) { | ||||
| params.set_output( | params.set_output( | ||||
| "Normal", | "Normal", | ||||
| AnonymousAttributeFieldInput::Create<float3>(std::move(attribute_outputs.normal_id))); | AnonymousAttributeFieldInput::Create<float3>(std::move(attribute_outputs.normal_id))); | ||||
| } | } | ||||
| if (attribute_outputs.rotation_id) { | if (attribute_outputs.rotation_id) { | ||||
| params.set_output( | params.set_output( | ||||
| "Rotation", | "Rotation", | ||||
| AnonymousAttributeFieldInput::Create<float3>(std::move(attribute_outputs.rotation_id))); | AnonymousAttributeFieldInput::Create<float3>(std::move(attribute_outputs.rotation_id))); | ||||
| } | } | ||||
| if (attribute_outputs.stable_id_id) { | |||||
| params.set_output( | |||||
| "Stable ID", | |||||
| AnonymousAttributeFieldInput::Create<int>(std::move(attribute_outputs.stable_id_id))); | |||||
| } | |||||
| } | } | ||||
| } // namespace blender::nodes | } // namespace blender::nodes | ||||
| void register_node_type_geo_distribute_points_on_faces() | void register_node_type_geo_distribute_points_on_faces() | ||||
| { | { | ||||
| static bNodeType ntype; | static bNodeType ntype; | ||||
| Show All 12 Lines | |||||
This returns null for some reason when the point cloud is empty, which is causing the crash Dalai mentions.