Fix T94078: Wrong Bound Box calculated for curves

`DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN` creates temporary objects that
correspond to duplicates or instances.

These temporary objects can share same pointers with the original object
as in the case of Bounding Box.

Bound Box of temporary objects is marked dirty in
`BKE_object_replace_data_on_shallow_copy` since `ob->data` is different.

This causes the original Bounding Box, calculated for the evaluated
geometry, to be lost.

The solution in this commit is to change the boundbox reference of the
temporary objects, so the boundbox of the non-temporary object (with
the data curve) is not marked dirty.

Differential Revision: https://developer.blender.org/D13581
This commit is contained in:
Germano Cavalcante 2022-01-04 11:29:15 -03:00 committed by Germano Cavalcante
parent 5085c622ea
commit 5560f32447
Notes: blender-bot 2023-02-13 16:47:57 +01:00
Referenced by issue #94733, Geometry nodes. Low performance case with instancing
Referenced by issue #94078, Wrong Bound Box calculated for curves
2 changed files with 37 additions and 9 deletions

View File

@ -76,14 +76,8 @@ void deg_invalidate_iterator_work_data(DEGObjectIterData *data)
#endif
}
void verify_id_properties_freed(DEGObjectIterData *data)
void ensure_id_properties_freed(const Object *dupli_object, Object *temp_dupli_object)
{
if (data->dupli_object_current == nullptr) {
/* We didn't enter duplication yet, so we can't have any dangling pointers. */
return;
}
const Object *dupli_object = data->dupli_object_current->ob;
Object *temp_dupli_object = &data->temp_dupli_object;
if (temp_dupli_object->id.properties == nullptr) {
/* No ID properties in temp data-block -- no leak is possible. */
return;
@ -97,6 +91,35 @@ void verify_id_properties_freed(DEGObjectIterData *data)
temp_dupli_object->id.properties = nullptr;
}
void ensure_boundbox_freed(const Object *dupli_object, Object *temp_dupli_object)
{
if (temp_dupli_object->runtime.bb == nullptr) {
/* No Bounding Box in temp data-block -- no leak is possible. */
return;
}
if (temp_dupli_object->runtime.bb == dupli_object->runtime.bb) {
/* Temp copy of object did not modify Bounding Box. */
return;
}
/* Free memory which is owned by temporary storage which is about to get overwritten. */
MEM_freeN(temp_dupli_object->runtime.bb);
temp_dupli_object->runtime.bb = nullptr;
}
void free_owned_memory(DEGObjectIterData *data)
{
if (data->dupli_object_current == nullptr) {
/* We didn't enter duplication yet, so we can't have any dangling pointers. */
return;
}
const Object *dupli_object = data->dupli_object_current->ob;
Object *temp_dupli_object = &data->temp_dupli_object;
ensure_id_properties_freed(dupli_object, temp_dupli_object);
ensure_boundbox_freed(dupli_object, temp_dupli_object);
}
bool deg_object_hide_original(eEvaluationMode eval_mode, Object *ob, DupliObject *dob)
{
/* Automatic hiding if this object is being instanced on verts/faces/frames
@ -153,7 +176,7 @@ bool deg_iterator_duplis_step(DEGObjectIterData *data)
continue;
}
verify_id_properties_freed(data);
free_owned_memory(data);
data->dupli_object_current = dob;
@ -169,6 +192,8 @@ bool deg_iterator_duplis_step(DEGObjectIterData *data)
copy_v4_v4(temp_dupli_object->color, dupli_parent->color);
temp_dupli_object->runtime.select_id = dupli_parent->runtime.select_id;
if (dob->ob->data != dob->ob_data) {
/* Do not modify the original boundbox. */
temp_dupli_object->runtime.bb = nullptr;
BKE_object_replace_data_on_shallow_copy(temp_dupli_object, dob->ob_data);
}
@ -192,7 +217,7 @@ bool deg_iterator_duplis_step(DEGObjectIterData *data)
return true;
}
verify_id_properties_freed(data);
free_owned_memory(data);
free_object_duplilist(data->dupli_list);
data->dupli_parent = nullptr;
data->dupli_list = nullptr;

View File

@ -757,8 +757,11 @@ static void duplidata_key_free(void *key)
}
else {
Object temp_object = *dupli_key->ob;
/* Do not modify the original boundbox. */
temp_object.runtime.bb = NULL;
BKE_object_replace_data_on_shallow_copy(&temp_object, dupli_key->ob_data);
drw_batch_cache_generate_requested(&temp_object);
MEM_SAFE_FREE(temp_object.runtime.bb);
}
MEM_freeN(key);
}