Blender  V2.93
node_geo_bounding_box.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 #include "BKE_volume.h"
18 
19 #include "node_geometry_util.hh"
20 
22  {SOCK_GEOMETRY, N_("Geometry")},
23  {-1, ""},
24 };
25 
27  {SOCK_GEOMETRY, N_("Mesh")},
28  {SOCK_VECTOR, N_("Min")},
29  {SOCK_VECTOR, N_("Max")},
30  {-1, ""},
31 };
32 
33 namespace blender::nodes {
34 
35 using bke::GeometryInstanceGroup;
36 
38  Span<float4x4> transforms,
39  float3 &r_min,
40  float3 &r_max)
41 {
42  ReadAttributePtr position_attribute = component.attribute_try_get_for_read("position");
43  if (!position_attribute) {
44  BLI_assert(component.attribute_domain_size(ATTR_DOMAIN_POINT) == 0);
45  return;
46  }
47  Span<float3> positions = position_attribute->get_span<float3>();
48 
49  for (const float4x4 &transform : transforms) {
50  for (const float3 &position : positions) {
51  const float3 transformed_position = transform * position;
52  minmax_v3v3_v3(r_min, r_max, transformed_position);
53  }
54  }
55 }
56 
57 static void compute_min_max_from_volume_and_transforms(const VolumeComponent &volume_component,
58  Span<float4x4> transforms,
59  float3 &r_min,
60  float3 &r_max)
61 {
62 #ifdef WITH_OPENVDB
63  const Volume *volume = volume_component.get_for_read();
64  if (volume == nullptr) {
65  return;
66  }
67  for (const int i : IndexRange(BKE_volume_num_grids(volume))) {
68  const VolumeGrid *volume_grid = BKE_volume_grid_get_for_read(volume, i);
69  openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
70 
71  for (const float4x4 &transform : transforms) {
72  openvdb::GridBase::ConstPtr instance_grid = BKE_volume_grid_shallow_transform(grid,
73  transform);
74  float3 grid_min = float3(FLT_MAX);
75  float3 grid_max = float3(-FLT_MAX);
76  if (BKE_volume_grid_bounds(instance_grid, grid_min, grid_max)) {
77  DO_MIN(grid_min, r_min);
78  DO_MAX(grid_max, r_max);
79  }
80  }
81  }
82 #else
83  UNUSED_VARS(volume_component, transforms, r_min, r_max);
84 #endif
85 }
86 
87 static void compute_geometry_set_instances_boundbox(const GeometrySet &geometry_set,
88  float3 &r_min,
89  float3 &r_max)
90 {
92  bke::geometry_set_gather_instances(geometry_set, set_groups);
93 
94  for (const GeometryInstanceGroup &set_group : set_groups) {
95  const GeometrySet &set = set_group.geometry_set;
96  Span<float4x4> transforms = set_group.transforms;
97 
98  if (set.has<PointCloudComponent>()) {
100  *set.get_component_for_read<PointCloudComponent>(), transforms, r_min, r_max);
101  }
102  if (set.has<MeshComponent>()) {
104  *set.get_component_for_read<MeshComponent>(), transforms, r_min, r_max);
105  }
106  if (set.has<VolumeComponent>()) {
108  *set.get_component_for_read<VolumeComponent>(), transforms, r_min, r_max);
109  }
110  }
111 }
112 
114 {
115  GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
116 
117  float3 min = float3(FLT_MAX);
118  float3 max = float3(-FLT_MAX);
119 
120  if (geometry_set.has_instances()) {
122  }
123  else {
124  geometry_set.compute_boundbox_without_instances(&min, &max);
125  }
126 
127  if (min == float3(FLT_MAX)) {
128  params.set_output("Mesh", GeometrySet());
129  params.set_output("Min", float3(0));
130  params.set_output("Max", float3(0));
131  }
132  else {
133  const float3 scale = max - min;
134  const float3 center = min + scale / 2.0f;
135  Mesh *mesh = create_cube_mesh(1.0f);
136  transform_mesh(mesh, center, float3(0), scale);
137  params.set_output("Mesh", GeometrySet::create_with_mesh(mesh));
138  params.set_output("Min", min);
139  params.set_output("Max", max);
140  }
141 }
142 
143 } // namespace blender::nodes
144 
146 {
147  static bNodeType ntype;
148 
149  geo_node_type_base(&ntype, GEO_NODE_BOUNDING_BOX, "Bounding Box", NODE_CLASS_GEOMETRY, 0);
152  nodeRegisterType(&ntype);
153 }
@ ATTR_DOMAIN_POINT
Definition: BKE_attribute.h:43
void node_type_socket_templates(struct bNodeType *ntype, struct bNodeSocketTemplate *inputs, struct bNodeSocketTemplate *outputs)
Definition: node.cc:4527
#define GEO_NODE_BOUNDING_BOX
Definition: BKE_node.h:1418
#define NODE_CLASS_GEOMETRY
Definition: BKE_node.h:359
void nodeRegisterType(struct bNodeType *ntype)
Definition: node.cc:1298
Volume datablock.
const VolumeGrid * BKE_volume_grid_get_for_read(const struct Volume *volume, int grid_index)
int BKE_volume_num_grids(const struct Volume *volume)
#define BLI_assert(a)
Definition: BLI_assert.h:58
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
Definition: math_vector.c:1020
#define UNUSED_VARS(...)
#define DO_MAX(vec, max)
#define DO_MIN(vec, min)
#define N_(msgid)
static uint8 component(Color32 c, uint i)
Definition: ColorBlock.cpp:126
@ SOCK_VECTOR
@ SOCK_GEOMETRY
NSNotificationCenter * center
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
const Volume * get_for_read() const
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void geometry_set_gather_instances(const GeometrySet &geometry_set, Vector< GeometryInstanceGroup > &r_instance_groups)
std::unique_ptr< ReadAttribute > ReadAttributePtr
void transform_mesh(Mesh *mesh, const float3 translation, const float3 rotation, const float3 scale)
static void compute_geometry_set_instances_boundbox(const GeometrySet &geometry_set, float3 &r_min, float3 &r_max)
static void geo_node_bounding_box_exec(GeoNodeExecParams params)
static void compute_min_max_from_volume_and_transforms(const VolumeComponent &volume_component, Span< float4x4 > transforms, float3 &r_min, float3 &r_max)
Mesh * create_cube_mesh(const float size)
static void compute_min_max_from_position_and_transform(const GeometryComponent &component, Span< float4x4 > transforms, float3 &r_min, float3 &r_max)
static bNodeSocketTemplate geo_node_bounding_box_out[]
static bNodeSocketTemplate geo_node_bounding_box_in[]
void register_node_type_geo_bounding_box()
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag)
#define min(a, b)
Definition: sort.c:51
void compute_boundbox_without_instances(blender::float3 *r_min, blender::float3 *r_max) const
static GeometrySet create_with_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
bool has(const GeometryComponentType component_type) const
const GeometryComponent * get_component_for_read(GeometryComponentType component_type) const
bool has_instances() const
Compact definition of a node socket.
Definition: BKE_node.h:95
Defines a node type.
Definition: BKE_node.h:221
NodeGeometryExecFunction geometry_node_execute
Definition: BKE_node.h:327
float max