Changeset View
Changeset View
Standalone View
Standalone View
source/blender/nodes/geometry/nodes/node_geo_raycast.cc
| Show All 19 Lines | |||||
| NODE_STORAGE_FUNCS(NodeGeometryRaycast) | NODE_STORAGE_FUNCS(NodeGeometryRaycast) | ||||
| static void node_declare(NodeDeclarationBuilder &b) | static void node_declare(NodeDeclarationBuilder &b) | ||||
| { | { | ||||
| b.add_input<decl::Geometry>(N_("Target Geometry")) | b.add_input<decl::Geometry>(N_("Target Geometry")) | ||||
| .only_realized_data() | .only_realized_data() | ||||
| .supported_type(GEO_COMPONENT_TYPE_MESH); | .supported_type(GEO_COMPONENT_TYPE_MESH); | ||||
| b.add_input<decl::Vector>(N_("Attribute")).hide_value().supports_field(); | b.add_input<decl::Vector>(N_("Attribute"), "Vector").hide_value().supports_field(); | ||||
| b.add_input<decl::Float>(N_("Attribute"), "Attribute_001").hide_value().supports_field(); | b.add_input<decl::Float>(N_("Attribute"), "Float").hide_value().supports_field(); | ||||
| b.add_input<decl::Color>(N_("Attribute"), "Attribute_002").hide_value().supports_field(); | b.add_input<decl::Color>(N_("Attribute"), "Color").hide_value().supports_field(); | ||||
| b.add_input<decl::Bool>(N_("Attribute"), "Attribute_003").hide_value().supports_field(); | b.add_input<decl::Bool>(N_("Attribute"), "Bool").hide_value().supports_field(); | ||||
| b.add_input<decl::Int>(N_("Attribute"), "Attribute_004").hide_value().supports_field(); | b.add_input<decl::Int>(N_("Attribute"), "Int").hide_value().supports_field(); | ||||
| b.add_input<decl::Vector>(N_("Source Position")).implicit_field(); | b.add_input<decl::Vector>(N_("Source Position")).implicit_field(); | ||||
| b.add_input<decl::Vector>(N_("Ray Direction")) | b.add_input<decl::Vector>(N_("Ray Direction")) | ||||
| .default_value({0.0f, 0.0f, -1.0f}) | .default_value({0.0f, 0.0f, -1.0f}) | ||||
| .supports_field(); | .supports_field(); | ||||
| b.add_input<decl::Float>(N_("Ray Length")) | b.add_input<decl::Float>(N_("Ray Length")) | ||||
| .default_value(100.0f) | .default_value(100.0f) | ||||
| .min(0.0f) | .min(0.0f) | ||||
| .subtype(PROP_DISTANCE) | .subtype(PROP_DISTANCE) | ||||
| .supports_field(); | .supports_field(); | ||||
| b.add_output<decl::Bool>(N_("Is Hit")).dependent_field(); | b.add_output<decl::Bool>(N_("Is Hit")).dependent_field(); | ||||
| b.add_output<decl::Vector>(N_("Hit Position")).dependent_field(); | b.add_output<decl::Vector>(N_("Hit Position")).dependent_field(); | ||||
| b.add_output<decl::Vector>(N_("Hit Normal")).dependent_field(); | b.add_output<decl::Vector>(N_("Hit Normal")).dependent_field(); | ||||
| b.add_output<decl::Float>(N_("Hit Distance")).dependent_field(); | b.add_output<decl::Float>(N_("Hit Distance")).dependent_field(); | ||||
| b.add_output<decl::Vector>(N_("Attribute")).dependent_field({1, 2, 3, 4, 5, 6}); | b.add_output<decl::Vector>(N_("Attribute"), "Vector").dependent_field({1, 2, 3, 4, 5, 6}); | ||||
| b.add_output<decl::Float>(N_("Attribute"), "Attribute_001").dependent_field({1, 2, 3, 4, 5, 6}); | b.add_output<decl::Float>(N_("Attribute"), "Float").dependent_field({1, 2, 3, 4, 5, 6}); | ||||
| b.add_output<decl::Color>(N_("Attribute"), "Attribute_002").dependent_field({1, 2, 3, 4, 5, 6}); | b.add_output<decl::Color>(N_("Attribute"), "Color").dependent_field({1, 2, 3, 4, 5, 6}); | ||||
| b.add_output<decl::Bool>(N_("Attribute"), "Attribute_003").dependent_field({1, 2, 3, 4, 5, 6}); | b.add_output<decl::Bool>(N_("Attribute"), "Bool").dependent_field({1, 2, 3, 4, 5, 6}); | ||||
| b.add_output<decl::Int>(N_("Attribute"), "Attribute_004").dependent_field({1, 2, 3, 4, 5, 6}); | b.add_output<decl::Int>(N_("Attribute"), "Int").dependent_field({1, 2, 3, 4, 5, 6}); | ||||
| } | } | ||||
| static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) | static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) | ||||
| { | { | ||||
| uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE); | uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE); | ||||
| uiItemR(layout, ptr, "mapping", 0, "", ICON_NONE); | uiItemR(layout, ptr, "mapping", 0, "", ICON_NONE); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 253 Lines • ▼ Show 20 Lines | void evaluate_target_field(GField src_field) | ||||
| const int domain_num = mesh_component.attribute_domain_num(domain_); | const int domain_num = mesh_component.attribute_domain_num(domain_); | ||||
| target_evaluator_ = std::make_unique<FieldEvaluator>(*target_context_, domain_num); | target_evaluator_ = std::make_unique<FieldEvaluator>(*target_context_, domain_num); | ||||
| target_evaluator_->add(std::move(src_field)); | target_evaluator_->add(std::move(src_field)); | ||||
| target_evaluator_->evaluate(); | target_evaluator_->evaluate(); | ||||
| target_data_ = &target_evaluator_->get_evaluated(0); | target_data_ = &target_evaluator_->get_evaluated(0); | ||||
| } | } | ||||
| }; | }; | ||||
| static GField get_input_attribute_field(GeoNodeExecParams ¶ms, const eCustomDataType data_type) | |||||
| { | |||||
| switch (data_type) { | |||||
| case CD_PROP_FLOAT: | |||||
| if (params.output_is_required("Attribute_001")) { | |||||
| return params.extract_input<Field<float>>("Attribute_001"); | |||||
| } | |||||
| break; | |||||
| case CD_PROP_FLOAT3: | |||||
| if (params.output_is_required("Attribute")) { | |||||
| return params.extract_input<Field<float3>>("Attribute"); | |||||
| } | |||||
| break; | |||||
| case CD_PROP_COLOR: | |||||
| if (params.output_is_required("Attribute_002")) { | |||||
| return params.extract_input<Field<ColorGeometry4f>>("Attribute_002"); | |||||
| } | |||||
| break; | |||||
| case CD_PROP_BOOL: | |||||
| if (params.output_is_required("Attribute_003")) { | |||||
| return params.extract_input<Field<bool>>("Attribute_003"); | |||||
| } | |||||
| break; | |||||
| case CD_PROP_INT32: | |||||
| if (params.output_is_required("Attribute_004")) { | |||||
| return params.extract_input<Field<int>>("Attribute_004"); | |||||
| } | |||||
| break; | |||||
| default: | |||||
| BLI_assert_unreachable(); | |||||
| } | |||||
| return {}; | |||||
| } | |||||
| static void output_attribute_field(GeoNodeExecParams ¶ms, GField field) | |||||
| { | |||||
| switch (bke::cpp_type_to_custom_data_type(field.cpp_type())) { | |||||
| case CD_PROP_FLOAT: { | |||||
| params.set_output("Attribute_001", Field<float>(field)); | |||||
| break; | |||||
| } | |||||
| case CD_PROP_FLOAT3: { | |||||
| params.set_output("Attribute", Field<float3>(field)); | |||||
| break; | |||||
| } | |||||
| case CD_PROP_COLOR: { | |||||
| params.set_output("Attribute_002", Field<ColorGeometry4f>(field)); | |||||
| break; | |||||
| } | |||||
| case CD_PROP_BOOL: { | |||||
| params.set_output("Attribute_003", Field<bool>(field)); | |||||
| break; | |||||
| } | |||||
| case CD_PROP_INT32: { | |||||
| params.set_output("Attribute_004", Field<int>(field)); | |||||
| break; | |||||
| } | |||||
| default: | |||||
| break; | |||||
| } | |||||
| } | |||||
| static void node_geo_exec(GeoNodeExecParams params) | static void node_geo_exec(GeoNodeExecParams params) | ||||
| { | { | ||||
| GeometrySet target = params.extract_input<GeometrySet>("Target Geometry"); | GeometrySet target = params.extract_input<GeometrySet>("Target Geometry"); | ||||
| const NodeGeometryRaycast &storage = node_storage(params.node()); | const NodeGeometryRaycast &storage = node_storage(params.node()); | ||||
| const GeometryNodeRaycastMapMode mapping = (GeometryNodeRaycastMapMode)storage.mapping; | const GeometryNodeRaycastMapMode mapping = (GeometryNodeRaycastMapMode)storage.mapping; | ||||
| const eCustomDataType data_type = static_cast<eCustomDataType>(storage.data_type); | const eCustomDataType data_type = static_cast<eCustomDataType>(storage.data_type); | ||||
| if (target.is_empty()) { | if (target.is_empty()) { | ||||
| params.set_default_remaining_outputs(); | params.set_default_remaining_outputs(); | ||||
| return; | return; | ||||
| } | } | ||||
| if (!target.has_mesh()) { | if (!target.has_mesh()) { | ||||
| params.set_default_remaining_outputs(); | params.set_default_remaining_outputs(); | ||||
| return; | return; | ||||
| } | } | ||||
| if (target.get_mesh_for_read()->totpoly == 0) { | if (target.get_mesh_for_read()->totpoly == 0) { | ||||
| params.error_message_add(NodeWarningType::Error, TIP_("The target mesh must have faces")); | params.error_message_add(NodeWarningType::Error, TIP_("The target mesh must have faces")); | ||||
| params.set_default_remaining_outputs(); | params.set_default_remaining_outputs(); | ||||
| return; | return; | ||||
| } | } | ||||
| GField field = get_input_attribute_field(params, data_type); | GField field; | ||||
| attribute_math::convert_to_static_type(data_type, [&](auto dummy) { | |||||
| using T = decltype(dummy); | |||||
| field = params.extract_input<Field<T>>(attribute_math::default_name<T>()); | |||||
| }); | |||||
| const bool do_attribute_transfer = bool(field); | const bool do_attribute_transfer = bool(field); | ||||
| Field<float3> position_field = params.extract_input<Field<float3>>("Source Position"); | Field<float3> position_field = params.extract_input<Field<float3>>("Source Position"); | ||||
| Field<float3> direction_field = params.extract_input<Field<float3>>("Ray Direction"); | Field<float3> direction_field = params.extract_input<Field<float3>>("Ray Direction"); | ||||
| Field<float> length_field = params.extract_input<Field<float>>("Ray Length"); | Field<float> length_field = params.extract_input<Field<float>>("Ray Length"); | ||||
| auto fn = std::make_unique<RaycastFunction>(std::move(target), std::move(field), mapping); | auto fn = std::make_unique<RaycastFunction>(std::move(target), std::move(field), mapping); | ||||
| auto op = std::make_shared<FieldOperation>(FieldOperation( | auto op = std::make_shared<FieldOperation>(FieldOperation( | ||||
| std::move(fn), | std::move(fn), | ||||
| {std::move(position_field), std::move(direction_field), std::move(length_field)})); | {std::move(position_field), std::move(direction_field), std::move(length_field)})); | ||||
| params.set_output("Is Hit", Field<bool>(op, 0)); | params.set_output("Is Hit", Field<bool>(op, 0)); | ||||
| params.set_output("Hit Position", Field<float3>(op, 1)); | params.set_output("Hit Position", Field<float3>(op, 1)); | ||||
| params.set_output("Hit Normal", Field<float3>(op, 2)); | params.set_output("Hit Normal", Field<float3>(op, 2)); | ||||
| params.set_output("Hit Distance", Field<float>(op, 3)); | params.set_output("Hit Distance", Field<float>(op, 3)); | ||||
| if (do_attribute_transfer) { | if (do_attribute_transfer) { | ||||
| output_attribute_field(params, GField(op, 4)); | attribute_math::convert_to_static_type(data_type, [&](auto dummy) { | ||||
| using T = decltype(dummy); | |||||
| params.set_output(attribute_math::default_name<T>(), Field<T>(GField(op, 4))); | |||||
| }); | |||||
| } | } | ||||
| } | } | ||||
| } // namespace blender::nodes::node_geo_raycast_cc | } // namespace blender::nodes::node_geo_raycast_cc | ||||
| void register_node_type_geo_raycast() | void register_node_type_geo_raycast() | ||||
| { | { | ||||
| namespace file_ns = blender::nodes::node_geo_raycast_cc; | namespace file_ns = blender::nodes::node_geo_raycast_cc; | ||||
| Show All 15 Lines | |||||