29 const bNode *node =
b.node_or_null();
34 if (node !=
nullptr) {
37 b.add_input(data_type,
"Attribute").hide_value().field_on_all();
41 b.add_input<
decl::Vector>(
"Ray Direction").default_value({0.0f, 0.0f, -1.0f}).supports_field();
43 .default_value(100.0f)
48 b.add_output<
decl::Bool>(
"Is Hit").dependent_field({2, 3, 4});
49 b.add_output<
decl::Vector>(
"Hit Position").dependent_field({2, 3, 4});
50 b.add_output<
decl::Vector>(
"Hit Normal").dependent_field({2, 3, 4});
51 b.add_output<
decl::Float>(
"Hit Distance").dependent_field({2, 3, 4});
53 if (node !=
nullptr) {
55 b.add_output(data_type,
"Attribute").dependent_field({2, 3, 4});
84 bNode &node =
params.add_node(
"GeometryNodeRaycast");
85 node_storage(node).data_type = *type;
86 params.update_and_connect_available_socket(node,
"Attribute");
106 if (tree_data.
tree ==
nullptr) {
112 mask.foreach_index([&](
const int i) {
113 const float ray_length = ray_lengths[i];
114 const float3 ray_origin = ray_origins[i];
115 const float3 ray_direction = ray_directions[i];
119 hit.dist = ray_length;
128 if (!r_hit.is_empty()) {
129 r_hit[i] = hit.index >= 0;
133 r_hit_indices[i] = hit.index;
136 r_hit_positions[i] = hit.co;
139 r_hit_normals[i] = hit.no;
142 r_hit_distances[i] = hit.dist;
150 r_hit_indices[i] = -1;
153 r_hit_positions[i] = float3(0.0f, 0.0f, 0.0f);
156 r_hit_normals[i] = float3(0.0f, 0.0f, 0.0f);
159 r_hit_distances[i] = ray_length;
176 builder.single_input<
float3>(
"Source Position");
177 builder.single_input<
float3>(
"Ray Direction");
178 builder.single_input<
float>(
"Ray Length");
179 builder.single_output<
bool>(
"Is Hit", mf::ParamFlag::SupportsUnusedOutput);
180 builder.single_output<
float3>(
"Hit Position", mf::ParamFlag::SupportsUnusedOutput);
181 builder.single_output<
float3>(
"Hit Normal", mf::ParamFlag::SupportsUnusedOutput);
182 builder.single_output<
float>(
"Distance", mf::ParamFlag::SupportsUnusedOutput);
183 builder.single_output<
int>(
"Triangle Index", mf::ParamFlag::SupportsUnusedOutput);
186 this->set_signature(&signature);
196 params.readonly_single_input<
float3>(0,
"Source Position"),
197 params.readonly_single_input<
float3>(1,
"Ray Direction"),
198 params.readonly_single_input<
float>(2,
"Ray Length"),
199 params.uninitialized_single_output_if_required<
bool>(3,
"Is Hit"),
200 params.uninitialized_single_output_if_required<
int>(7,
"Triangle Index"),
201 params.uninitialized_single_output_if_required<
float3>(4,
"Hit Position"),
202 params.uninitialized_single_output_if_required<
float3>(5,
"Hit Normal"),
203 params.uninitialized_single_output_if_required<
float>(6,
"Distance"));
213 if (target.is_empty()) {
214 params.set_default_remaining_outputs();
218 if (!target.has_mesh()) {
219 params.set_default_remaining_outputs();
223 if (target.get_mesh()->faces_num == 0) {
224 params.error_message_add(NodeWarningType::Error,
TIP_(
"The target mesh must have faces"));
225 params.set_default_remaining_outputs();
229 static auto normalize_fn = mf::build::SI1_SO<float3, float3>(
232 mf::build::exec_presets::AllSpanOrSingle());
233 auto direction_op = FieldOperation::Create(
236 auto op = FieldOperation::Create(std::make_unique<RaycastFunction>(target),
243 params.set_output(
"Hit Position", hit_position);
247 if (!
params.output_is_required(
"Attribute")) {
257 std::make_shared<bke::mesh_surface_sample::BaryWeightFromPositionFn>(target),
258 {hit_position, triangle_index}));
262 std::make_shared<bke::mesh_surface_sample::CornerBaryWeightFromPositionFn>(target),
263 {hit_position, triangle_index}));
266 auto sample_op = FieldOperation::Create(
267 std::make_shared<bke::mesh_surface_sample::BaryWeightSampleFn>(std::move(target),
269 {triangle_index, bary_weights});
280 "Interpolate the attribute from the corners of the hit face"},
285 "Use the attribute value of the closest mesh element"},
286 {0,
nullptr, 0,
nullptr,
nullptr},
292 "Mapping from the target geometry to hit points",
299 "Type of data stored in attribute",
303 enums::attribute_type_type_with_socket_fn);
311 bke::node_type_size_preset(&ntype, bke::eNodeSizePreset::Middle);
void free_bvhtree_from_mesh(BVHTreeFromMesh *data)
BVHTree * BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data, const Mesh *mesh, BVHCacheType bvh_cache_type, int tree_type)
@ BVHTREE_FROM_CORNER_TRIS
#define NODE_STORAGE_FUNCS(StorageT)
#define NODE_CLASS_GEOMETRY
int BLI_bvhtree_ray_cast(const BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata)
#define BLI_SCOPED_DEFER(function_to_defer)
GeometryNodeRaycastMapMode
@ GEO_NODE_RAYCAST_NEAREST
@ GEO_NODE_RAYCAST_INTERPOLATED
#define NOD_REGISTER_NODE(REGISTER_FUNC)
#define NOD_storage_enum_accessors(member)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
ATTR_WARN_UNUSED_RESULT const BMVert * v
constexpr bool is_empty() const
Vector< SocketDeclaration * > inputs
Vector< SocketDeclaration * > outputs
void call(const IndexMask &mask, mf::Params params, mf::Context) const override
RaycastFunction(GeometrySet target)
local_group_size(16, 16) .push_constant(Type b
void node_type_storage(bNodeType *ntype, const char *storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
void node_register_type(bNodeType *ntype)
std::optional< eCustomDataType > socket_type_to_custom_data_type(eNodeSocketDatatype type)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
static void node_geo_exec(GeoNodeExecParams params)
static void node_init(bNodeTree *, bNode *node)
static void node_rna(StructRNA *srna)
static void node_layout(uiLayout *layout, bContext *, PointerRNA *ptr)
static void raycast_to_mesh(const IndexMask &mask, const Mesh &mesh, const VArray< float3 > &ray_origins, const VArray< float3 > &ray_directions, const VArray< float > &ray_lengths, const MutableSpan< bool > r_hit, const MutableSpan< int > r_hit_indices, const MutableSpan< float3 > r_hit_positions, const MutableSpan< float3 > r_hit_normals, const MutableSpan< float > r_hit_distances)
static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms)
static void node_register()
static void node_declare(NodeDeclarationBuilder &b)
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)
void geo_node_type_base(blender::bke::bNodeType *ntype, int type, const char *name, short nclass)
void node_free_standard_storage(bNode *node)
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
const EnumPropertyItem rna_enum_attribute_type_items[]
BVHTree_RayCastCallback raycast_callback
void ensure_owns_direct_data()
const Mesh * get_mesh() const
void(* initfunc)(bNodeTree *ntree, bNode *node)
NodeGeometryExecFunction geometry_node_execute
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
NodeDeclareFunction declare