Blender V5.0
node_geo_input_instance_bounds.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2025 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
6#include "BKE_instances.hh"
7
9
11
13{
14 b.add_input<decl::Bool>("Use Radius")
15 .default_value(true)
17 "For curves, point clouds, and Grease Pencil, take the radius attribute into account "
18 "when computing the bounds.");
19 b.add_output<decl::Vector>("Min").field_source();
20 b.add_output<decl::Vector>("Max").field_source();
21}
22
24 private:
25 bool use_radius_;
26 bool return_max_;
27
28 public:
29 InstanceBoundsField(bool use_radius, bool return_max)
30 : bke::InstancesFieldInput(CPPType::get<float3>(), return_max ? "Max" : "Min"),
31 use_radius_(use_radius),
32 return_max_(return_max)
33 {
34 }
35
37 const IndexMask &mask) const final
38 {
39 const Span<int> handles = instances.reference_handles();
40 const Span<bke::InstanceReference> references = instances.references();
41
42 IndexMaskMemory memory;
43 IndexMask reference_mask(references.size());
44 Array<bool> reference_in_mask(references.size(), false);
45
46 mask.foreach_index(GrainSize(2048), [&](const int i) {
47 const int handle = handles[i];
48 if (handle < reference_in_mask.size()) {
49 reference_in_mask[handle] = true;
50 }
51 });
52
53 reference_mask = IndexMask::from_bools(reference_in_mask.as_span(), memory);
54 Array<float3> reference_bounds(references.size());
55
56 reference_mask.foreach_index(GrainSize(128), [&](const int reference_index) {
57 const blender::bke::InstanceReference &reference = references[reference_index];
58
59 GeometrySet instance_geometry;
60 switch (reference.type()) {
62 instance_geometry = reference.geometry_set();
63 break;
65 instance_geometry = blender::bke::object_get_evaluated_geometry_set(reference.object());
66 break;
68 break;
70 break;
71 }
72
73 std::optional<Bounds<float3>> sub_bounds =
74 instance_geometry.compute_boundbox_without_instances(use_radius_);
75
76 if (sub_bounds) {
77 reference_bounds[reference_index] = return_max_ ? sub_bounds->max : sub_bounds->min;
78 }
79 else {
80 reference_bounds[reference_index] = float3(0.0f);
81 }
82 });
83
84 Array<float3> output_bounds(mask.min_array_size());
85 mask.foreach_index(GrainSize(4096), [&](const int instance_index) {
86 output_bounds[instance_index] = reference_bounds[handles[instance_index]];
87 });
88
89 return VArray<float3>::from_container(std::move(output_bounds));
90 }
91
92 uint64_t hash() const override
93 {
94 return get_default_hash(use_radius_, return_max_);
95 }
96
97 bool is_equal_to(const fn::FieldNode &other) const override
98 {
99 if (const auto *other_field = dynamic_cast<const InstanceBoundsField *>(&other)) {
100 return use_radius_ == other_field->use_radius_ && return_max_ == other_field->return_max_;
101 }
102 return false;
103 }
104};
105
107{
108 const bool use_radius = params.extract_input<bool>("Use Radius");
109 params.set_output("Min",
110 Field<float3>(std::make_shared<InstanceBoundsField>(use_radius, false)));
111 params.set_output("Max", Field<float3>(std::make_shared<InstanceBoundsField>(use_radius, true)));
112}
113
114static void node_register()
115{
116 static blender::bke::bNodeType ntype;
117
118 geo_node_type_base(&ntype, "GeometryNodeInputInstanceBounds");
119 ntype.ui_name = "Instance Bounds";
120 ntype.ui_description = "Calculate position bounds of each instance's geometry set";
121 ntype.nclass = NODE_CLASS_INPUT;
123 ntype.declare = node_declare;
125}
127
128} // namespace blender::nodes::node_geo_input_instance_bounds_cc
#define NODE_CLASS_INPUT
Definition BKE_node.hh:447
#define final(a, b, c)
Definition BLI_hash.h:19
#define NOD_REGISTER_NODE(REGISTER_FUNC)
unsigned long long int uint64_t
int64_t size() const
Definition BLI_array.hh:256
Span< T > as_span() const
Definition BLI_array.hh:243
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
constexpr int64_t size() const
Definition BLI_span.hh:252
static VArray from_container(ContainerT container)
void foreach_index(Fn &&fn) const
GVArray get_varray_for_context(const bke::Instances &instances, const IndexMask &mask) const final
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
void node_register_type(bNodeType &ntype)
Definition node.cc:2416
GeometrySet object_get_evaluated_geometry_set(const Object &object, bool apply_subdiv=true)
uint64_t get_default_hash(const T &v, const Args &...args)
Definition BLI_hash.hh:233
VecBase< float, 3 > float3
void geo_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
std::optional< Bounds< float3 > > compute_boundbox_without_instances(bool use_radius=true, bool use_subdiv=false) const
Defines a node type.
Definition BKE_node.hh:238
std::string ui_description
Definition BKE_node.hh:244
NodeGeometryExecFunction geometry_node_execute
Definition BKE_node.hh:354
NodeDeclareFunction declare
Definition BKE_node.hh:362
i
Definition text_draw.cc:230
ParamHandle ** handles