37 b.add_input<
decl::Vector>(
N_(
"Attribute")).hide_value().supports_field();
38 b.add_input<
decl::Float>(
N_(
"Attribute"),
"Attribute_001").hide_value().supports_field();
39 b.add_input<
decl::Color>(
N_(
"Attribute"),
"Attribute_002").hide_value().supports_field();
40 b.add_input<
decl::Bool>(
N_(
"Attribute"),
"Attribute_003").hide_value().supports_field();
41 b.add_input<
decl::Int>(
N_(
"Attribute"),
"Attribute_004").hide_value().supports_field();
53 b.add_output<
decl::Float>(
N_(
"Attribute"),
"Attribute_001").dependent_field({6, 7});
54 b.add_output<
decl::Color>(
N_(
"Attribute"),
"Attribute_002").dependent_field({6, 7});
55 b.add_output<
decl::Bool>(
N_(
"Attribute"),
"Attribute_003").dependent_field({6, 7});
56 b.add_output<
decl::Int>(
N_(
"Attribute"),
"Attribute_004").dependent_field({6, 7});
66 uiItemR(layout,
ptr,
"data_type", 0,
"", ICON_NONE);
67 uiItemR(layout,
ptr,
"mapping", 0,
"", ICON_NONE);
69 uiItemR(layout,
ptr,
"domain", 0,
"", ICON_NONE);
132 node_storage(
node).data_type = *
type;
133 params.update_and_connect_available_socket(
node,
"Attribute");
149 for (
const int i :
mask) {
156 r_indices[i] = nearest.
index;
159 r_distances_sq[i] = nearest.
dist_sq;
162 r_positions[i] = nearest.
co;
179 for (
const int i :
mask) {
185 r_indices[i] = nearest.
index;
187 r_distances_sq[i] = nearest.
dist_sq;
233 tree_data,
positions,
mask, r_looptri_indices, r_distances_sq, r_positions);
252 for (
const int i :
mask) {
253 const MLoopTri &looptri = looptris[looptri_indices[i]];
254 r_poly_indices[i] = looptri.
poly;
270 for (
const int i :
mask) {
272 const int poly_index = poly_indices[i];
276 float min_distance_sq = FLT_MAX;
277 const MVert *closest_mvert;
278 int closest_loop_index = 0;
281 const int vertex_index = loop.
v;
284 if (distance_sq < min_distance_sq) {
285 min_distance_sq = distance_sq;
286 closest_loop_index = loop_index;
287 closest_mvert = &mvert;
291 r_corner_indices[i] = closest_loop_index;
294 r_positions[i] = closest_mvert->
co;
297 r_distances_sq[i] = min_distance_sq;
308 if (
src.is_empty()) {
311 for (
const int i :
mask) {
322 if (
src.is_empty()) {
325 const int max_index =
src.size() - 1;
327 for (const int i : range) {
328 const int index = mask[i];
329 dst[index] = src[std::clamp(indices[index], 0, max_index)];
347 for (
const int i :
mask) {
348 if (distances_1[i] < distances_2[i]) {
349 dst[i] = src_1[indices_1[i]];
352 dst[i] = src_2[indices_2[i]];
368 return component.attribute_domain_size(domain) != 0;
390 std::optional<GeometryComponentFieldContext> source_context_;
391 std::unique_ptr<FieldEvaluator> source_evaluator_;
396 : source_(
std::move(geometry)), src_field_(
std::move(src_field))
401 this->evaluate_source_field();
428 interp.sample_data(*source_data_, domain_, eAttributeMapMode::INTERPOLATED, dst);
432 void evaluate_source_field()
437 source_evaluator_ = std::make_unique<FieldEvaluator>(*source_context_,
domain_num);
438 source_evaluator_->add(src_field_);
439 source_evaluator_->evaluate();
440 source_data_ = &source_evaluator_->get_evaluated(0);
460 std::optional<GeometryComponentFieldContext> mesh_context_;
461 std::unique_ptr<FieldEvaluator> mesh_evaluator_;
464 std::optional<GeometryComponentFieldContext> point_context_;
465 std::unique_ptr<FieldEvaluator> point_evaluator_;
470 : source_(
std::move(geometry)), src_field_(
std::move(src_field)), domain_(domain)
479 this->evaluate_source_field();
495 if (!use_mesh_ && !use_points_) {
496 dst.type().value_initialize_indices(dst.data(),
mask);
503 const int tot_samples =
mask.min_array_size();
552 using T = decltype(dummy);
553 if (use_mesh_ && use_points_) {
554 VArray<T> src_mesh = mesh_data_->typed<T>();
555 VArray<T> src_point = point_data_->typed<T>();
556 copy_with_indices_and_comparison(src_mesh,
565 else if (use_points_) {
569 else if (use_mesh_) {
577 void evaluate_source_field()
583 mesh_evaluator_ = std::make_unique<FieldEvaluator>(*mesh_context_,
domain_num);
584 mesh_evaluator_->add(src_field_);
585 mesh_evaluator_->evaluate();
586 mesh_data_ = &mesh_evaluator_->get_evaluated(0);
592 point_context_.emplace(GeometryComponentFieldContext(points, domain_));
593 point_evaluator_ = std::make_unique<FieldEvaluator>(*point_context_,
domain_num);
594 point_evaluator_->add(src_field_);
595 point_evaluator_->evaluate();
596 point_data_ = &point_evaluator_->get_evaluated(0);
631 std::optional<GeometryComponentFieldContext> geometry_context_;
632 std::unique_ptr<FieldEvaluator> evaluator_;
633 const GVArray *src_data_ =
nullptr;
637 : src_geometry_(
std::move(geometry)), src_field_(
std::move(src_field)), domain_(domain)
641 signature_ = this->create_signature();
642 this->set_signature(&signature_);
644 this->evaluate_field();
651 signature.single_output(
"Attribute", src_field_.
cpp_type());
652 return signature.build();
663 evaluator_ = std::make_unique<FieldEvaluator>(*geometry_context_,
domain_num);
664 evaluator_->add(src_field_);
665 evaluator_->evaluate();
666 src_data_ = &evaluator_->get_evaluated(0);
675 if (src_data_ ==
nullptr) {
676 type.value_initialize_indices(dst.data(),
mask);
681 using T = decltype(dummy);
745 auto return_default = [&]() {
747 using T = decltype(dummy);
756 if (
mesh ==
nullptr) {
758 params.error_message_add(NodeWarningType::Error,
759 TIP_(
"The source geometry must contain a mesh"));
761 return return_default();
766 params.error_message_add(NodeWarningType::Error,
767 TIP_(
"The source mesh must have faces"));
769 return return_default();
771 auto fn = std::make_unique<NearestInterpolatedTransferFunction>(std::move(geometry),
773 auto op = std::make_shared<FieldOperation>(
775 output_field =
GField(std::move(op));
780 params.error_message_add(NodeWarningType::Error,
781 TIP_(
"The source geometry must contain a mesh or a point cloud"));
782 return return_default();
784 auto fn = std::make_unique<NearestTransferFunction>(
785 std::move(geometry), std::move(field), domain);
786 auto op = std::make_shared<FieldOperation>(
788 output_field =
GField(std::move(op));
793 auto fn = std::make_unique<IndexTransferFunction>(
794 std::move(geometry), std::move(field), domain);
795 auto op = std::make_shared<FieldOperation>(
797 output_field =
GField(std::move(op));
818 "NodeGeometryTransferAttribute",
BVHTree * BKE_bvhtree_from_pointcloud_get(struct BVHTreeFromPointCloud *data, const struct PointCloud *pointcloud, int tree_type)
void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
void free_bvhtree_from_pointcloud(struct BVHTreeFromPointCloud *data)
BVHTree * BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, const struct Mesh *mesh, BVHCacheType bvh_cache_type, int tree_type)
@ GEO_COMPONENT_TYPE_MESH
@ GEO_COMPONENT_TYPE_POINT_CLOUD
@ GEO_COMPONENT_TYPE_INSTANCES
@ GEO_COMPONENT_TYPE_CURVE
const struct MLoopTri * BKE_mesh_runtime_looptri_ensure(const struct Mesh *mesh)
int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh)
void node_type_update(struct bNodeType *ntype, void(*updatefunc)(struct bNodeTree *ntree, struct bNode *node))
#define NODE_STORAGE_FUNCS(StorageT)
void nodeSetSocketAvailability(struct bNodeTree *ntree, struct bNodeSocket *sock, bool is_available)
void node_type_init(struct bNodeType *ntype, void(*initfunc)(struct bNodeTree *ntree, struct bNode *node))
#define GEO_NODE_TRANSFER_ATTRIBUTE
void node_type_storage(struct bNodeType *ntype, const char *storagename, void(*freefunc)(struct bNode *node), void(*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, const struct bNode *src_node))
#define NODE_CLASS_ATTRIBUTE
void nodeRegisterType(struct bNodeType *ntype)
#define BLI_assert_unreachable()
int BLI_bvhtree_find_nearest(BVHTree *tree, const float co[3], BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata)
static uint8 component(Color32 c, uint i)
GeometryNodeAttributeTransferMode
@ GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST_FACE_INTERPOLATED
@ GEO_NODE_ATTRIBUTE_TRANSFER_INDEX
@ GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
int attribute_domain_size(eAttrDomain domain) const
const Mesh * get_for_read() const
void reinitialize(const int64_t new_size)
VArray< T > typed() const
constexpr int64_t size() const
constexpr bool is_empty() const
const CPPType & cpp_type() const
void single_input(const char *name)
void set_signature(const MFSignature *signature)
const MFSignature & signature() const
Span< SocketDeclarationPtr > inputs() const
void make_available(bNode &node) const
fn::MFSignature create_signature()
void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
NearestInterpolatedTransferFunction(GeometrySet geometry, GField src_field)
NearestTransferFunction(GeometrySet geometry, GField src_field, eAttrDomain domain)
fn::MFSignature create_signature()
void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
SyclQueue void void * src
ccl_gpu_kernel_postfix int ccl_global int * indices
ccl_device_inline float2 interp(const float2 &a, const float2 &b, float t)
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
void convert_to_static_type(const CPPType &cpp_type, const Func &func)
static int domain_num(const CurvesGeometry &curves, const eAttrDomain domain)
eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type)
T distance_squared(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
void copy_with_indices(const VArray< T > &src, const IndexMask mask, const Span< int > indices, const MutableSpan< T > dst)
static void get_closest_mesh_looptris(const Mesh &mesh, const VArray< float3 > &positions, const IndexMask mask, const MutableSpan< int > r_looptri_indices, const MutableSpan< float > r_distances_sq, const MutableSpan< float3 > r_positions)
static void get_closest_mesh_corners(const Mesh &mesh, const VArray< float3 > &positions, const IndexMask mask, const MutableSpan< int > r_corner_indices, const MutableSpan< float > r_distances_sq, const MutableSpan< float3 > r_positions)
static void node_geo_exec(GeoNodeExecParams params)
static void get_closest_in_bvhtree(BVHTreeFromMesh &tree_data, const VArray< float3 > &positions, const IndexMask mask, const MutableSpan< int > r_indices, const MutableSpan< float > r_distances_sq, const MutableSpan< float3 > r_positions)
void copy_with_indices_clamped(const VArray< T > &src, const IndexMask mask, const VArray< int > &indices, const MutableSpan< T > dst)
static void get_closest_mesh_edges(const Mesh &mesh, const VArray< float3 > &positions, const IndexMask mask, const MutableSpan< int > r_edge_indices, const MutableSpan< float > r_distances_sq, const MutableSpan< float3 > r_positions)
static bool component_is_available(const GeometrySet &geometry, const GeometryComponentType type, const eAttrDomain domain)
static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
static void get_closest_mesh_points(const Mesh &mesh, const VArray< float3 > &positions, const IndexMask mask, const MutableSpan< int > r_point_indices, const MutableSpan< float > r_distances_sq, const MutableSpan< float3 > r_positions)
static const GeometryComponent * find_source_component(const GeometrySet &geometry, const eAttrDomain domain)
static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms)
static void node_declare(NodeDeclarationBuilder &b)
static GField get_input_attribute_field(GeoNodeExecParams ¶ms, const eCustomDataType data_type)
void copy_with_indices_and_comparison(const VArray< T > &src_1, const VArray< T > &src_2, const Span< float > distances_1, const Span< float > distances_2, const IndexMask mask, const Span< int > indices_1, const Span< int > indices_2, const MutableSpan< T > dst)
static void node_update(bNodeTree *ntree, bNode *node)
static void get_closest_mesh_polygons(const Mesh &mesh, const VArray< float3 > &positions, const IndexMask mask, const MutableSpan< int > r_poly_indices, const MutableSpan< float > r_distances_sq, const MutableSpan< float3 > r_positions)
static void output_attribute_field(GeoNodeExecParams ¶ms, GField field)
static void get_closest_pointcloud_points(const PointCloud &pointcloud, const VArray< float3 > &positions, const IndexMask mask, const MutableSpan< int > r_indices, const MutableSpan< float > r_distances_sq)
static void node_init(bNodeTree *UNUSED(tree), bNode *node)
std::optional< eCustomDataType > node_data_type_to_custom_data_type(const eNodeSocketDatatype type)
void search_link_ops_for_declarations(GatherLinkSearchOpParams ¶ms, Span< SocketDeclarationPtr > declarations)
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
vec_base< float, 3 > float3
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node)
MutableSpan< float3 > positions
void register_node_type_geo_transfer_attribute()
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
void node_copy_standard_storage(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, const bNode *src_node)
void node_free_standard_storage(bNode *node)
BVHTree_NearestPointCallback nearest_callback
BVHTree_NearestPointCallback nearest_callback
const PointCloud * get_pointcloud_for_read() const
void ensure_owns_direct_data()
bool has(const GeometryComponentType component_type) const
const GeometryComponent * get_component_for_read(GeometryComponentType component_type) const
const Mesh * get_mesh_for_read() const
bool has_pointcloud() const
struct bNodeSocket * next
NodeGeometryExecFunction geometry_node_execute
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
void(* draw_buttons)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr)
NodeDeclareFunction declare