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,6 +1328,37 @@ void BKE_pose_rest(bPose *pose)
}
}
void BKE_pose_copyesult_pchan_result(bPoseChannel *pchanto, const bPoseChannel *pchanfrom)
{
copy_m4_m4(pchanto->pose_mat, pchanfrom->pose_mat);
copy_m4_m4(pchanto->chan_mat, pchanfrom->chan_mat);
/* used for local constraints */
copy_v3_v3(pchanto->loc, pchanfrom->loc);
copy_qt_qt(pchanto->quat, pchanfrom->quat);
copy_v3_v3(pchanto->eul, pchanfrom->eul);
copy_v3_v3(pchanto->size, pchanfrom->size);
copy_v3_v3(pchanto->pose_head, pchanfrom->pose_head);
copy_v3_v3(pchanto->pose_tail, pchanfrom->pose_tail);
pchanto->roll1 = pchanfrom->roll1;
pchanto->roll2 = pchanfrom->roll2;
pchanto->curveInX = pchanfrom->curveInX;
pchanto->curveInY = pchanfrom->curveInY;
pchanto->curveOutX = pchanfrom->curveOutX;
pchanto->curveOutY = pchanfrom->curveOutY;
pchanto->ease1 = pchanfrom->ease1;
pchanto->ease2 = pchanfrom->ease2;
pchanto->scaleIn = pchanfrom->scaleIn;
pchanto->scaleOut = pchanfrom->scaleOut;
pchanto->rotmode = pchanfrom->rotmode;
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)
{
@@ -1346,34 +1377,8 @@ bool BKE_pose_copy_result(bPose *to, bPose *from)
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);
/* used for local constraints */
copy_v3_v3(pchanto->loc, pchanfrom->loc);
copy_qt_qt(pchanto->quat, pchanfrom->quat);
copy_v3_v3(pchanto->eul, pchanfrom->eul);
copy_v3_v3(pchanto->size, pchanfrom->size);
copy_v3_v3(pchanto->pose_head, pchanfrom->pose_head);
copy_v3_v3(pchanto->pose_tail, pchanfrom->pose_tail);
pchanto->roll1 = pchanfrom->roll1;
pchanto->roll2 = pchanfrom->roll2;
pchanto->curveInX = pchanfrom->curveInX;
pchanto->curveInY = pchanfrom->curveInY;
pchanto->curveOutX = pchanfrom->curveOutX;
pchanto->curveOutY = pchanfrom->curveOutY;
pchanto->ease1 = pchanfrom->ease1;
pchanto->ease2 = pchanfrom->ease2;
pchanto->scaleIn = pchanfrom->scaleIn;
pchanto->scaleOut = pchanfrom->scaleOut;
pchanto->rotmode = pchanfrom->rotmode;
pchanto->flag = pchanfrom->flag;
pchanto->protectflag = pchanfrom->protectflag;
pchanto->bboneflag = pchanfrom->bboneflag;
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,