Fix T94113: Local view + Geometry Nodes is broken for instances

`GeometrySet::compute_boundbox_without_instances` may not initialize min
max in some cases such as meshes without vertices.

This can result in a Bounding Box with impossible dimensions
(min=FLT_MAX, max=-FLT_MAX).

So repeat the same solution seen in `BKE_object_boundbox_calc_from_mesh`
and set boundbox values to zero.

Reviewed By: HooglyBoogly

Differential Revision: https://developer.blender.org/D13664
This commit is contained in:
Germano Cavalcante 2021-12-29 12:27:24 -03:00 committed by Germano Cavalcante
parent d786b48aab
commit 1c7d7c9150
Notes: blender-bot 2023-02-14 01:52:41 +01:00
Referenced by issue #94113, Local view + Geometry Nodes is broken for instances
7 changed files with 30 additions and 13 deletions

View File

@ -372,7 +372,7 @@ struct GeometrySet {
*/
blender::Vector<const GeometryComponent *> get_components_for_read() const;
void compute_boundbox_without_instances(blender::float3 *r_min, blender::float3 *r_max) const;
bool compute_boundbox_without_instances(blender::float3 *r_min, blender::float3 *r_max) const;
friend std::ostream &operator<<(std::ostream &stream, const GeometrySet &geometry_set);

View File

@ -41,7 +41,7 @@ void *BKE_pointcloud_add_default(struct Main *bmain, const char *name);
struct PointCloud *BKE_pointcloud_new_nomain(const int totpoint);
struct BoundBox *BKE_pointcloud_boundbox_get(struct Object *ob);
void BKE_pointcloud_minmax(const struct PointCloud *pointcloud, float r_min[3], float r_max[3]);
bool BKE_pointcloud_minmax(const struct PointCloud *pointcloud, float r_min[3], float r_max[3]);
void BKE_pointcloud_update_customdata_pointers(struct PointCloud *pointcloud);
bool BKE_pointcloud_customdata_required(struct PointCloud *pointcloud,

View File

@ -686,7 +686,7 @@ struct CurveEval {
void translate(const blender::float3 &translation);
void transform(const blender::float4x4 &matrix);
void bounds_min_max(blender::float3 &min, blender::float3 &max, const bool use_evaluated) const;
bool bounds_min_max(blender::float3 &min, blender::float3 &max, const bool use_evaluated) const;
/**
* Return the start indices for each of the curve spline's control points, if they were part

View File

@ -100,11 +100,17 @@ void CurveEval::transform(const float4x4 &matrix)
}
}
void CurveEval::bounds_min_max(float3 &min, float3 &max, const bool use_evaluated) const
bool CurveEval::bounds_min_max(float3 &min, float3 &max, const bool use_evaluated) const
{
bool have_minmax = false;
for (const SplinePtr &spline : this->splines()) {
spline->bounds_min_max(min, max, use_evaluated);
if (spline->size()) {
spline->bounds_min_max(min, max, use_evaluated);
have_minmax = true;
}
}
return have_minmax;
}
float CurveEval::total_length() const

View File

@ -183,25 +183,27 @@ Vector<const GeometryComponent *> GeometrySet::get_components_for_read() const
return components;
}
void GeometrySet::compute_boundbox_without_instances(float3 *r_min, float3 *r_max) const
bool GeometrySet::compute_boundbox_without_instances(float3 *r_min, float3 *r_max) const
{
bool have_minmax = false;
const PointCloud *pointcloud = this->get_pointcloud_for_read();
if (pointcloud != nullptr) {
BKE_pointcloud_minmax(pointcloud, *r_min, *r_max);
have_minmax |= BKE_pointcloud_minmax(pointcloud, *r_min, *r_max);
}
const Mesh *mesh = this->get_mesh_for_read();
if (mesh != nullptr) {
BKE_mesh_wrapper_minmax(mesh, *r_min, *r_max);
have_minmax |= BKE_mesh_wrapper_minmax(mesh, *r_min, *r_max);
}
const Volume *volume = this->get_volume_for_read();
if (volume != nullptr) {
BKE_volume_min_max(volume, *r_min, *r_max);
have_minmax |= BKE_volume_min_max(volume, *r_min, *r_max);
}
const CurveEval *curve = this->get_curve_for_read();
if (curve != nullptr) {
/* Using the evaluated positions is somewhat arbitrary, but it is probably expected. */
curve->bounds_min_max(*r_min, *r_max, true);
have_minmax |= curve->bounds_min_max(*r_min, *r_max, true);
}
return have_minmax;
}
std::ostream &operator<<(std::ostream &stream, const GeometrySet &geometry_set)

View File

@ -3918,11 +3918,15 @@ bool BKE_object_boundbox_calc_from_evaluated_geometry(Object *ob)
INIT_MINMAX(min, max);
if (ob->runtime.geometry_set_eval) {
ob->runtime.geometry_set_eval->compute_boundbox_without_instances(&min, &max);
if (!ob->runtime.geometry_set_eval->compute_boundbox_without_instances(&min, &max)) {
zero_v3(min);
zero_v3(max);
}
}
else if (const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob)) {
if (!BKE_mesh_wrapper_minmax(mesh_eval, min, max)) {
return false;
zero_v3(min);
zero_v3(max);
}
}
else if (ob->runtime.curve_cache) {

View File

@ -261,8 +261,12 @@ PointCloud *BKE_pointcloud_new_nomain(const int totpoint)
return pointcloud;
}
void BKE_pointcloud_minmax(const struct PointCloud *pointcloud, float r_min[3], float r_max[3])
bool BKE_pointcloud_minmax(const struct PointCloud *pointcloud, float r_min[3], float r_max[3])
{
if (!pointcloud->totpoint) {
return false;
}
float(*pointcloud_co)[3] = pointcloud->co;
float *pointcloud_radius = pointcloud->radius;
for (int a = 0; a < pointcloud->totpoint; a++) {
@ -273,6 +277,7 @@ void BKE_pointcloud_minmax(const struct PointCloud *pointcloud, float r_min[3],
DO_MIN(co_min, r_min);
DO_MAX(co_max, r_max);
}
return true;
}
BoundBox *BKE_pointcloud_boundbox_get(Object *ob)