Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenlib/BLI_arithb.h1
-rw-r--r--source/blender/blenlib/intern/arithb.c12
-rw-r--r--source/blender/src/autoarmature.c362
3 files changed, 214 insertions, 161 deletions
diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h
index c22b6f79e08..ccb592bba05 100644
--- a/source/blender/blenlib/BLI_arithb.h
+++ b/source/blender/blenlib/BLI_arithb.h
@@ -262,6 +262,7 @@ void Vec2Subf(float *v, float *v1, float *v2);
void Vec2Copyf(float *v1, float *v2);
void AxisAngleToQuat(float *q, float *axis, float angle);
+void RotationBetweenVectorsToQuat(float *q, float v1[3], float v2[3]);
void vectoquat(float *vec, short axis, short upflag, float *q);
float VecAngle2(float *v1, float *v2);
diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c
index c97ca3c6a8a..6685e1b6dc5 100644
--- a/source/blender/blenlib/intern/arithb.c
+++ b/source/blender/blenlib/intern/arithb.c
@@ -1335,6 +1335,18 @@ void NormalQuat(float *q)
}
}
+void RotationBetweenVectorsToQuat(float *q, float v1[3], float v2[3])
+{
+ float axis[3];
+ float angle;
+
+ Crossf(axis, v1, v2);
+
+ angle = NormalizedVecAngle2(v1, v2);
+
+ AxisAngleToQuat(q, axis, angle);
+}
+
void AxisAngleToQuat(float *q, float *axis, float angle)
{
float nor[3];
diff --git a/source/blender/src/autoarmature.c b/source/blender/src/autoarmature.c
index 728cbff77da..cbbe0ffbb15 100644
--- a/source/blender/src/autoarmature.c
+++ b/source/blender/src/autoarmature.c
@@ -37,7 +37,9 @@
#include "PIL_time.h"
#include "DNA_ID.h"
+#include "DNA_action_types.h"
#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
@@ -55,6 +57,7 @@
#include "BKE_global.h"
#include "BKE_utildefines.h"
+#include "BKE_constraint.h"
#include "BIF_editarmature.h"
#include "BIF_space.h"
@@ -87,6 +90,12 @@ typedef struct RigGraph {
struct RigNode *head;
ReebGraph *link_mesh;
+
+ ListBase controls;
+
+ GHash *bones_map;
+
+ Object *ob;
} RigGraph;
typedef struct RigNode {
@@ -130,6 +139,13 @@ typedef struct RigEdge {
EditBone *bone;
} RigEdge;
+typedef struct RigControl {
+ struct RigControl *next, *prev;
+ EditBone *bone;
+ EditBone *parent;
+ float offset[3];
+} RigControl;
+
/*******************************************************************************************************/
static void RIG_calculateEdgeAngle(RigEdge *edge_first, RigEdge *edge_second);
@@ -196,6 +212,8 @@ void RIG_freeRigGraph(BGraph *rg)
}
BLI_freelistN(&rg->nodes);
+ BLI_ghash_free(((RigGraph*)rg)->bones_map, NULL, NULL);
+
MEM_freeN(rg);
}
@@ -208,6 +226,8 @@ static RigGraph *newRigGraph()
rg->head = NULL;
+ rg->bones_map = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp);
+
rg->free_arc = RIG_freeRigArc;
rg->free_node = NULL;
@@ -226,6 +246,17 @@ static RigArc *newRigArc(RigGraph *rg)
return arc;
}
+static RigControl *newRigControl(RigGraph *rg)
+{
+ RigControl *ctrl;
+
+ ctrl = MEM_callocN(sizeof(RigControl), "rig control");
+
+ BLI_addtail(&rg->controls, ctrl);
+
+ return ctrl;
+}
+
static RigNode *newRigNodeHead(RigGraph *rg, RigArc *arc, float p[3])
{
RigNode *node;
@@ -308,39 +339,121 @@ static void RIG_calculateEdgeAngle(RigEdge *edge_first, RigEdge *edge_second)
edge_first->angle = saacos(Inpf(vec_first, vec_second));
}
-/*******************************************************************************************************/
+/************************************ CONTROL BONES ****************************************************/
-static void RIG_arcFromBoneChain(RigGraph *rg, ListBase *list, EditBone *root_bone, RigNode *starting_node)
+static void RIG_addControlBone(RigGraph *rg, EditBone *bone)
{
- EditBone *bone, *last_bone = NULL;
- RigArc *arc;
- int contain_head = 0;
-
- arc = newRigArc(rg);
-
- if (starting_node == NULL)
+ RigControl *ctrl = newRigControl(rg);
+ ctrl->bone = bone;
+}
+
+static void RIG_parentControl(RigControl *ctrl, EditBone *parent)
+{
+ if (parent)
{
- starting_node = newRigNodeHead(rg, arc, root_bone->head);
+ ctrl->parent = parent;
+
+ VecSubf(ctrl->offset, ctrl->bone->head, ctrl->parent->tail);
}
- else
+}
+
+static void RIG_reconnectControlBones(RigGraph *rg)
+{
+ RigControl *ctrl;
+
+ for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next)
{
- addRigNodeHead(rg, arc, starting_node);
+ bPoseChannel *pchan;
+ bConstraint *con;
+ int found = 0;
+
+ /* DO SOME MAGIC HERE */
+ for (pchan= rg->ob->pose->chanbase.first; pchan; pchan= pchan->next)
+ {
+ for (con= pchan->constraints.first; con; con= con->next)
+ {
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ /* constraint targets */
+ if (cti && cti->get_constraint_targets)
+ {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct= targets.first; ct; ct= ct->next)
+ {
+ if ((ct->tar == rg->ob) && strcmp(ct->subtarget, ctrl->bone->name) == 0)
+ {
+ /* SET bone parent to bone corresponding to pchan */
+ EditBone *parent = BLI_ghash_lookup(rg->bones_map, pchan->name);
+
+ RIG_parentControl(ctrl, parent);
+ found = 1;
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
+ }
+ }
+
+ /* if not found yet, check parent */
+ if (found == 0)
+ {
+ RIG_parentControl(ctrl, ctrl->bone->parent);
+ }
}
+}
+
+/*******************************************************************************************************/
+
+static void RIG_arcFromBoneChain(RigGraph *rg, ListBase *list, EditBone *root_bone, RigNode *starting_node)
+{
+ EditBone *bone, *last_bone = root_bone;
+ RigArc *arc = NULL;
+ int contain_head = 0;
for(bone = root_bone; bone; bone = nextEditBoneChild(list, bone, 0))
{
int nb_children;
- if (bone->parent && (bone->flag & BONE_CONNECTED) == 0)
+ BLI_ghash_insert(rg->bones_map, bone->name, bone);
+
+ if ((bone->flag & BONE_NO_DEFORM) == 0)
{
- RIG_addEdgeToArc(arc, bone->head, NULL);
+ if (arc == NULL)
+ {
+ arc = newRigArc(rg);
+
+ if (starting_node == NULL)
+ {
+ starting_node = newRigNodeHead(rg, arc, root_bone->head);
+ }
+ else
+ {
+ addRigNodeHead(rg, arc, starting_node);
+ }
+ }
+
+ if (bone->parent && (bone->flag & BONE_CONNECTED) == 0)
+ {
+ RIG_addEdgeToArc(arc, bone->head, NULL);
+ }
+
+ RIG_addEdgeToArc(arc, bone->tail, bone);
+
+ last_bone = bone;
+
+ if (strcmp(bone->name, "head") == 0)
+ {
+ contain_head = 1;
+ }
}
-
- RIG_addEdgeToArc(arc, bone->tail, bone);
-
- if (strcmp(bone->name, "head") == 0)
+ else
{
- contain_head = 1;
+ RIG_addControlBone(rg, bone);
}
nb_children = countEditBoneChildren(list, bone);
@@ -358,11 +471,10 @@ static void RIG_arcFromBoneChain(RigGraph *rg, ListBase *list, EditBone *root_bo
/* arc ends here, break */
break;
}
- last_bone = bone;
}
/* If the loop exited without forking */
- if (bone == NULL)
+ if (arc != NULL && bone == NULL)
{
newRigNodeTail(rg, arc, last_bone->tail);
}
@@ -480,12 +592,14 @@ void RIG_printGraph(RigGraph *rg)
/*******************************************************************************************************/
-static RigGraph *armatureToGraph(ListBase *list)
+static RigGraph *armatureToGraph(Object *ob, ListBase *list)
{
EditBone *ebone;
RigGraph *rg;
rg = newRigGraph();
+
+ rg->ob = ob;
/* Do the rotations */
for (ebone = list->first; ebone; ebone=ebone->next){
@@ -495,6 +609,8 @@ static RigGraph *armatureToGraph(ListBase *list)
}
}
+ RIG_reconnectControlBones(rg);
+
BLI_removeDoubleNodes((BGraph*)rg, 0.001);
BLI_buildAdjacencyList((BGraph*)rg);
@@ -506,6 +622,57 @@ static RigGraph *armatureToGraph(ListBase *list)
/************************************ RETARGETTING *****************************************************/
+static void repositionControl(RigControl *ctrl, float parent[3], float qrot[4], float resize)
+{
+ float parent_offset[3], tail_offset[3];
+
+ VecSubf(tail_offset, ctrl->bone->tail, ctrl->bone->head);
+
+ VECCOPY(parent_offset, ctrl->offset);
+ VecMulf(parent_offset, resize);
+
+ QuatMulVecf(qrot, parent_offset);
+ QuatMulVecf(qrot, tail_offset);
+
+ VecAddf(ctrl->bone->head, parent, parent_offset);
+ VecAddf(ctrl->bone->tail, ctrl->bone->head, tail_offset);
+}
+
+static void repositionBone(RigGraph *rigg, EditBone *bone, float vec0[3], float vec1[3])
+{
+ RigControl *ctrl;
+ float qrot[4], resize = 0;
+
+ QuatOne(qrot);
+
+ for (ctrl = rigg->controls.first; ctrl; ctrl = ctrl->next)
+ {
+ if (ctrl->parent == bone)
+ {
+ if (resize == 0)
+ {
+ float v1[3], v2[3];
+ float l1, l2;
+
+ VecSubf(v1, bone->tail, bone->head);
+ VecSubf(v2, vec1, vec0);
+
+ l1 = Normalize(v1);
+ l2 = Normalize(v2);
+
+ resize = l2 / l1;
+
+ RotationBetweenVectorsToQuat(qrot, v1, v2);
+ }
+
+ repositionControl(ctrl, vec1, qrot, resize);
+ }
+ }
+
+ VECCOPY(bone->head, vec0);
+ VECCOPY(bone->tail, vec1);
+}
+
typedef enum
{
RETARGET_LENGTH,
@@ -513,7 +680,7 @@ typedef enum
} RetargetMode;
static RetargetMode detectArcRetargetMode(RigArc *arc);
-static void retargetArctoArcLength(RigArc *iarc);
+static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc);
static RetargetMode detectArcRetargetMode(RigArc *iarc)
@@ -881,7 +1048,7 @@ static int neighbour(int nb_joints, float *cost_cube, int *moving_joint, int *mo
return 1;
}
-static void retargetArctoArcAggresive(RigArc *iarc)
+static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc)
{
ReebArcIterator iter;
RigEdge *edge;
@@ -1195,86 +1362,7 @@ static void retargetArctoArcAggresive(RigArc *iarc)
MEM_freeN(cost_cube);
}
- /* GRADIENT DESCENT*/
- else if (G.scene->toolsettings->skgen_optimisation_method == 2)
- {
- RigEdge *previous;
- float *cost_cube;
-
- /* [joint: index][position: -1, 0, +1] */
- cost_cube = MEM_callocN(sizeof(float) * 3 * nb_joints, "Cost Cube");
-
- initArcIterator(&iter, earc, node_start);
-
- /* init vec_cache */
- for (i = 0; i < nb_joints; i++)
- {
- bucket = peekBucket(&iter, positions[i]);
- vec_cache[i + 1] = bucket->p;
- }
-
- /* init cost cube */
- for (previous = iarc->edges.first, edge = previous->next, i = 0;
- edge;
- previous = edge, edge = edge->next, i += 1)
- {
- calcGradient(previous, edge, &iter, i, nb_joints, cost_cube, positions, vec_cache);
- }
-
- while(1)
- {
- float min_gradient = 0;
- int moving_joint = -1;
- int move_direction = -1;
-
- for (i = 0; i < nb_joints; i++)
- {
- if (cost_cube[i * 3] < min_gradient)
- {
- min_gradient = cost_cube[i * 3];
- moving_joint = i;
- move_direction = -1;
- }
-
- if (cost_cube[i * 3 + 2] < min_gradient)
- {
- min_gradient = cost_cube[i * 3 + 2];
- moving_joint = i;
- move_direction = 1;
- }
- }
-
- if (moving_joint == -1)
- {
- break;
- }
-
- positions[moving_joint] += move_direction;
-
- /* update vector cache */
- bucket = peekBucket(&iter, positions[moving_joint]);
- vec_cache[moving_joint + 1] = bucket->p;
- /* update cost cube */
- for (previous = iarc->edges.first, edge = previous->next, i = 0;
- edge;
- previous = edge, edge = edge->next, i += 1)
- {
- if (i == moving_joint - 1 ||
- i == moving_joint ||
- i == moving_joint + 1)
- {
- calcGradient(previous, edge, &iter, i, nb_joints, cost_cube, positions, vec_cache);
- }
- }
-
-
- }
-
- memcpy(best_positions, positions, sizeof(int) * nb_joints);
-
- MEM_freeN(cost_cube);
- }
vec0 = node_start->p;
initArcIterator(&iter, earc, node_start);
@@ -1303,8 +1391,7 @@ static void retargetArctoArcAggresive(RigArc *iarc)
if (bone)
{
- VECCOPY(bone->head, vec0);
- VECCOPY(bone->tail, vec1);
+ repositionBone(rigg, bone, vec0, vec1);
}
vec0 = vec1;
@@ -1316,7 +1403,7 @@ static void retargetArctoArcAggresive(RigArc *iarc)
MEM_freeN(vec_cache);
}
-static void retargetArctoArcLength(RigArc *iarc)
+static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc)
{
ReebArcIterator iter;
ReebArc *earc = iarc->link_mesh;
@@ -1370,50 +1457,11 @@ static void retargetArctoArcLength(RigArc *iarc)
previous_vec = vec0;
vec1 = bucket->p;
- printf("arc: %f embedding %f\n", iarc->length, embedding_length);
-
for (edge = iarc->edges.first; edge; edge = edge->next)
{
EditBone *bone = edge->bone;
float new_bone_length = edge->length / iarc->length * embedding_length;
-#if 0
- while (bucket && new_bone_length > VecLenf(vec0, vec1))
- {
- bucket = nextBucket(&iter);
- previous_vec = vec1;
- vec1 = bucket->p;
- }
-
- if (bucket == NULL)
- {
- vec1 = node_end->p;
- }
-
- if (embedding_length < VecLenf(vec0, vec1))
- {
- float dv[3], off[3];
- float a, b, c, f;
-
- /* Solve quadratic distance equation */
- VecSubf(dv, vec1, previous_vec);
- a = Inpf(dv, dv);
-
- VecSubf(off, previous_vec, vec0);
- b = 2 * Inpf(dv, off);
-
- c = Inpf(off, off) - (new_bone_length * new_bone_length);
-
- f = (-b + (float)sqrt(b * b - 4 * a * c)) / (2 * a);
-
- if (isnan(f) == 0 && f < 1.0f)
- {
- VECCOPY(vec1, dv);
- VecMulf(vec1, f);
- VecAddf(vec1,vec1, vec0);
- }
- }
-#else
float length = 0;
while (bucket && new_bone_length > length)
@@ -1428,25 +1476,19 @@ static void retargetArctoArcLength(RigArc *iarc)
{
vec1 = node_end->p;
}
-#endif
/* no need to move virtual edges (space between unconnected bones) */
if (bone)
{
- printf("BONE: %s\n", bone->name);
- VECCOPY(bone->head, vec0);
- VECCOPY(bone->tail, vec1);
+ repositionBone(rigg, bone, vec0, vec1);
}
- printvecf("vec0", vec0);
- printvecf("vec1", vec1);
- printf("old: %f target: %f new: %f\n", edge->length, new_bone_length, VecLenf(vec0, vec1));
vec0 = vec1;
previous_vec = vec1;
}
}
-static void retargetArctoArc(RigArc *iarc)
+static void retargetArctoArc(RigGraph *rigg, RigArc *iarc)
{
ReebArc *earc = iarc->link_mesh;
@@ -1458,14 +1500,12 @@ static void retargetArctoArc(RigArc *iarc)
/* symmetry axis */
if (earc->symmetry_level == 1 && iarc->symmetry_level == 1)
{
- VECCOPY(bone->head, earc->tail->p);
- VECCOPY(bone->tail, earc->head->p);
+ repositionBone(rigg, bone, earc->tail->p, earc->head->p);
}
/* or not */
else
{
- VECCOPY(bone->head, earc->head->p);
- VECCOPY(bone->tail, earc->tail->p);
+ repositionBone(rigg, bone, earc->head->p, earc->tail->p);
}
}
else
@@ -1474,11 +1514,11 @@ static void retargetArctoArc(RigArc *iarc)
if (mode == RETARGET_AGGRESSIVE)
{
- retargetArctoArcAggresive(iarc);
+ retargetArctoArcAggresive(rigg, iarc);
}
else
{
- retargetArctoArcLength(iarc);
+ retargetArctoArcLength(rigg, iarc);
}
}
}
@@ -1598,7 +1638,7 @@ static void retargetSubgraph(RigGraph *rigg, RigArc *start_arc, RigNode *start_n
ReebNode *enode = start_node->link_mesh;
ReebArc *earc = start_arc->link_mesh;
- retargetArctoArc(start_arc);
+ retargetArctoArc(rigg, start_arc);
enode = BIF_otherNodeFromIndex(earc, enode);
inode = (RigNode*)BLI_otherNode((BArc*)start_arc, (BNode*)inode);
@@ -1672,7 +1712,7 @@ void BIF_retargetArmature()
list.first= list.last = NULL;
make_boneList(&list, &arm->bonebase, NULL);
- rigg = armatureToGraph(&list);
+ rigg = armatureToGraph(ob, &list);
BLI_markdownSymmetry((BGraph*)rigg, (BNode*)rigg->head, G.scene->toolsettings->skgen_symmetry_limit);