diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_blender_version.h | 2 | ||||
-rw-r--r-- | source/blender/blenloader/intern/versioning_300.c | 13 | ||||
-rw-r--r-- | source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc | 154 |
3 files changed, 50 insertions, 119 deletions
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 899d21683e4..32b607ecf9b 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -39,7 +39,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 36 +#define BLENDER_FILE_SUBVERSION 37 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c index 51a3e32f2bb..bdee5194c9a 100644 --- a/source/blender/blenloader/intern/versioning_300.c +++ b/source/blender/blenloader/intern/versioning_300.c @@ -754,6 +754,19 @@ void do_versions_after_linking_300(Main *bmain, ReportList *UNUSED(reports)) } } + if (!MAIN_VERSION_ATLEAST(bmain, 300, 37)) { + LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) { + if (ntree->type == NTREE_GEOMETRY) { + LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) { + if (node->type == GEO_NODE_BOUNDING_BOX) { + bNodeSocket *geometry_socket = node->inputs.first; + add_realize_instances_before_socket(ntree, node, geometry_socket); + } + } + } + } + } + /** * Versioning code until next subversion bump goes here. * diff --git a/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc b/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc index 8b90595a641..e34b65e6c94 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc @@ -14,9 +14,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "BKE_spline.hh" -#include "BKE_volume.h" - #include "node_geometry_util.hh" namespace blender::nodes { @@ -29,135 +26,56 @@ static void geo_node_bounding_box_declare(NodeDeclarationBuilder &b) b.add_output<decl::Vector>("Max"); } -using bke::GeometryInstanceGroup; - -static void compute_min_max_from_position_and_transform(const GeometryComponent &component, - Span<float4x4> transforms, - float3 &r_min, - float3 &r_max) -{ - GVArray_Typed<float3> positions = component.attribute_get_for_read<float3>( - "position", ATTR_DOMAIN_POINT, {0, 0, 0}); - - for (const float4x4 &transform : transforms) { - for (const int i : positions.index_range()) { - const float3 position = positions[i]; - const float3 transformed_position = transform * position; - minmax_v3v3_v3(r_min, r_max, transformed_position); - } - } -} - -static void compute_min_max_from_volume_and_transforms(const VolumeComponent &volume_component, - Span<float4x4> transforms, - float3 &r_min, - float3 &r_max) -{ -#ifdef WITH_OPENVDB - const Volume *volume = volume_component.get_for_read(); - if (volume == nullptr) { - return; - } - for (const int i : IndexRange(BKE_volume_num_grids(volume))) { - const VolumeGrid *volume_grid = BKE_volume_grid_get_for_read(volume, i); - openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid); - - for (const float4x4 &transform : transforms) { - openvdb::GridBase::ConstPtr instance_grid = BKE_volume_grid_shallow_transform(grid, - transform); - float3 grid_min = float3(FLT_MAX); - float3 grid_max = float3(-FLT_MAX); - if (BKE_volume_grid_bounds(instance_grid, grid_min, grid_max)) { - DO_MIN(grid_min, r_min); - DO_MAX(grid_max, r_max); - } - } - } -#else - UNUSED_VARS(volume_component, transforms, r_min, r_max); -#endif -} - -static void compute_min_max_from_curve_and_transforms(const CurveComponent &curve_component, - Span<float4x4> transforms, - float3 &r_min, - float3 &r_max) -{ - const CurveEval *curve = curve_component.get_for_read(); - if (curve == nullptr) { - return; - } - for (const SplinePtr &spline : curve->splines()) { - Span<float3> positions = spline->evaluated_positions(); - - for (const float4x4 &transform : transforms) { - for (const int i : positions.index_range()) { - const float3 position = positions[i]; - 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); - } - if (set.has<VolumeComponent>()) { - compute_min_max_from_volume_and_transforms( - *set.get_component_for_read<VolumeComponent>(), transforms, r_min, r_max); - } - if (set.has<CurveComponent>()) { - compute_min_max_from_curve_and_transforms( - *set.get_component_for_read<CurveComponent>(), transforms, r_min, r_max); - } - } -} - static void geo_node_bounding_box_exec(GeoNodeExecParams params) { GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); + /* Compute the min and max of all realized geometry for the two + * vector outputs, which are only meant to consider real 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); - } - + geometry_set.compute_boundbox_without_instances(&min, &max); if (min == float3(FLT_MAX)) { - params.set_output("Bounding Box", 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_cuboid_mesh(scale, 2, 2, 2); - transform_mesh(*mesh, center, float3(0), float3(1)); - params.set_output("Bounding Box", GeometrySet::create_with_mesh(mesh)); params.set_output("Min", min); params.set_output("Max", max); } + + /* Generate the bounding box meshes inside each unique geometry set (including individually for + * every instance). Because geometry components are reference counted anyway, we can just + * repurpose the original geometry sets for the output. */ + if (params.output_is_required("Bounding Box")) { + geometry_set.modify_geometry_sets([&](GeometrySet &sub_geometry) { + float3 sub_min = float3(FLT_MAX); + float3 sub_max = float3(-FLT_MAX); + + /* Reuse the min and max calculation if this is the main "real" geometry set. */ + if (&sub_geometry == &geometry_set) { + sub_min = min; + sub_max = max; + } + else { + sub_geometry.compute_boundbox_without_instances(&sub_min, &sub_max); + } + + if (sub_min == float3(FLT_MAX)) { + sub_geometry.keep_only({GEO_COMPONENT_TYPE_INSTANCES}); + } + else { + const float3 scale = sub_max - sub_min; + const float3 center = sub_min + scale / 2.0f; + Mesh *mesh = create_cuboid_mesh(scale, 2, 2, 2); + transform_mesh(*mesh, center, float3(0), float3(1)); + sub_geometry.replace_mesh(mesh); + sub_geometry.keep_only({GEO_COMPONENT_TYPE_MESH, GEO_COMPONENT_TYPE_INSTANCES}); + } + }); + + params.set_output("Bounding Box", std::move(geometry_set)); + } } } // namespace blender::nodes |