Bugfix #5038
The "Copy Size" constraint was calling a where_is_object(), this caused the depsgraph to mess up in very weird ways and rare occasions. In the sample file it showed strange lags in bones for using the "Stride bone" option. While trying to locate the bug I've revisited the Pose depsgraph in detail, trying to figure out how it can print possible cycle errors in dependency. That has been added now too (in console). Unfortunately the bugreport example had no cycle errors. :)
This commit is contained in:
@@ -73,6 +73,7 @@ typedef struct DagNode
|
||||
int DFS_dvtm; // DFS discovery time
|
||||
int DFS_fntm; // DFS Finishing time
|
||||
struct DagAdjList *child;
|
||||
struct DagAdjList *parent;
|
||||
struct DagNode *next;
|
||||
} DagNode;
|
||||
|
||||
|
||||
@@ -1000,8 +1000,6 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
|
||||
data = (bSizeLikeConstraint*)con->data;
|
||||
|
||||
if (data->tar){
|
||||
/* Update the location of the target object */
|
||||
where_is_object_time (data->tar, ctime);
|
||||
constraint_target_to_mat4(data->tar, data->subtarget, mat, size);
|
||||
valid=1;
|
||||
}
|
||||
@@ -1151,7 +1149,7 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
|
||||
|
||||
if (!constraint || !ob)
|
||||
return;
|
||||
|
||||
return;
|
||||
Mat4One (M_identity);
|
||||
|
||||
switch (constraint->type){
|
||||
@@ -1380,7 +1378,6 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
|
||||
|
||||
|
||||
data=(bLockTrackConstraint*)constraint->data;
|
||||
|
||||
|
||||
if (data->tar){
|
||||
|
||||
|
||||
@@ -650,6 +650,14 @@ void free_forest(DagForest *Dag)
|
||||
itA = itA->next;
|
||||
MEM_freeN(tempA);
|
||||
}
|
||||
|
||||
itA = itN->parent;
|
||||
while (itA) {
|
||||
tempA = itA;
|
||||
itA = itA->next;
|
||||
MEM_freeN(tempA);
|
||||
}
|
||||
|
||||
tempN = itN;
|
||||
itN = itN->next;
|
||||
MEM_freeN(tempN);
|
||||
@@ -759,6 +767,27 @@ void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel
|
||||
fob1->child = itA;
|
||||
}
|
||||
|
||||
static void dag_add_parent_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel)
|
||||
{
|
||||
DagAdjList *itA = fob2->parent;
|
||||
|
||||
while (itA) { /* search if relation exist already */
|
||||
if (itA->node == fob1) {
|
||||
itA->type |= rel;
|
||||
itA->count += 1;
|
||||
return;
|
||||
}
|
||||
itA = itA->next;
|
||||
}
|
||||
/* create new relation and insert at head. MALLOC alert! */
|
||||
itA = MEM_mallocN(sizeof(DagAdjList),"DAG adj list");
|
||||
itA->node = fob1;
|
||||
itA->type = rel;
|
||||
itA->count = 1;
|
||||
itA->next = fob2->parent;
|
||||
fob2->parent = itA;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* MainDAG is the DAG of all objects in current scene
|
||||
@@ -1925,6 +1954,50 @@ void DAG_object_update_flags(Scene *sce, Object *ob, unsigned int lay)
|
||||
|
||||
/* ******************* DAG FOR ARMATURE POSE ***************** */
|
||||
|
||||
static int node_recurs_level(DagNode *node, int level)
|
||||
{
|
||||
DagAdjList *itA;
|
||||
|
||||
node->color= DAG_BLACK; /* done */
|
||||
level++;
|
||||
|
||||
for(itA= node->parent; itA; itA= itA->next) {
|
||||
if(itA->node->color==DAG_WHITE)
|
||||
itA->node->ancestor_count= node_recurs_level(itA->node, level);
|
||||
}
|
||||
|
||||
return level;
|
||||
}
|
||||
|
||||
static void pose_check_cycle(DagForest *dag)
|
||||
{
|
||||
DagNode *node;
|
||||
DagAdjList *itA;
|
||||
|
||||
/* tag nodes unchecked */
|
||||
for(node = dag->DagNode.first; node; node= node->next)
|
||||
node->color= DAG_WHITE;
|
||||
|
||||
for(node = dag->DagNode.first; node; node= node->next) {
|
||||
if(node->color==DAG_WHITE) {
|
||||
node->ancestor_count= node_recurs_level(node, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* check relations, and print errors */
|
||||
for(node = dag->DagNode.first; node; node= node->next) {
|
||||
for(itA= node->parent; itA; itA= itA->next) {
|
||||
if(itA->node->ancestor_count > node->ancestor_count) {
|
||||
bPoseChannel *pchan= (bPoseChannel *)node->ob;
|
||||
bPoseChannel *parchan= (bPoseChannel *)itA->node->ob;
|
||||
|
||||
if(pchan && parchan)
|
||||
printf("Cycle in %s to %s\n", pchan->name, parchan->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* we assume its an armature with pose */
|
||||
void DAG_pose_sort(Object *ob)
|
||||
{
|
||||
@@ -1954,6 +2027,7 @@ void DAG_pose_sort(Object *ob)
|
||||
if(pchan->parent) {
|
||||
node2 = dag_get_node(dag, pchan->parent);
|
||||
dag_add_relation(dag, node2, node, 0);
|
||||
dag_add_parent_relation(dag, node2, node, 0);
|
||||
addtoroot = 0;
|
||||
}
|
||||
for (con = pchan->constraints.first; con; con=con->next){
|
||||
@@ -1966,6 +2040,7 @@ void DAG_pose_sort(Object *ob)
|
||||
if(target) {
|
||||
node2= dag_get_node(dag, target);
|
||||
dag_add_relation(dag, node2, node, 0);
|
||||
dag_add_parent_relation(dag, node2, node, 0);
|
||||
|
||||
if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
|
||||
bKinematicConstraint *data = (bKinematicConstraint*)con->data;
|
||||
@@ -1982,6 +2057,7 @@ void DAG_pose_sort(Object *ob)
|
||||
while (parchan){
|
||||
node3= dag_get_node(dag, parchan);
|
||||
dag_add_relation(dag, node2, node3, 0);
|
||||
dag_add_parent_relation(dag, node2, node3, 0);
|
||||
|
||||
segcount++;
|
||||
if(segcount==data->rootbone || segcount>255) break; // 255 is weak
|
||||
@@ -1992,10 +2068,14 @@ void DAG_pose_sort(Object *ob)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (addtoroot == 1 )
|
||||
if (addtoroot == 1 ) {
|
||||
dag_add_relation(dag, rootnode, node, 0);
|
||||
dag_add_parent_relation(dag, rootnode, node, 0);
|
||||
}
|
||||
}
|
||||
|
||||
pose_check_cycle(dag);
|
||||
|
||||
/* now we try to sort... */
|
||||
tempbase.first= tempbase.last= NULL;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user