Fix T49718: Wrong "Make Duplicates Real" behavior with "Keep Hierarchy"

All objects were being parented to a single instance of each parent
object, instead of their respective instances, when using dupliverts or
dupligroups.

Behavior was caused by the `persistent_id[0]` (vertex/face id) being
ignored when computing `parent_gh` hash, which caused all instances to
have the same hash, and thus only the first one was included.

Reviewed By: mont29

Differential Revision: https://developer.blender.org/D2370
This commit is contained in:
Luca Rood 2016-11-22 14:38:43 -02:00
parent 9aa8d1bc45
commit 99c5c8befc
Notes: blender-bot 2023-02-21 17:59:30 +01:00
Referenced by issue #49718, "Make duplicates real" on dupliverts doesn't keep hierarchy
1 changed files with 48 additions and 7 deletions

View File

@ -1253,10 +1253,10 @@ static void copy_object_set_idnew(bContext *C)
/********************* Make Duplicates Real ************************/
/**
* \note regarding hashing dupli-objects, skip the first member of #DupliObject.persistent_id
* \note regarding hashing dupli-objects when using OB_DUPLIGROUP, skip the first member of #DupliObject.persistent_id
* since its a unique index and we only want to know if the group objects are from the same dupli-group instance.
*/
static unsigned int dupliobject_hash(const void *ptr)
static unsigned int dupliobject_group_hash(const void *ptr)
{
const DupliObject *dob = ptr;
unsigned int hash = BLI_ghashutil_ptrhash(dob->ob);
@ -1267,7 +1267,20 @@ static unsigned int dupliobject_hash(const void *ptr)
return hash;
}
static bool dupliobject_cmp(const void *a_, const void *b_)
/**
* \note regarding hashing dupli-objects when NOT using OB_DUPLIGROUP, include the first member of #DupliObject.persistent_id
* since its the index of the vertex/face the object is instantiated on and we want to identify objects on the same vertex/face.
*/
static unsigned int dupliobject_hash(const void *ptr)
{
const DupliObject *dob = ptr;
unsigned int hash = BLI_ghashutil_ptrhash(dob->ob);
hash ^= (dob->persistent_id[0] ^ 0);
return hash;
}
/* Compare function that matches dupliobject_group_hash */
static bool dupliobject_group_cmp(const void *a_, const void *b_)
{
const DupliObject *a = a_;
const DupliObject *b = b_;
@ -1290,6 +1303,24 @@ static bool dupliobject_cmp(const void *a_, const void *b_)
return false;
}
/* Compare function that matches dupliobject_hash */
static bool dupliobject_cmp(const void *a_, const void *b_)
{
const DupliObject *a = a_;
const DupliObject *b = b_;
if (a->ob != b->ob) {
return true;
}
if (a->persistent_id[0] != b->persistent_id[0]) {
return true;
}
/* matching */
return false;
}
static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
const bool use_base_parent,
const bool use_hierarchy)
@ -1308,7 +1339,12 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
if (use_hierarchy || use_base_parent) {
dupli_gh = BLI_ghash_ptr_new(__func__);
if (use_hierarchy) {
parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
if (base->object->transflag & OB_DUPLIGROUP) {
parent_gh = BLI_ghash_new(dupliobject_group_hash, dupliobject_group_cmp, __func__);
}
else {
parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
}
}
}
@ -1376,9 +1412,14 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
* they won't be read, this is simply for a hash lookup. */
DupliObject dob_key;
dob_key.ob = ob_src_par;
memcpy(&dob_key.persistent_id[1],
&dob->persistent_id[1],
sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
if (base->object->transflag & OB_DUPLIGROUP) {
memcpy(&dob_key.persistent_id[1],
&dob->persistent_id[1],
sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
}
else {
dob_key.persistent_id[0] = dob->persistent_id[0];
}
ob_dst_par = BLI_ghash_lookup(parent_gh, &dob_key);
}