Geometry Nodes: Bounding Box Node
This commit adds a simple node to output the min and max of an axis-aligned bounding box for the input geometry, as well a rectangular prism mesh created from these values for convenience. The initial use case for this node is a "bounding box boolean", where doing the boolean with just a bounding box could be signigicantly faster, for cases like cutting a hole in a wall for a window. But it's easy to imagine other cases where it could be useful. This node supports mesh and point cloud data right now, volume support will come as a separate patch. Also note that there is plenty of room to improve the performance of this node through parallelization. Differential Revision: https://developer.blender.org/D10420
This commit is contained in:
parent
93114180d7
commit
e0a1a2f49d
Notes:
blender-bot
2023-02-14 06:46:23 +01:00
Referenced by issue #87301, Cycles+OSL: Mysterious black lines in render Referenced by issue #87292, "File Output" node does not saves anything Referenced by issue #87279, External OSL scripts are not compiled anymore
|
@ -505,6 +505,7 @@ geometry_node_categories = [
|
|||
NodeItem("ShaderNodeCombineRGB"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_GEOMETRY", "Geometry", items=[
|
||||
NodeItem("GeometryNodeBoundBox"),
|
||||
NodeItem("GeometryNodeTransform"),
|
||||
NodeItem("GeometryNodeJoinGeometry"),
|
||||
]),
|
||||
|
|
|
@ -1398,6 +1398,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
|
|||
#define GEO_NODE_MESH_PRIMITIVE_GRID 1039
|
||||
#define GEO_NODE_ATTRIBUTE_MAP_RANGE 1040
|
||||
#define GEO_NODE_ATTRIBUTE_CLAMP 1041
|
||||
#define GEO_NODE_BOUNDING_BOX 1042
|
||||
|
||||
/** \} */
|
||||
|
||||
|
|
|
@ -4937,6 +4937,7 @@ static void registerGeometryNodes()
|
|||
register_node_type_geo_attribute_vector_math();
|
||||
register_node_type_geo_attribute_remove();
|
||||
register_node_type_geo_boolean();
|
||||
register_node_type_geo_bounding_box();
|
||||
register_node_type_geo_collection_info();
|
||||
register_node_type_geo_edge_split();
|
||||
register_node_type_geo_is_viewport();
|
||||
|
|
|
@ -156,6 +156,7 @@ set(SRC
|
|||
geometry/nodes/node_geo_attribute_separate_xyz.cc
|
||||
geometry/nodes/node_geo_attribute_vector_math.cc
|
||||
geometry/nodes/node_geo_boolean.cc
|
||||
geometry/nodes/node_geo_bounding_box.cc
|
||||
geometry/nodes/node_geo_collection_info.cc
|
||||
geometry/nodes/node_geo_common.cc
|
||||
geometry/nodes/node_geo_edge_split.cc
|
||||
|
|
|
@ -42,6 +42,7 @@ void register_node_type_geo_attribute_separate_xyz(void);
|
|||
void register_node_type_geo_attribute_vector_math(void);
|
||||
void register_node_type_geo_attribute_remove(void);
|
||||
void register_node_type_geo_boolean(void);
|
||||
void register_node_type_geo_bounding_box(void);
|
||||
void register_node_type_geo_collection_info(void);
|
||||
void register_node_type_geo_edge_split(void);
|
||||
void register_node_type_geo_is_viewport(void);
|
||||
|
|
|
@ -309,6 +309,7 @@ DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_LINE, def_geo_mesh_line, "MESH_PRI
|
|||
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_GRID, 0, "MESH_PRIMITIVE_GRID", MeshGrid, "Grid", "")
|
||||
DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_MAP_RANGE, def_geo_attribute_map_range, "ATTRIBUTE_MAP_RANGE", AttributeMapRange, "Attribute Map Range", "")
|
||||
DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_CLAMP, def_geo_attribute_clamp, "ATTRIBUTE_CLAMP", AttributeClamp, "Attribute Clamp", "")
|
||||
DefNode(GeometryNode, GEO_NODE_BOUNDING_BOX, 0, "BOUNDING_BOX", BoundBox, "Bounding Box", "")
|
||||
|
||||
/* undefine macros */
|
||||
#undef DefNode
|
||||
|
|
|
@ -58,4 +58,6 @@ Mesh *create_cylinder_or_cone_mesh(const float radius_top,
|
|||
const int verts_num,
|
||||
const GeometryNodeMeshCircleFillType fill_type);
|
||||
|
||||
Mesh *create_cube_mesh(const float size);
|
||||
|
||||
} // namespace blender::nodes
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "BLI_task.hh"
|
||||
|
||||
#include "BLI_math_matrix.h"
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
static bNodeSocketTemplate geo_node_bounding_box_in[] = {
|
||||
{SOCK_GEOMETRY, N_("Geometry")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static bNodeSocketTemplate geo_node_bounding_box_out[] = {
|
||||
{SOCK_GEOMETRY, N_("Mesh")},
|
||||
{SOCK_VECTOR, N_("Min")},
|
||||
{SOCK_VECTOR, N_("Max")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
using bke::GeometryInstanceGroup;
|
||||
|
||||
static void compute_min_max_from_position_and_transform(const GeometryComponent &component,
|
||||
Span<float4x4> transforms,
|
||||
float3 &r_min,
|
||||
float3 &r_max)
|
||||
{
|
||||
ReadAttributePtr position_attribute = component.attribute_try_get_for_read("position");
|
||||
if (!position_attribute) {
|
||||
BLI_assert(component.attribute_domain_size(ATTR_DOMAIN_POINT) == 0);
|
||||
return;
|
||||
}
|
||||
Span<float3> positions = position_attribute->get_span<float3>();
|
||||
|
||||
for (const float4x4 &transform : transforms) {
|
||||
for (const float3 &position : positions) {
|
||||
const float3 transformed_position = transform * position;
|
||||
minmax_v3v3_v3(r_min, r_max, transformed_position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void compute_geometry_set_instances_boundbox(const GeometrySet &geometry_set,
|
||||
float3 &r_min,
|
||||
float3 &r_max)
|
||||
{
|
||||
Vector<GeometryInstanceGroup> set_groups;
|
||||
bke::geometry_set_gather_instances(geometry_set, set_groups);
|
||||
|
||||
for (const GeometryInstanceGroup &set_group : set_groups) {
|
||||
const GeometrySet &set = set_group.geometry_set;
|
||||
Span<float4x4> transforms = set_group.transforms;
|
||||
|
||||
if (set.has<PointCloudComponent>()) {
|
||||
compute_min_max_from_position_and_transform(
|
||||
*set.get_component_for_read<PointCloudComponent>(), transforms, r_min, r_max);
|
||||
}
|
||||
if (set.has<MeshComponent>()) {
|
||||
compute_min_max_from_position_and_transform(
|
||||
*set.get_component_for_read<MeshComponent>(), transforms, r_min, r_max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void geo_node_bounding_box_exec(GeoNodeExecParams params)
|
||||
{
|
||||
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
|
||||
|
||||
float3 min = float3(FLT_MAX);
|
||||
float3 max = float3(-FLT_MAX);
|
||||
|
||||
if (geometry_set.has_instances()) {
|
||||
compute_geometry_set_instances_boundbox(geometry_set, min, max);
|
||||
}
|
||||
else {
|
||||
geometry_set.compute_boundbox_without_instances(&min, &max);
|
||||
}
|
||||
|
||||
if (min == float3(FLT_MAX)) {
|
||||
params.set_output("Mesh", GeometrySet());
|
||||
params.set_output("Min", float3(0));
|
||||
params.set_output("Max", float3(0));
|
||||
}
|
||||
else {
|
||||
const float3 scale = max - min;
|
||||
const float3 center = min + scale / 2.0f;
|
||||
Mesh *mesh = create_cube_mesh(1.0f);
|
||||
transform_mesh(mesh, center, float3(0), scale);
|
||||
params.set_output("Mesh", GeometrySet::create_with_mesh(mesh));
|
||||
params.set_output("Min", min);
|
||||
params.set_output("Max", max);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::nodes
|
||||
|
||||
void register_node_type_geo_bounding_box()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
|
||||
geo_node_type_base(&ntype, GEO_NODE_BOUNDING_BOX, "Bounding Box", NODE_CLASS_GEOMETRY, 0);
|
||||
node_type_socket_templates(&ntype, geo_node_bounding_box_in, geo_node_bounding_box_out);
|
||||
ntype.geometry_node_execute = blender::nodes::geo_node_bounding_box_exec;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
|
@ -35,7 +35,7 @@ static bNodeSocketTemplate geo_node_mesh_primitive_cube_out[] = {
|
|||
|
||||
namespace blender::nodes {
|
||||
|
||||
static Mesh *create_cube_mesh(const float size)
|
||||
Mesh *create_cube_mesh(const float size)
|
||||
{
|
||||
const float4x4 transform = float4x4::identity();
|
||||
|
||||
|
|
Loading…
Reference in New Issue