28 const bNode *node =
b.node_or_null();
31 .supported_type(GeometryComponent::Type::Mesh)
33 if (node !=
nullptr) {
35 b.add_input(data_type,
"Value").hide_value().field_on_all();
40 .
description(
"The mesh UV map to sample. Should not have overlapping faces");
43 .
description(
"The coordinates to sample within the UV map")
44 .structure_type(StructureType::Dynamic);
46 if (node !=
nullptr) {
48 b.add_output(data_type,
"Value").dependent_field({3});
52 .description(
"Whether the node could find a single face to sample at the UV coordinate");
76 bNode &node =
params.add_node(
"GeometryNodeSampleUVSurface");
78 params.update_and_connect_available_socket(node,
"Value");
87 std::optional<bke::MeshFieldContext> source_context_;
88 std::unique_ptr<FieldEvaluator> source_evaluator_;
91 std::optional<ReverseUVSampler> reverse_uv_sampler_;
95 : source_(std::move(
geometry)), src_uv_map_field_(std::move(src_uv_map_field))
97 source_.ensure_owns_direct_data();
98 this->evaluate_source();
100 static const mf::Signature
signature = []() {
102 mf::SignatureBuilder builder{
"Sample UV Surface",
signature};
103 builder.single_input<
float2>(
"Sample UV");
104 builder.single_output<
bool>(
"Is Valid", mf::ParamFlag::SupportsUnusedOutput);
105 builder.single_output<
int>(
"Triangle Index", mf::ParamFlag::SupportsUnusedOutput);
106 builder.single_output<
float3>(
"Barycentric Weights", mf::ParamFlag::SupportsUnusedOutput);
118 2,
"Triangle Index");
120 3,
"Barycentric Weights");
122 mask.foreach_index([&](
const int i) {
124 if (!is_valid.is_empty()) {
125 is_valid[
i] =
result.type == ReverseUVSampler::ResultType::Ok;
127 if (!tri_index.is_empty()) {
128 tri_index[
i] =
result.tri_index;
130 if (!bary_weights.is_empty()) {
131 bary_weights[
i] =
result.bary_weights;
137 void evaluate_source()
141 source_evaluator_ = std::make_unique<FieldEvaluator>(*source_context_, mesh.
corners_num);
142 source_evaluator_->add(src_uv_map_field_);
143 source_evaluator_->evaluate();
144 source_uv_map_ = source_evaluator_->get_evaluated<
float2>(0);
146 reverse_uv_sampler_.emplace(source_uv_map_, mesh.corner_tris());
154 if (mesh ==
nullptr) {
155 params.set_default_remaining_outputs();
158 if (mesh->faces_num == 0 && mesh->verts_num != 0) {
160 params.set_default_remaining_outputs();
171 if (sample_uv_value.is_list()) {
173 "Lists are not supported for \"Sample UV\" input");
175 if (sample_uv_value.is_volume_grid()) {
177 "Volume grids are not supported for \"Sample UV\" input");
183 std::make_shared<ReverseUVSampleFunction>(
geometry, std::move(source_uv_map)),
184 {std::move(sample_uvs)});
191 std::make_shared<bke::mesh_surface_sample::BaryWeightSampleFn>(std::move(
geometry),
214 ntype.
ui_name =
"Sample UV Surface";
216 "Calculate the interpolated values of a mesh attribute at a UV coordinate";
#define NODE_CLASS_GEOMETRY
#define GEO_NODE_SAMPLE_UV_SURFACE
#define NOD_REGISTER_NODE(REGISTER_FUNC)
#define NOD_inline_enum_accessors(member)
static const CPPType & get()
GVArray try_convert(GVArray varray, const CPPType &to_type) const
const Signature & signature() const
void set_signature(const Signature *signature)
static std::shared_ptr< FieldOperation > from(std::shared_ptr< const mf::MultiFunction > function, Vector< GField > inputs={})
Vector< SocketDeclaration * > inputs
Vector< SocketDeclaration * > outputs
ReverseUVSampleFunction(GeometrySet geometry, Field< float2 > src_uv_map_field)
void call(const IndexMask &mask, mf::Params params, mf::Context) const override
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
const DataTypeConversions & get_implicit_type_conversions()
void node_register_type(bNodeType &ntype)
std::optional< eCustomDataType > socket_type_to_custom_data_type(eNodeSocketDatatype type)
const EnumPropertyItem * attribute_type_type_with_socket_fn(bContext *, PointerRNA *, PropertyRNA *, bool *r_free)
static void node_register()
static void node_init(bNodeTree *, bNode *node)
static void node_rna(StructRNA *srna)
static void node_geo_exec(GeoNodeExecParams params)
static void node_layout(uiLayout *layout, bContext *, PointerRNA *ptr)
static void node_declare(NodeDeclarationBuilder &b)
static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms)
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)
VecBase< float, 2 > float2
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[]
const Mesh * get_mesh() const
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)