Fix T56170: Fake dependency cycle in new depsgraph + interleaved armature update + proxy

Make proxy copy result more atomic operation.
This commit is contained in:
2018-07-31 13:23:01 +02:00
parent 7a91ae1103
commit bb7b1cc884
7 changed files with 117 additions and 51 deletions

View File

@@ -201,6 +201,7 @@ void BKE_pose_remove_group_index(struct bPose *pose, const int index);
void what_does_obaction(struct Object *ob, struct Object *workob, struct bPose *pose, struct bAction *act, char groupname[], float cframe);
/* for proxy */
void BKE_pose_copyesult_pchan_result(struct bPoseChannel *pchanto, const struct bPoseChannel *pchanfrom);
bool BKE_pose_copy_result(struct bPose *to, struct bPose *from);
/* clear all transforms */
void BKE_pose_rest(struct bPose *pose);

View File

@@ -231,9 +231,16 @@ void BKE_pose_eval_flush(
struct Scene *scene,
struct Object *ob);
void BKE_pose_eval_proxy_copy(
void BKE_pose_eval_proxy_pose_init(struct Depsgraph *depsgraph,
struct Object *object);
void BKE_pose_eval_proxy_pose_done(struct Depsgraph *depsgraph,
struct Object *object);
void BKE_pose_eval_proxy_copy_bone(
struct Depsgraph *depsgraph,
struct Object *ob);
struct Object *object,
int pchan_index);
#ifdef __cplusplus
}

View File

@@ -1328,25 +1328,8 @@ void BKE_pose_rest(bPose *pose)
}
}
/* both poses should be in sync */
bool BKE_pose_copy_result(bPose *to, bPose *from)
void BKE_pose_copyesult_pchan_result(bPoseChannel *pchanto, const bPoseChannel *pchanfrom)
{
bPoseChannel *pchanto, *pchanfrom;
if (to == NULL || from == NULL) {
printf("Pose copy error, pose to:%p from:%p\n", (void *)to, (void *)from); /* debug temp */
return false;
}
if (to == from) {
printf("BKE_pose_copy_result source and target are the same\n");
return false;
}
for (pchanfrom = from->chanbase.first; pchanfrom; pchanfrom = pchanfrom->next) {
pchanto = BKE_pose_channel_find_name(to, pchanfrom->name);
if (pchanto) {
copy_m4_m4(pchanto->pose_mat, pchanfrom->pose_mat);
copy_m4_m4(pchanto->chan_mat, pchanfrom->chan_mat);
@@ -1374,6 +1357,28 @@ bool BKE_pose_copy_result(bPose *to, bPose *from)
pchanto->flag = pchanfrom->flag;
pchanto->protectflag = pchanfrom->protectflag;
pchanto->bboneflag = pchanfrom->bboneflag;
}
/* both poses should be in sync */
bool BKE_pose_copy_result(bPose *to, bPose *from)
{
bPoseChannel *pchanto, *pchanfrom;
if (to == NULL || from == NULL) {
printf("Pose copy error, pose to:%p from:%p\n", (void *)to, (void *)from); /* debug temp */
return false;
}
if (to == from) {
printf("BKE_pose_copy_result source and target are the same\n");
return false;
}
for (pchanfrom = from->chanbase.first; pchanfrom; pchanfrom = pchanfrom->next) {
pchanto = BKE_pose_channel_find_name(to, pchanfrom->name);
if (pchanto != NULL) {
BKE_pose_copyesult_pchan_result(pchanto, pchanfrom);
}
}
return true;

View File

@@ -558,6 +558,17 @@ void BKE_splineik_execute_tree(
/* *************** Depsgraph evaluation callbacks ************ */
static void pose_pchan_index_create(bPose *pose)
{
const int num_channels = BLI_listbase_count(&pose->chanbase);
pose->chan_array = MEM_malloc_arrayN(
num_channels, sizeof(bPoseChannel *), "pose->chan_array");
int pchan_index = 0;
for (bPoseChannel *pchan = pose->chanbase.first; pchan != NULL; pchan = pchan->next) {
pose->chan_array[pchan_index++] = pchan;
}
}
BLI_INLINE bPoseChannel *pose_pchan_get_indexed(Object *ob, int pchan_index)
{
bPose *pose = ob->pose;
@@ -585,16 +596,12 @@ void BKE_pose_eval_init(struct Depsgraph *depsgraph,
/* imat is needed for solvers. */
invert_m4_m4(ob->imat, ob->obmat);
const int num_channels = BLI_listbase_count(&pose->chanbase);
pose->chan_array = MEM_malloc_arrayN(
num_channels, sizeof(bPoseChannel *), "pose->chan_array");
/* clear flags */
int pchan_index = 0;
for (bPoseChannel *pchan = pose->chanbase.first; pchan != NULL; pchan = pchan->next) {
pchan->flag &= ~(POSE_DONE | POSE_CHAIN | POSE_IKTREE | POSE_IKSPLINE);
pose->chan_array[pchan_index++] = pchan;
}
pose_pchan_index_create(pose);
}
void BKE_pose_eval_init_ik(struct Depsgraph *depsgraph,
@@ -752,12 +759,44 @@ void BKE_pose_eval_flush(struct Depsgraph *depsgraph,
pose->chan_array = NULL;
}
void BKE_pose_eval_proxy_copy(struct Depsgraph *depsgraph, Object *ob)
void BKE_pose_eval_proxy_pose_init(struct Depsgraph *depsgraph, Object *object)
{
BLI_assert(ID_IS_LINKED(ob) && ob->proxy_from != NULL);
DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob);
if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) {
printf("Proxy copy error, lib Object: %s proxy Object: %s\n",
ob->id.name + 2, ob->proxy_from->id.name + 2);
}
BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL);
DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
pose_pchan_index_create(object->pose);
}
void BKE_pose_eval_proxy_pose_done(struct Depsgraph *depsgraph, Object *object)
{
BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL);
DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
bPose *pose = object->pose;
BLI_assert(pose->chan_array != NULL);
MEM_freeN(pose->chan_array);
pose->chan_array = NULL;
}
void BKE_pose_eval_proxy_copy_bone(
struct Depsgraph *depsgraph,
Object *object,
int pchan_index)
{
BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL);
DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
bPoseChannel *pchan = pose_pchan_get_indexed(object, pchan_index);
/* TODO(sergey): Use indexec lookup, once it's guaranteed to be kept
* around for the time while proxies are evaluating.
*/
#if 0
bPoseChannel *pchan_from = pose_pchan_get_indexed(
object->proxy_from, pchan_index);
#else
bPoseChannel *pchan_from = BKE_pose_channel_find_name(
object->proxy_from->pose, pchan->name);
#endif
BLI_assert(pchan != NULL);
BLI_assert(pchan_from != NULL);
BKE_pose_copyesult_pchan_result(pchan, pchan_from);
}

View File

@@ -314,12 +314,13 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object)
}
op_node = add_operation_node(&object->id,
DEG_NODE_TYPE_EVAL_POSE,
function_bind(BKE_pose_eval_proxy_copy,
function_bind(BKE_pose_eval_proxy_pose_init,
_1,
object_cow),
DEG_OPCODE_POSE_INIT);
op_node->set_as_entry();
int pchan_index = 0;
LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
op_node = add_operation_node(&object->id,
DEG_NODE_TYPE_BONE,
@@ -334,10 +335,14 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object)
NULL,
DEG_OPCODE_BONE_READY);
/* Bone is fully evaluated. */
op_node = add_operation_node(&object->id,
op_node = add_operation_node(
&object->id,
DEG_NODE_TYPE_BONE,
pchan->name,
NULL,
function_bind(BKE_pose_eval_proxy_copy_bone,
_1,
object_cow,
pchan_index),
DEG_OPCODE_BONE_DONE);
op_node->set_as_exit();
@@ -349,10 +354,14 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object)
DEG_OPCODE_PARAMETERS_EVAL,
pchan->name);
}
pchan_index++;
}
op_node = add_operation_node(&object->id,
DEG_NODE_TYPE_EVAL_POSE,
NULL,
function_bind(BKE_pose_eval_proxy_pose_done,
_1,
object_cow),
DEG_OPCODE_POSE_DONE);
op_node->set_as_exit();
}

View File

@@ -587,10 +587,6 @@ void DepsgraphRelationBuilder::build_object(Base *base, Object *object)
/* Proxy object to copy from. */
if (object->proxy_from != NULL) {
build_object(NULL, object->proxy_from);
ComponentKey ob_pose_key(&object->proxy_from->id, DEG_NODE_TYPE_EVAL_POSE);
ComponentKey proxy_pose_key(&object->id, DEG_NODE_TYPE_EVAL_POSE);
add_relation(ob_pose_key, proxy_pose_key, "Proxy Pose");
ComponentKey ob_transform_key(&object->proxy_from->id, DEG_NODE_TYPE_TRANSFORM);
ComponentKey proxy_transform_key(&object->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(ob_transform_key, proxy_transform_key, "Proxy Transform");

View File

@@ -469,11 +469,20 @@ void DepsgraphRelationBuilder::build_proxy_rig(Object *object)
DEG_NODE_TYPE_BONE,
pchan->name,
DEG_OPCODE_BONE_DONE);
OperationKey from_bone_done_key(&proxy_from->id,
DEG_NODE_TYPE_BONE,
pchan->name,
DEG_OPCODE_BONE_DONE);
add_relation(pose_init_key, bone_local_key, "Pose Init -> Bone Local");
add_relation(bone_local_key, bone_ready_key, "Local -> Ready");
add_relation(bone_ready_key, bone_done_key, "Ready -> Done");
add_relation(bone_done_key, pose_done_key, "Bone Done -> Pose Done");
/* Make sure bone in the proxy is not done before it's FROM is done. */
add_relation(from_bone_done_key,
bone_done_key,
"From Bone Done -> Pose Done");
if (pchan->prop != NULL) {
OperationKey bone_parameters(&object->id,
DEG_NODE_TYPE_PARAMETERS,