27 const bNode *node =
b.node_or_null();
31 .
description(
"Mesh to find the closest surface point on");
32 if (node !=
nullptr) {
34 b.add_input(data_type,
"Value").hide_value().field_on_all();
40 "Splits the faces of the input mesh into groups which can be sampled individually");
49 if (node !=
nullptr) {
51 b.add_output(data_type,
"Value").dependent_field({3, 4});
54 .dependent_field({3, 4})
56 "Whether the sampling was successful. It can fail when the sampled group is empty");
79 bNode &node =
params.add_node(
"GeometryNodeSampleNearestSurface");
81 params.update_and_connect_available_socket(node,
"Value");
96 source_.ensure_owns_direct_data();
97 static const mf::Signature
signature = []() {
99 mf::SignatureBuilder builder{
"Sample Nearest Surface",
signature};
100 builder.single_input<
float3>(
"Position");
101 builder.single_input<
int>(
"Sample ID");
102 builder.single_output<
int>(
"Triangle Index");
103 builder.single_output<
float3>(
"Sample Position");
104 builder.single_output<
bool>(
"Is Valid", mf::ParamFlag::SupportsUnusedOutput);
109 const Mesh &
mesh = *source_.get_mesh();
114 field_evaluator.
add(group_id_field);
121 group_ids, memory, group_indices_);
122 const int groups_num = group_masks.
size();
125 bvh_trees_.reinitialize(groups_num);
130 for (
const int group_i : range) {
131 const IndexMask &group_mask = group_masks[group_i];
136 [&](
const int group_i) {
return group_masks[group_i].
size(); },
mesh.faces_num));
144 const VArray<int> &sample_ids =
params.readonly_single_input<
int>(1,
"Sample ID");
147 3,
"Sample Position");
151 mask.foreach_index([&](
const int i) {
152 const float3 position = positions[
i];
153 const int sample_id = sample_ids[
i];
154 const int group_index = group_indices_.index_of_try(sample_id);
155 if (group_index == -1) {
156 triangle_index[
i] = -1;
157 sample_position[
i] =
float3(0, 0, 0);
158 if (!is_valid_span.is_empty()) {
159 is_valid_span[
i] =
false;
172 triangle_index[
i] = nearest.
index;
173 sample_position[
i] = nearest.
co;
174 if (!is_valid_span.is_empty()) {
175 is_valid_span[
i] =
true;
192 if (
mesh ==
nullptr) {
193 params.set_default_remaining_outputs();
196 if (
mesh->verts_num == 0) {
197 params.set_default_remaining_outputs();
200 if (
mesh->faces_num == 0) {
202 params.set_default_remaining_outputs();
211 std::string error_message;
217 std::make_shared<SampleNearestSurfaceFunction>(
geometry, group_id_field),
218 {&sample_position, &sample_group_id},
219 {&triangle_index, &nearest_positions, &is_valid},
223 params.set_default_remaining_outputs();
231 std::make_shared<bke::mesh_surface_sample::BaryWeightFromPositionFn>(
geometry),
232 {&nearest_positions, &triangle_index_copy},
237 params.set_default_remaining_outputs();
244 std::make_shared<bke::mesh_surface_sample::BaryWeightSampleFn>(
geometry,
246 {&triangle_index, &bary_weights},
251 params.set_default_remaining_outputs();
256 params.set_output(
"Value", std::move(sample_value));
257 params.set_output(
"Is Valid", std::move(is_valid));
277 ntype.
ui_name =
"Sample Nearest Surface";
279 "Calculate the interpolated value of a mesh attribute on the closest point of its surface";
#define NODE_CLASS_GEOMETRY
#define GEO_NODE_SAMPLE_NEAREST_SURFACE
int BLI_bvhtree_find_nearest(const BVHTree *tree, const float co[3], BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata)
@ NODE_DEFAULT_INPUT_POSITION_FIELD
#define NOD_REGISTER_NODE(REGISTER_FUNC)
#define NOD_inline_enum_accessors(member)
static Vector< IndexMask, 4 > from_group_ids(const VArray< int > &group_ids, IndexMaskMemory &memory, VectorSet< int > &r_index_by_group_id)
int add(GField field, GVArray *varray_ptr)
const GVArray & get_evaluated(const int field_index) const
const Signature & signature() const
void set_signature(const Signature *signature)
Vector< SocketDeclaration * > inputs
StructureType structure_type
ExecutionHints get_execution_hints() const override
void call(const IndexMask &mask, mf::Params params, mf::Context) const override
SampleNearestSurfaceFunction(GeometrySet geometry, const Field< int > &group_id_field)
~SampleNearestSurfaceFunction() override=default
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
void node_register_type(bNodeType &ntype)
BVHTreeFromMesh bvhtree_from_mesh_tris_init(const Mesh &mesh, const IndexMask &faces_mask)
std::optional< eCustomDataType > socket_type_to_custom_data_type(eNodeSocketDatatype type)
void node_type_size_preset(bNodeType &ntype, eNodeSizePreset size)
const EnumPropertyItem * attribute_type_type_with_socket_fn(bContext *, PointerRNA *, PropertyRNA *, bool *r_free)
static void node_register()
static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms)
static void node_rna(StructRNA *srna)
static void node_declare(NodeDeclarationBuilder &b)
static void node_geo_exec(GeoNodeExecParams params)
static void node_layout(uiLayout *layout, bContext *, PointerRNA *ptr)
static void node_init(bNodeTree *, bNode *node)
void search_link_ops_for_declarations(GatherLinkSearchOpParams ¶ms, Span< SocketDeclaration * > declarations)
PropertyRNA * RNA_def_node_enum(StructRNA *srna, const char *identifier, const char *ui_name, const char *ui_description, const EnumPropertyItem *static_items, const EnumRNAAccessors accessors, std::optional< int > default_value, const EnumPropertyItemFunc item_func, const bool allow_animation)
bool execute_multi_function_on_value_variant(const MultiFunction &fn, const std::shared_ptr< MultiFunction > &owned_fn, const Span< SocketValueVariant * > input_values, const Span< SocketValueVariant * > output_values, GeoNodesUserData *user_data, std::string &r_error_message)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
auto individual_task_sizes(Fn &&fn, const std::optional< int64_t > full_size=std::nullopt)
VecBase< float, 3 > float3
void geo_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
const EnumPropertyItem rna_enum_attribute_type_items[]
BVHTree_NearestPointCallback nearest_callback
std::string ui_description
void(* initfunc)(bNodeTree *ntree, bNode *node)
NodeGeometryExecFunction geometry_node_execute
const char * enum_name_legacy
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
NodeDeclareFunction declare
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)