Blender  V2.59
editarmature_retarget.c
Go to the documentation of this file.
00001 /*
00002  * $Id: editarmature_retarget.c 36276 2011-04-21 15:53:30Z campbellbarton $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * Contributor(s): Martin Poirier
00021  *
00022  * ***** END GPL LICENSE BLOCK *****
00023  * autoarmature.c: Interface for automagically manipulating armature (retarget, created, ...)
00024  */
00025 
00031 #include <ctype.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <math.h> 
00035 #include <float.h>
00036 
00037 #include "MEM_guardedalloc.h"
00038 
00039 #include "PIL_time.h"
00040 
00041 #include "DNA_armature_types.h"
00042 #include "DNA_constraint_types.h"
00043 #include "DNA_scene_types.h"
00044 #include "DNA_object_types.h"
00045 
00046 #include "BLI_blenlib.h"
00047 #include "BLI_math.h"
00048 #include "BLI_editVert.h"
00049 #include "BLI_utildefines.h"
00050 #include "BLI_ghash.h"
00051 #include "BLI_graph.h"
00052 #include "BLI_rand.h"
00053 #include "BLI_threads.h"
00054 
00055 //#include "BDR_editobject.h"
00056 
00057 #include "BKE_constraint.h"
00058 #include "BKE_armature.h"
00059 #include "BKE_context.h"
00060 
00061 #include "ED_armature.h"
00062 #include "ED_util.h"
00063 
00064 #include "BIF_retarget.h"
00065 
00066 
00067 //#include "mydevice.h"
00068 #include "reeb.h" // FIX ME
00069 //#include "blendef.h"
00070 
00071 #include "armature_intern.h"
00072 
00073 /************ RIG RETARGET DATA STRUCTURES ***************/
00074 
00075 typedef struct MemoNode {
00076         float   weight;
00077         int     next;
00078 } MemoNode;
00079 
00080 typedef struct RetargetParam {
00081         RigGraph        *rigg;
00082         RigArc          *iarc;
00083         RigNode         *inode_start;
00084         bContext        *context;
00085 } RetargetParam;
00086 
00087 typedef enum 
00088 {
00089         RETARGET_LENGTH,
00090         RETARGET_AGGRESSIVE
00091 } RetargetMode; 
00092 
00093 typedef enum
00094 {
00095         METHOD_BRUTE_FORCE = 0,
00096         METHOD_MEMOIZE = 1
00097 } RetargetMethod;
00098 
00099 typedef enum
00100 {
00101         ARC_FREE = 0,
00102         ARC_TAKEN = 1,
00103         ARC_USED = 2
00104 } ArcUsageFlags;
00105 
00106 static RigGraph *GLOBAL_RIGG = NULL;
00107 
00108 /*******************************************************************************************************/
00109 
00110 void *exec_retargetArctoArc(void *param);
00111 
00112 static void RIG_calculateEdgeAngles(RigEdge *edge_first, RigEdge *edge_second);
00113 float rollBoneByQuat(EditBone *bone, float old_up_axis[3], float qrot[4]);
00114 
00115 /* two levels */
00116 #define SHAPE_LEVELS (SHAPE_RADIX * SHAPE_RADIX) 
00117 
00118 /*********************************** EDITBONE UTILS ****************************************************/
00119 
00120 static int countEditBoneChildren(ListBase *list, EditBone *parent)
00121 {
00122         EditBone *ebone;
00123         int count = 0;
00124         
00125         for (ebone = list->first; ebone; ebone = ebone->next)
00126         {
00127                 if (ebone->parent == parent)
00128                 {
00129                         count++;
00130                 }
00131         }
00132         
00133         return count;
00134 }
00135 
00136 static EditBone* nextEditBoneChild(ListBase *list, EditBone *parent, int n)
00137 {
00138         EditBone *ebone;
00139         
00140         for (ebone = list->first; ebone; ebone = ebone->next)
00141         {
00142                 if (ebone->parent == parent)
00143                 {
00144                         if (n == 0)
00145                         {
00146                                 return ebone;
00147                         }
00148                         n--;
00149                 }
00150         }
00151         
00152         return NULL;
00153 }
00154 
00155 static void getEditBoneRollUpAxis(EditBone *bone, float roll, float up_axis[3])
00156 {
00157         float mat[3][3], nor[3];
00158 
00159         sub_v3_v3v3(nor, bone->tail, bone->head);
00160         
00161         vec_roll_to_mat3(nor, roll, mat);
00162         VECCOPY(up_axis, mat[2]);
00163 }
00164 
00165 static float rollBoneByQuatAligned(EditBone *bone, float old_up_axis[3], float qrot[4], float qroll[4], float aligned_axis[3])
00166 {
00167         float nor[3], new_up_axis[3], x_axis[3], z_axis[3];
00168         
00169         VECCOPY(new_up_axis, old_up_axis);
00170         mul_qt_v3(qrot, new_up_axis);
00171         
00172         sub_v3_v3v3(nor, bone->tail, bone->head);
00173         
00174         cross_v3_v3v3(x_axis, nor, aligned_axis);
00175         cross_v3_v3v3(z_axis, x_axis, nor);
00176         
00177         normalize_v3(new_up_axis);
00178         normalize_v3(x_axis);
00179         normalize_v3(z_axis);
00180         
00181         if (dot_v3v3(new_up_axis, x_axis) < 0)
00182         {
00183                 negate_v3(x_axis);
00184         }
00185         
00186         if (dot_v3v3(new_up_axis, z_axis) < 0)
00187         {
00188                 negate_v3(z_axis);
00189         }
00190         
00191         if (angle_normalized_v3v3(x_axis, new_up_axis) < angle_normalized_v3v3(z_axis, new_up_axis))
00192         {
00193                 rotation_between_vecs_to_quat(qroll, new_up_axis, x_axis); /* set roll rotation quat */
00194                 return ED_rollBoneToVector(bone, x_axis, FALSE);
00195         }
00196         else
00197         {
00198                 rotation_between_vecs_to_quat(qroll, new_up_axis, z_axis); /* set roll rotation quat */
00199                 return ED_rollBoneToVector(bone, z_axis, FALSE);
00200         }
00201 }
00202 
00203 static float rollBoneByQuatJoint(RigEdge *edge, RigEdge *previous, float qrot[4], float qroll[4], float up_axis[3])
00204 {
00205         if (previous == NULL)
00206         {
00207                 /* default to up_axis if no previous */
00208                 return rollBoneByQuatAligned(edge->bone, edge->up_axis, qrot, qroll, up_axis);
00209         }
00210         else
00211         {
00212                 float new_up_axis[3];
00213                 float vec_first[3], vec_second[3], normal[3];
00214                 
00215                 if (previous->bone)
00216                 {
00217                         sub_v3_v3v3(vec_first, previous->bone->tail, previous->bone->head);
00218                 } 
00219                 else if (previous->prev->bone)
00220                 {
00221                         sub_v3_v3v3(vec_first, edge->bone->head, previous->prev->bone->tail);
00222                 }
00223                 else
00224                 {
00225                         /* default to up_axis if first bone in the chain is an offset */
00226                         return rollBoneByQuatAligned(edge->bone, edge->up_axis, qrot, qroll, up_axis);
00227                 }
00228                 
00229                 sub_v3_v3v3(vec_second, edge->bone->tail, edge->bone->head);
00230         
00231                 normalize_v3(vec_first);
00232                 normalize_v3(vec_second);
00233                 
00234                 cross_v3_v3v3(normal, vec_first, vec_second);
00235                 normalize_v3(normal);
00236                 
00237                 axis_angle_to_quat(qroll, vec_second, edge->up_angle);
00238                 
00239                 mul_qt_v3(qroll, normal);
00240                         
00241                 VECCOPY(new_up_axis, edge->up_axis);
00242                 mul_qt_v3(qrot, new_up_axis);
00243                 
00244                 normalize_v3(new_up_axis);
00245                 
00246                 /* real qroll between normal and up_axis */
00247                 rotation_between_vecs_to_quat(qroll, new_up_axis, normal);
00248 
00249                 return ED_rollBoneToVector(edge->bone, normal, FALSE);
00250         }
00251 }
00252 
00253 float rollBoneByQuat(EditBone *bone, float old_up_axis[3], float qrot[4])
00254 {
00255         float new_up_axis[3];
00256         
00257         VECCOPY(new_up_axis, old_up_axis);
00258         mul_qt_v3(qrot, new_up_axis);
00259         
00260         return ED_rollBoneToVector(bone, new_up_axis, FALSE);
00261 }
00262 
00263 /************************************ DESTRUCTORS ******************************************************/
00264 
00265 static void RIG_freeRigArc(BArc *arc)
00266 {
00267         BLI_freelistN(&((RigArc*)arc)->edges);
00268 }
00269 
00270 void RIG_freeRigGraph(BGraph *rg)
00271 {
00272         RigGraph *rigg = (RigGraph*)rg;
00273         BNode *node;
00274         BArc *arc;
00275         
00276 #ifdef USE_THREADS
00277         BLI_destroy_worker(rigg->worker);
00278 #endif
00279         
00280         if (rigg->link_mesh)
00281         {
00282                 REEB_freeGraph(rigg->link_mesh);
00283         }
00284         
00285         for (arc = rg->arcs.first; arc; arc = arc->next)
00286         {
00287                 RIG_freeRigArc(arc);
00288         }
00289         BLI_freelistN(&rg->arcs);
00290         
00291         for (node = rg->nodes.first; node; node = node->next)
00292         {
00293                 BLI_freeNode(rg, (BNode*)node);
00294         }
00295         BLI_freelistN(&rg->nodes);
00296         
00297         BLI_freelistN(&rigg->controls);
00298 
00299         BLI_ghash_free(rigg->bones_map, NULL, NULL);
00300         BLI_ghash_free(rigg->controls_map, NULL, NULL);
00301         
00302         if (rigg->flag & RIG_FREE_BONELIST)
00303         {
00304                 BLI_freelistN(rigg->editbones);
00305                 MEM_freeN(rigg->editbones);
00306         }
00307         
00308         MEM_freeN(rg);
00309 }
00310 
00311 /************************************* ALLOCATORS ******************************************************/
00312 
00313 static RigGraph *newRigGraph(void)
00314 {
00315         RigGraph *rg;
00316         int totthread;
00317         
00318         rg = MEM_callocN(sizeof(RigGraph), "rig graph");
00319         
00320         rg->head = NULL;
00321         
00322         rg->bones_map = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "newRigGraph bones gh");
00323         rg->controls_map = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "newRigGraph cont gh");
00324         
00325         rg->free_arc = RIG_freeRigArc;
00326         rg->free_node = NULL;
00327         
00328 #ifdef USE_THREADS
00329 //      if(G.scene->r.mode & R_FIXED_THREADS)
00330 //      {
00331 //              totthread = G.scene->r.threads;
00332 //      }
00333 //      else
00334 //      {
00335                 totthread = BLI_system_thread_count();
00336 //      }
00337         
00338         rg->worker = BLI_create_worker(exec_retargetArctoArc, totthread, 20); /* fix number of threads */
00339 #endif
00340         
00341         return rg;
00342 }
00343 
00344 static RigArc *newRigArc(RigGraph *rg)
00345 {
00346         RigArc *arc;
00347         
00348         arc = MEM_callocN(sizeof(RigArc), "rig arc");
00349         arc->count = 0;
00350         BLI_addtail(&rg->arcs, arc);
00351         
00352         return arc;
00353 }
00354 
00355 static RigControl *newRigControl(RigGraph *rg)
00356 {
00357         RigControl *ctrl;
00358         
00359         ctrl = MEM_callocN(sizeof(RigControl), "rig control");
00360         
00361         BLI_addtail(&rg->controls, ctrl);
00362         
00363         return ctrl;
00364 }
00365 
00366 static RigNode *newRigNodeHead(RigGraph *rg, RigArc *arc, float p[3])
00367 {
00368         RigNode *node;
00369         node = MEM_callocN(sizeof(RigNode), "rig node");
00370         BLI_addtail(&rg->nodes, node);
00371 
00372         VECCOPY(node->p, p);
00373         node->degree = 1;
00374         node->arcs = NULL;
00375         
00376         arc->head = node;
00377         
00378         return node;
00379 }
00380 
00381 static void addRigNodeHead(RigGraph *UNUSED(rg), RigArc *arc, RigNode *node)
00382 {
00383         node->degree++;
00384 
00385         arc->head = node;
00386 }
00387 
00388 static RigNode *newRigNode(RigGraph *rg, float p[3])
00389 {
00390         RigNode *node;
00391         node = MEM_callocN(sizeof(RigNode), "rig node");
00392         BLI_addtail(&rg->nodes, node);
00393 
00394         VECCOPY(node->p, p);
00395         node->degree = 0;
00396         node->arcs = NULL;
00397         
00398         return node;
00399 }
00400 
00401 static RigNode *newRigNodeTail(RigGraph *rg, RigArc *arc, float p[3])
00402 {
00403         RigNode *node = newRigNode(rg, p);
00404         
00405         node->degree = 1;
00406         arc->tail = node;
00407 
00408         return node;
00409 }
00410 
00411 static void RIG_appendEdgeToArc(RigArc *arc, RigEdge *edge)
00412 {
00413         BLI_addtail(&arc->edges, edge);
00414 
00415         if (edge->prev == NULL)
00416         {
00417                 VECCOPY(edge->head, arc->head->p);
00418         }
00419         else
00420         {
00421                 RigEdge *last_edge = edge->prev;
00422                 VECCOPY(edge->head, last_edge->tail);
00423                 RIG_calculateEdgeAngles(last_edge, edge);
00424         }
00425         
00426         edge->length = len_v3v3(edge->head, edge->tail);
00427         
00428         arc->length += edge->length;
00429         
00430         arc->count += 1;
00431 }
00432 
00433 static void RIG_addEdgeToArc(RigArc *arc, float tail[3], EditBone *bone)
00434 {
00435         RigEdge *edge;
00436 
00437         edge = MEM_callocN(sizeof(RigEdge), "rig edge");
00438 
00439         VECCOPY(edge->tail, tail);
00440         edge->bone = bone;
00441         
00442         if (bone)
00443         {
00444                 getEditBoneRollUpAxis(bone, bone->roll, edge->up_axis);
00445         }
00446         
00447         RIG_appendEdgeToArc(arc, edge);
00448 }
00449 /************************************** CLONING TEMPLATES **********************************************/
00450 
00451 static void renameTemplateBone(char *name, char *template_name, ListBase *editbones, char *side_string, char *num_string)
00452 {
00453         int i, j;
00454         
00455         for (i = 0, j = 0; template_name[i] != '\0' && i < 31 && j < 31; i++)
00456         {
00457                 if (template_name[i] == '&')
00458                 {
00459                         if (template_name[i+1] == 'S' || template_name[i+1] == 's')
00460                         {
00461                                 j += sprintf(name + j, "%s", side_string);
00462                                 i++;
00463                         }
00464                         else if (template_name[i+1] == 'N' || template_name[i+1] == 'n')
00465                         {
00466                                 j += sprintf(name + j, "%s", num_string);
00467                                 i++;
00468                         }
00469                         else
00470                         {
00471                                 name[j] = template_name[i];
00472                                 j++;
00473                         }
00474                 }
00475                 else
00476                 {
00477                         name[j] = template_name[i];
00478                         j++;
00479                 }
00480         }
00481         
00482         name[j] = '\0';
00483         
00484         unique_editbone_name(editbones, name, NULL);
00485 }
00486 
00487 static RigControl *cloneControl(RigGraph *rg, RigGraph *src_rg, RigControl *src_ctrl, GHash *ptr_hash, char *side_string, char *num_string)
00488 {
00489         RigControl *ctrl;
00490         char name[32];
00491         
00492         ctrl = newRigControl(rg);
00493         
00494         VECCOPY(ctrl->head, src_ctrl->head);
00495         VECCOPY(ctrl->tail, src_ctrl->tail);
00496         VECCOPY(ctrl->up_axis, src_ctrl->up_axis);
00497         VECCOPY(ctrl->offset, src_ctrl->offset);
00498         
00499         ctrl->tail_mode = src_ctrl->tail_mode;
00500         ctrl->flag = src_ctrl->flag;
00501 
00502         renameTemplateBone(name, src_ctrl->bone->name, rg->editbones, side_string, num_string);
00503         ctrl->bone = duplicateEditBoneObjects(src_ctrl->bone, name, rg->editbones, src_rg->ob, rg->ob);
00504         ctrl->bone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL);
00505         BLI_ghash_insert(ptr_hash, src_ctrl->bone, ctrl->bone);
00506         
00507         ctrl->link = src_ctrl->link;
00508         ctrl->link_tail = src_ctrl->link_tail;
00509         
00510         return ctrl;
00511 }
00512 
00513 static RigArc *cloneArc(RigGraph *rg, RigGraph *src_rg, RigArc *src_arc, GHash *ptr_hash, char *side_string, char *num_string)
00514 {
00515         RigEdge *src_edge;
00516         RigArc  *arc;
00517         
00518         arc = newRigArc(rg);
00519         
00520         arc->head = BLI_ghash_lookup(ptr_hash, src_arc->head);
00521         arc->tail = BLI_ghash_lookup(ptr_hash, src_arc->tail);
00522         
00523         arc->head->degree++;
00524         arc->tail->degree++;
00525         
00526         arc->length = src_arc->length;
00527 
00528         arc->count = src_arc->count;
00529         
00530         for (src_edge = src_arc->edges.first; src_edge; src_edge = src_edge->next)
00531         {
00532                 RigEdge *edge;
00533         
00534                 edge = MEM_callocN(sizeof(RigEdge), "rig edge");
00535 
00536                 VECCOPY(edge->head, src_edge->head);
00537                 VECCOPY(edge->tail, src_edge->tail);
00538                 VECCOPY(edge->up_axis, src_edge->up_axis);
00539                 
00540                 edge->length = src_edge->length;
00541                 edge->angle = src_edge->angle;
00542                 edge->up_angle = src_edge->up_angle;
00543                 
00544                 if (src_edge->bone != NULL)
00545                 {
00546                         char name[32];
00547                         renameTemplateBone(name, src_edge->bone->name, rg->editbones, side_string, num_string);
00548                         edge->bone = duplicateEditBoneObjects(src_edge->bone, name, rg->editbones, src_rg->ob, rg->ob);
00549                         edge->bone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL);
00550                         BLI_ghash_insert(ptr_hash, src_edge->bone, edge->bone);
00551                 }
00552 
00553                 BLI_addtail(&arc->edges, edge);
00554         }
00555         
00556         return arc;
00557 }
00558 
00559 static RigGraph *cloneRigGraph(RigGraph *src, ListBase *editbones, Object *ob, char *side_string, char *num_string)
00560 {
00561         GHash   *ptr_hash;      
00562         RigNode *node;
00563         RigArc  *arc;
00564         RigControl *ctrl;
00565         RigGraph *rg;
00566         
00567         ptr_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "cloneRigGraph gh");
00568 
00569         rg = newRigGraph();
00570         
00571         rg->ob = ob;
00572         rg->editbones = editbones;
00573         
00574         preEditBoneDuplicate(rg->editbones); /* prime bones for duplication */
00575         preEditBoneDuplicate(src->editbones); /* prime bones for duplication */
00576         
00577         /* Clone nodes */
00578         for (node = src->nodes.first; node; node = node->next)
00579         {
00580                 RigNode *cloned_node = newRigNode(rg, node->p);
00581                 BLI_ghash_insert(ptr_hash, node, cloned_node);
00582         }
00583         
00584         rg->head = BLI_ghash_lookup(ptr_hash, src->head);
00585         
00586         /* Clone arcs */
00587         for (arc = src->arcs.first; arc; arc = arc->next)
00588         {
00589                 cloneArc(rg, src, arc, ptr_hash, side_string, num_string);
00590         }
00591         
00592         /* Clone controls */
00593         for (ctrl = src->controls.first; ctrl; ctrl = ctrl->next)
00594         {
00595                 cloneControl(rg, src, ctrl, ptr_hash, side_string, num_string);
00596         }
00597         
00598         /* Relink bones properly */
00599         for (arc = rg->arcs.first; arc; arc = arc->next)
00600         {
00601                 RigEdge *edge;
00602                 
00603                 for (edge = arc->edges.first; edge; edge = edge->next)
00604                 {
00605                         if (edge->bone != NULL)
00606                         {
00607                                 EditBone *bone;
00608                                 
00609                                 updateDuplicateSubtargetObjects(edge->bone, src->editbones, src->ob, rg->ob);
00610 
00611                                 if (edge->bone->parent)
00612                                 {                               
00613                                         bone = BLI_ghash_lookup(ptr_hash, edge->bone->parent);
00614                 
00615                                         if (bone != NULL)
00616                                         {
00617                                                 edge->bone->parent = bone;
00618                                         }
00619                                         else
00620                                         {
00621                                                 /* disconnect since parent isn't cloned
00622                                                  * this will only happen when cloning from selected bones 
00623                                                  * */
00624                                                 edge->bone->flag &= ~BONE_CONNECTED;
00625                                         }
00626                                 }
00627                         }
00628                 }
00629         }
00630         
00631         for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next)
00632         {
00633                 EditBone *bone;
00634                 
00635                 updateDuplicateSubtargetObjects(ctrl->bone, src->editbones, src->ob, rg->ob);
00636 
00637                 if (ctrl->bone->parent)
00638                 {
00639                         bone = BLI_ghash_lookup(ptr_hash, ctrl->bone->parent);
00640                         
00641                         if (bone != NULL)
00642                         {
00643                                 ctrl->bone->parent = bone;
00644                         }
00645                         else
00646                         {
00647                                 /* disconnect since parent isn't cloned
00648                                  * this will only happen when cloning from selected bones 
00649                                  * */
00650                                 ctrl->bone->flag &= ~BONE_CONNECTED;
00651                         }
00652                 }
00653 
00654                 ctrl->link = BLI_ghash_lookup(ptr_hash, ctrl->link);
00655                 ctrl->link_tail = BLI_ghash_lookup(ptr_hash, ctrl->link_tail);
00656         }
00657         
00658         BLI_ghash_free(ptr_hash, NULL, NULL);
00659         
00660         return rg;
00661 }
00662 
00663 
00664 /*******************************************************************************************************/
00665 
00666 static void RIG_calculateEdgeAngles(RigEdge *edge_first, RigEdge *edge_second)
00667 {
00668         float vec_first[3], vec_second[3];
00669         
00670         sub_v3_v3v3(vec_first, edge_first->tail, edge_first->head); 
00671         sub_v3_v3v3(vec_second, edge_second->tail, edge_second->head);
00672 
00673         normalize_v3(vec_first);
00674         normalize_v3(vec_second);
00675         
00676         edge_first->angle = angle_normalized_v3v3(vec_first, vec_second);
00677         
00678         if (edge_second->bone != NULL)
00679         {
00680                 float normal[3];
00681 
00682                 cross_v3_v3v3(normal, vec_first, vec_second);
00683                 normalize_v3(normal);
00684 
00685                 edge_second->up_angle = angle_normalized_v3v3(normal, edge_second->up_axis);
00686         }
00687 }
00688 
00689 /************************************ CONTROL BONES ****************************************************/
00690 
00691 static void RIG_addControlBone(RigGraph *rg, EditBone *bone)
00692 {
00693         RigControl *ctrl = newRigControl(rg);
00694         ctrl->bone = bone;
00695         VECCOPY(ctrl->head, bone->head);
00696         VECCOPY(ctrl->tail, bone->tail);
00697         getEditBoneRollUpAxis(bone, bone->roll, ctrl->up_axis);
00698         ctrl->tail_mode = TL_NONE;
00699         
00700         BLI_ghash_insert(rg->controls_map, bone->name, ctrl);
00701 }
00702 
00703 static int RIG_parentControl(RigControl *ctrl, EditBone *link)
00704 {
00705         if (link)
00706         {
00707                 float offset[3];
00708                 int flag = 0;
00709                 
00710                 sub_v3_v3v3(offset, ctrl->bone->head, link->head);
00711 
00712                 /* if root matches, check for direction too */          
00713                 if (dot_v3v3(offset, offset) < 0.0001)
00714                 {
00715                         float vbone[3], vparent[3];
00716                         
00717                         flag |= RIG_CTRL_FIT_ROOT;
00718                         
00719                         sub_v3_v3v3(vbone, ctrl->bone->tail, ctrl->bone->head);
00720                         sub_v3_v3v3(vparent, link->tail, link->head);
00721                         
00722                         /* test for opposite direction */
00723                         if (dot_v3v3(vbone, vparent) > 0)
00724                         {
00725                                 float nor[3];
00726                                 float len;
00727                                 
00728                                 cross_v3_v3v3(nor, vbone, vparent);
00729                                 
00730                                 len = dot_v3v3(nor, nor);
00731                                 if (len < 0.0001)
00732                                 {
00733                                         flag |= RIG_CTRL_FIT_BONE;
00734                                 }
00735                         }
00736                 }
00737                 
00738                 /* Bail out if old one is automatically better */
00739                 if (flag < ctrl->flag)
00740                 {
00741                         return 0;
00742                 }
00743                 
00744                 /* if there's already a link
00745                  *      overwrite only if new link is higher in the chain */
00746                 if (ctrl->link && flag == ctrl->flag)
00747                 {
00748                         EditBone *bone = NULL;
00749                         
00750                         for (bone = ctrl->link; bone; bone = bone->parent)
00751                         {
00752                                 /* if link is in the chain, break and use that one */
00753                                 if (bone == link)
00754                                 {
00755                                         break;
00756                                 }
00757                         }
00758                         
00759                         /* not in chain, don't update link */
00760                         if (bone == NULL)
00761                         {
00762                                 return 0;
00763                         }
00764                 }
00765                 
00766                 
00767                 ctrl->link = link;
00768                 ctrl->flag = flag;
00769                 
00770                 VECCOPY(ctrl->offset, offset);
00771                 
00772                 return 1;
00773         }
00774         
00775         return 0;
00776 }
00777 
00778 static void RIG_reconnectControlBones(RigGraph *rg)
00779 {
00780         RigControl *ctrl;
00781         int change = 1;
00782         
00783         /* first pass, link to deform bones */
00784         for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next)
00785         {
00786                 bPoseChannel *pchan;
00787                 bConstraint *con;
00788                 int found = 0;
00789                 
00790                 /* DO SOME MAGIC HERE */
00791                 for (pchan= rg->ob->pose->chanbase.first; pchan; pchan= pchan->next)
00792                 {
00793                         for (con= pchan->constraints.first; con; con= con->next) 
00794                         {
00795                                 bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
00796                                 ListBase targets = {NULL, NULL};
00797                                 bConstraintTarget *ct;
00798                                 
00799                                 /* constraint targets */
00800                                 if (cti && cti->get_constraint_targets)
00801                                 {
00802                                         int target_index;
00803                                         
00804                                         cti->get_constraint_targets(con, &targets);
00805                                         
00806                                         for (target_index = 0, ct= targets.first; ct; target_index++, ct= ct->next)
00807                                         {
00808                                                 if ((ct->tar == rg->ob) && strcmp(ct->subtarget, ctrl->bone->name) == 0)
00809                                                 {
00810                                                         /* SET bone link to bone corresponding to pchan */
00811                                                         EditBone *link = BLI_ghash_lookup(rg->bones_map, pchan->name);
00812                                                         
00813                                                         /* Making sure bone is in this armature */
00814                                                         if (link != NULL)
00815                                                         {
00816                                                                 /* for pole targets, link to parent bone instead, if possible */
00817                                                                 if (con->type == CONSTRAINT_TYPE_KINEMATIC && target_index == 1)
00818                                                                 {
00819                                                                         if (link->parent && BLI_ghash_haskey(rg->bones_map, link->parent->name))
00820                                                                         {
00821                                                                                 link = link->parent;
00822                                                                         }
00823                                                                 }
00824                                                                 
00825                                                                 found = RIG_parentControl(ctrl, link);
00826                                                         }
00827                                                 }
00828                                         }
00829                                         
00830                                         if (cti->flush_constraint_targets)
00831                                                 cti->flush_constraint_targets(con, &targets, 0);
00832                                 }
00833                         }
00834                 }
00835 
00836                 /* if not found yet, check parent */
00837                 if (found == 0)
00838                 {               
00839                         if (ctrl->bone->parent)
00840                         {
00841                                 /* make sure parent is a deforming bone
00842                                  * NULL if not
00843                                  *  */
00844                                 EditBone *link = BLI_ghash_lookup(rg->bones_map, ctrl->bone->parent->name);
00845                                 
00846                                 found = RIG_parentControl(ctrl, link);
00847                         }
00848                         
00849                         /* check if bone is not superposed on another one */
00850                         {
00851                                 RigArc *arc;
00852                                 RigArc *best_arc = NULL;
00853                                 EditBone *link = NULL;
00854                                 
00855                                 for (arc = rg->arcs.first; arc; arc = arc->next)
00856                                 {
00857                                         RigEdge *edge;
00858                                         for (edge = arc->edges.first; edge; edge = edge->next)
00859                                         {
00860                                                 if (edge->bone)
00861                                                 {
00862                                                         int fit = 0;
00863                                                         
00864                                                         fit = len_v3v3(ctrl->bone->head, edge->bone->head) < 0.0001;
00865                                                         fit = fit || len_v3v3(ctrl->bone->tail, edge->bone->tail) < 0.0001;
00866                                                         
00867                                                         if (fit)
00868                                                         {
00869                                                                 /* pick the bone on the arc with the lowest symmetry level
00870                                                                  * means you connect control to the trunk of the skeleton */
00871                                                                 if (best_arc == NULL || arc->symmetry_level < best_arc->symmetry_level)
00872                                                                 {
00873                                                                         best_arc = arc;
00874                                                                         link = edge->bone;
00875                                                                 }
00876                                                         }
00877                                                 }
00878                                         }
00879                                 }
00880                                 
00881                                 found = RIG_parentControl(ctrl, link);
00882                         }
00883                 }
00884                 
00885                 /* if not found yet, check child */             
00886                 if (found == 0)
00887                 {
00888                         RigArc *arc;
00889                         RigArc *best_arc = NULL;
00890                         EditBone *link = NULL;
00891                         
00892                         for (arc = rg->arcs.first; arc; arc = arc->next)
00893                         {
00894                                 RigEdge *edge;
00895                                 for (edge = arc->edges.first; edge; edge = edge->next)
00896                                 {
00897                                         if (edge->bone && edge->bone->parent == ctrl->bone)
00898                                         {
00899                                                 /* pick the bone on the arc with the lowest symmetry level
00900                                                  * means you connect control to the trunk of the skeleton */
00901                                                 if (best_arc == NULL || arc->symmetry_level < best_arc->symmetry_level)
00902                                                 {
00903                                                         best_arc = arc;
00904                                                         link = edge->bone;
00905                                                 }
00906                                         }
00907                                 }
00908                         }
00909                         
00910                         found = RIG_parentControl(ctrl, link);
00911                 }
00912 
00913         }
00914         
00915         
00916         /* second pass, make chains in control bones */
00917         while (change)
00918         {
00919                 change = 0;
00920                 
00921                 for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next)
00922                 {
00923                         /* if control is not linked yet */
00924                         if (ctrl->link == NULL)
00925                         {
00926                                 bPoseChannel *pchan;
00927                                 bConstraint *con;
00928                                 RigControl *ctrl_parent = NULL;
00929                                 RigControl *ctrl_child;
00930                                 int found = 0;
00931 
00932                                 if (ctrl->bone->parent)
00933                                 {
00934                                         ctrl_parent = BLI_ghash_lookup(rg->controls_map, ctrl->bone->parent->name);
00935                                 }
00936 
00937                                 /* check constraints first */
00938                                 
00939                                 /* DO SOME MAGIC HERE */
00940                                 for (pchan= rg->ob->pose->chanbase.first; pchan; pchan= pchan->next)
00941                                 {
00942                                         for (con= pchan->constraints.first; con; con= con->next) 
00943                                         {
00944                                                 bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
00945                                                 ListBase targets = {NULL, NULL};
00946                                                 bConstraintTarget *ct;
00947                                                 
00948                                                 /* constraint targets */
00949                                                 if (cti && cti->get_constraint_targets)
00950                                                 {
00951                                                         cti->get_constraint_targets(con, &targets);
00952                                                         
00953                                                         for (ct= targets.first; ct; ct= ct->next)
00954                                                         {
00955                                                                 if ((ct->tar == rg->ob) && strcmp(ct->subtarget, ctrl->bone->name) == 0)
00956                                                                 {
00957                                                                         /* SET bone link to ctrl corresponding to pchan */
00958                                                                         RigControl *link = BLI_ghash_lookup(rg->controls_map, pchan->name);
00959 
00960                                                                         /* if owner is a control bone, link with it */                                                                  
00961                                                                         if (link && link->link)
00962                                                                         {
00963                                                                                 RIG_parentControl(ctrl, link->bone);
00964                                                                                 found = 1;
00965                                                                                 break;
00966                                                                         }
00967                                                                 }
00968                                                         }
00969                                                         
00970                                                         if (cti->flush_constraint_targets)
00971                                                                 cti->flush_constraint_targets(con, &targets, 0);
00972                                                 }
00973                                         }
00974                                 }                       
00975 
00976                                 if (found == 0)
00977                                 {
00978                                         /* check if parent is already linked */
00979                                         if (ctrl_parent && ctrl_parent->link)
00980                                         {
00981                                                 RIG_parentControl(ctrl, ctrl_parent->bone);
00982                                                 change = 1;
00983                                         }
00984                                         else
00985                                         {
00986                                                 /* check childs */
00987                                                 for (ctrl_child = rg->controls.first; ctrl_child; ctrl_child = ctrl_child->next)
00988                                                 {
00989                                                         /* if a child is linked, link to that one */
00990                                                         if (ctrl_child->link && ctrl_child->bone->parent == ctrl->bone)
00991                                                         {
00992                                                                 RIG_parentControl(ctrl, ctrl_child->bone);
00993                                                                 change = 1;
00994                                                                 break;
00995                                                         }
00996                                                 }
00997                                         }
00998                                 }
00999                         }
01000                 }
01001         }
01002         
01003         /* third pass, link control tails */
01004         for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next)
01005         {
01006                 /* fit bone already means full match, so skip those */
01007                 if ((ctrl->flag & RIG_CTRL_FIT_BONE) == 0)
01008                 {
01009                         GHashIterator ghi;
01010                         
01011                         /* look on deform bones first */
01012                         BLI_ghashIterator_init(&ghi, rg->bones_map);
01013                         
01014                         for( ; !BLI_ghashIterator_isDone(&ghi); BLI_ghashIterator_step(&ghi))
01015                         {
01016                                 EditBone *bone = (EditBone*)BLI_ghashIterator_getValue(&ghi);
01017                                 
01018                                 /* don't link with parent */
01019                                 if (bone->parent != ctrl->bone)
01020                                 {
01021                                         if (len_v3v3(ctrl->bone->tail, bone->head) < 0.01)
01022                                         {
01023                                                 ctrl->tail_mode = TL_HEAD;
01024                                                 ctrl->link_tail = bone;
01025                                                 break;
01026                                         }
01027                                         else if (len_v3v3(ctrl->bone->tail, bone->tail) < 0.01)
01028                                         {
01029                                                 ctrl->tail_mode = TL_TAIL;
01030                                                 ctrl->link_tail = bone;
01031                                                 break;
01032                                         }
01033                                 }
01034                         }
01035                         
01036                         /* if we haven't found one yet, look in control bones */
01037                         if (ctrl->tail_mode == TL_NONE)
01038                         {
01039                         }
01040                 }
01041         }
01042         
01043 }
01044 
01045 /*******************************************************************************************************/
01046 
01047 static void RIG_joinArcs(RigGraph *rg, RigNode *node, RigArc *joined_arc1, RigArc *joined_arc2)
01048 {
01049         RigEdge *edge, *next_edge;
01050         
01051         /* ignore cases where joint is at start or end */
01052         if (joined_arc1->head == joined_arc2->head || joined_arc1->tail == joined_arc2->tail)
01053         {
01054                 return;
01055         }
01056         
01057         /* swap arcs to make sure arc1 is before arc2 */
01058         if (joined_arc1->head == joined_arc2->tail)
01059         {
01060                 RigArc *tmp = joined_arc1;
01061                 joined_arc1 = joined_arc2;
01062                 joined_arc2 = tmp;
01063         }
01064         
01065         for (edge = joined_arc2->edges.first; edge; edge = next_edge)
01066         {
01067                 next_edge = edge->next;
01068                 
01069                 RIG_appendEdgeToArc(joined_arc1, edge);
01070         }
01071         
01072         joined_arc1->tail = joined_arc2->tail;
01073         
01074         joined_arc2->edges.first = joined_arc2->edges.last = NULL;
01075         
01076         BLI_removeArc((BGraph*)rg, (BArc*)joined_arc2);
01077         
01078         BLI_removeNode((BGraph*)rg, (BNode*)node);
01079 }
01080 
01081 static void RIG_removeNormalNodes(RigGraph *rg)
01082 {
01083         RigNode *node, *next_node;
01084         
01085         for (node = rg->nodes.first; node; node = next_node)
01086         {
01087                 next_node = node->next;
01088                 
01089                 if (node->degree == 2)
01090                 {
01091                         RigArc *arc, *joined_arc1 = NULL, *joined_arc2 = NULL;
01092                         
01093                         for (arc = rg->arcs.first; arc; arc = arc->next)
01094                         {
01095                                 if (arc->head == node || arc->tail == node)
01096                                 {
01097                                         if (joined_arc1 == NULL)
01098                                         {
01099                                                 joined_arc1 = arc;
01100                                         }
01101                                         else
01102                                         {
01103                                                 joined_arc2 = arc;
01104                                                 break;
01105                                         }
01106                                 }
01107                         }
01108                         
01109                         RIG_joinArcs(rg, node, joined_arc1, joined_arc2);
01110                 }
01111         }
01112 }
01113 
01114 static void RIG_removeUneededOffsets(RigGraph *rg)
01115 {
01116         RigArc *arc;
01117         
01118         for (arc = rg->arcs.first; arc; arc = arc->next)
01119         {
01120                 RigEdge *first_edge, *last_edge;
01121                 
01122                 first_edge = arc->edges.first;
01123                 last_edge = arc->edges.last;
01124                 
01125                 if (first_edge->bone == NULL)
01126                 {
01127                         if (first_edge->bone == NULL && len_v3v3(first_edge->tail, arc->head->p) <= 0.001)
01128                         {
01129                                 BLI_remlink(&arc->edges, first_edge);
01130                                 MEM_freeN(first_edge);
01131                         }
01132                         else if (arc->head->degree == 1)
01133                         {
01134                                 RigNode *new_node = (RigNode*)BLI_FindNodeByPosition((BGraph*)rg, first_edge->tail, 0.001);
01135                                 
01136                                 if (new_node)
01137                                 {
01138                                         BLI_remlink(&arc->edges, first_edge);
01139                                         MEM_freeN(first_edge);
01140                                         BLI_replaceNodeInArc((BGraph*)rg, (BArc*)arc, (BNode*)new_node, (BNode*)arc->head);
01141                                 }
01142                                 else
01143                                 {
01144                                         RigEdge *next_edge = first_edge->next;
01145         
01146                                         if (next_edge)
01147                                         {
01148                                                 BLI_remlink(&arc->edges, first_edge);
01149                                                 MEM_freeN(first_edge);
01150                                                 
01151                                                 VECCOPY(arc->head->p, next_edge->head);
01152                                         }
01153                                 }
01154                         }
01155                         else
01156                         {
01157                                 /* check if all arc connected start with a null edge */
01158                                 RigArc *other_arc;
01159                                 for (other_arc = rg->arcs.first; other_arc; other_arc = other_arc->next)
01160                                 {
01161                                         if (other_arc != arc)
01162                                         {
01163                                                 RigEdge *test_edge;
01164                                                 if (other_arc->head == arc->head)
01165                                                 {
01166                                                         test_edge = other_arc->edges.first;
01167                                                         
01168                                                         if (test_edge->bone != NULL)
01169                                                         {
01170                                                                 break;
01171                                                         }
01172                                                 }
01173                                                 else if (other_arc->tail == arc->head)
01174                                                 {
01175                                                         test_edge = other_arc->edges.last;
01176                                                         
01177                                                         if (test_edge->bone != NULL)
01178                                                         {
01179                                                                 break;
01180                                                         }
01181                                                 }
01182                                         }
01183                                 }
01184                                 
01185                                 if (other_arc == NULL)
01186                                 {
01187                                         RigNode *new_node = (RigNode*)BLI_FindNodeByPosition((BGraph*)rg, first_edge->tail, 0.001);
01188                                         
01189                                         if (new_node)
01190                                         {
01191                                                 /* remove null edge in other arcs too */
01192                                                 for (other_arc = rg->arcs.first; other_arc; other_arc = other_arc->next)
01193                                                 {
01194                                                         if (other_arc != arc)
01195                                                         {
01196                                                                 RigEdge *test_edge;
01197                                                                 if (other_arc->head == arc->head)
01198                                                                 {
01199                                                                         BLI_replaceNodeInArc((BGraph*)rg, (BArc*)other_arc, (BNode*)new_node, (BNode*)other_arc->head);
01200                                                                         test_edge = other_arc->edges.first;
01201                                                                         BLI_remlink(&other_arc->edges, test_edge);
01202                                                                         MEM_freeN(test_edge);
01203                                                                 }
01204                                                                 else if (other_arc->tail == arc->head)
01205                                                                 {
01206                                                                         BLI_replaceNodeInArc((BGraph*)rg, (BArc*)other_arc, (BNode*)new_node, (BNode*)other_arc->tail);
01207                                                                         test_edge = other_arc->edges.last;
01208                                                                         BLI_remlink(&other_arc->edges, test_edge);
01209                                                                         MEM_freeN(test_edge);
01210                                                                 }
01211                                                         }
01212                                                 }
01213                                                 
01214                                                 BLI_remlink(&arc->edges, first_edge);
01215                                                 MEM_freeN(first_edge);
01216                                                 BLI_replaceNodeInArc((BGraph*)rg, (BArc*)arc, (BNode*)new_node, (BNode*)arc->head);
01217                                         }
01218                                         else
01219                                         {
01220                                                 RigEdge *next_edge = first_edge->next;
01221                 
01222                                                 if (next_edge)
01223                                                 {
01224                                                         BLI_remlink(&arc->edges, first_edge);
01225                                                         MEM_freeN(first_edge);
01226                                                         
01227                                                         VECCOPY(arc->head->p, next_edge->head);
01228                                                         
01229                                                         /* remove null edge in other arcs too */
01230                                                         for (other_arc = rg->arcs.first; other_arc; other_arc = other_arc->next)
01231                                                         {
01232                                                                 if (other_arc != arc)
01233                                                                 {
01234                                                                         RigEdge *test_edge;
01235                                                                         if (other_arc->head == arc->head)
01236                                                                         {
01237                                                                                 test_edge = other_arc->edges.first;
01238                                                                                 BLI_remlink(&other_arc->edges, test_edge);
01239                                                                                 MEM_freeN(test_edge);
01240                                                                         }
01241                                                                         else if (other_arc->tail == arc->head)
01242                                                                         {
01243                                                                                 test_edge = other_arc->edges.last;
01244                                                                                 BLI_remlink(&other_arc->edges, test_edge);
01245                                                                                 MEM_freeN(test_edge);
01246                                                                         }
01247                                                                 }
01248                                                         }
01249                                                 }
01250                                         }
01251                                 }
01252                         }
01253                 }
01254                 
01255                 if (last_edge->bone == NULL)
01256                 {
01257                         if (len_v3v3(last_edge->head, arc->tail->p) <= 0.001)
01258                         {
01259                                 BLI_remlink(&arc->edges, last_edge);
01260                                 MEM_freeN(last_edge);
01261                         }
01262                         else if (arc->tail->degree == 1)
01263                         {
01264                                 RigNode *new_node = (RigNode*)BLI_FindNodeByPosition((BGraph*)rg, last_edge->head, 0.001);
01265                                 
01266                                 if (new_node)
01267                                 {
01268                                         RigEdge *previous_edge = last_edge->prev;
01269                                         
01270                                         BLI_remlink(&arc->edges, last_edge);
01271                                         MEM_freeN(last_edge);
01272                                         BLI_replaceNodeInArc((BGraph*)rg, (BArc*)arc, (BNode*)new_node, (BNode*)arc->tail);
01273                                         
01274                                         /* set previous angle to 0, since there's no following edges */
01275                                         if (previous_edge)
01276                                         {
01277                                                 previous_edge->angle = 0;
01278                                         }
01279                                 }
01280                                 else
01281                                 {
01282                                         RigEdge *previous_edge = last_edge->prev;
01283         
01284                                         if (previous_edge)
01285                                         {
01286                                                 BLI_remlink(&arc->edges, last_edge);
01287                                                 MEM_freeN(last_edge);
01288                                                 
01289                                                 VECCOPY(arc->tail->p, previous_edge->tail);
01290                                                 previous_edge->angle = 0;
01291                                         }
01292                                 }
01293                         }
01294                 }
01295         }
01296 }
01297 
01298 static void RIG_arcFromBoneChain(RigGraph *rg, ListBase *list, EditBone *root_bone, RigNode *starting_node, int selected)
01299 {
01300         EditBone *bone, *last_bone = root_bone;
01301         RigArc *arc = NULL;
01302         int contain_head = 0;
01303         
01304         for(bone = root_bone; bone; bone = nextEditBoneChild(list, bone, 0))
01305         {
01306                 int nb_children;
01307                 
01308                 if (selected == 0 || (bone->flag & BONE_SELECTED))
01309                 { 
01310                         if ((bone->flag & BONE_NO_DEFORM) == 0)
01311                         {
01312                                 BLI_ghash_insert(rg->bones_map, bone->name, bone);
01313                         
01314                                 if (arc == NULL)
01315                                 {
01316                                         arc = newRigArc(rg);
01317                                         
01318                                         if (starting_node == NULL)
01319                                         {
01320                                                 starting_node = newRigNodeHead(rg, arc, root_bone->head);
01321                                         }
01322                                         else
01323                                         {
01324                                                 addRigNodeHead(rg, arc, starting_node);
01325                                         }
01326                                 }
01327                                 
01328                                 if (bone->parent && (bone->flag & BONE_CONNECTED) == 0)
01329                                 {
01330                                         RIG_addEdgeToArc(arc, bone->head, NULL);
01331                                 }
01332                                 
01333                                 RIG_addEdgeToArc(arc, bone->tail, bone);
01334                                 
01335                                 last_bone = bone;
01336                                 
01337                                 if (strcmp(bone->name, "head") == 0)
01338                                 {
01339                                         contain_head = 1;
01340                                 }
01341                         }
01342                         else if ((bone->flag & BONE_EDITMODE_LOCKED) == 0) /* ignore locked bones */
01343                         {
01344                                 RIG_addControlBone(rg, bone);
01345                         }
01346                 }
01347                 
01348                 nb_children = countEditBoneChildren(list, bone);
01349                 if (nb_children > 1)
01350                 {
01351                         RigNode *end_node = NULL;
01352                         int i;
01353                         
01354                         if (arc != NULL)
01355                         {
01356                                 end_node = newRigNodeTail(rg, arc, bone->tail);
01357                         }
01358                         else
01359                         {
01360                                 end_node = newRigNode(rg, bone->tail);
01361                         }
01362 
01363                         for (i = 0; i < nb_children; i++)
01364                         {
01365                                 root_bone = nextEditBoneChild(list, bone, i);
01366                                 RIG_arcFromBoneChain(rg, list, root_bone, end_node, selected);
01367                         }
01368                         
01369                         /* arc ends here, break */
01370                         break;
01371                 }
01372         }
01373         
01374         /* If the loop exited without forking */
01375         if (arc != NULL && bone == NULL)
01376         {
01377                 newRigNodeTail(rg, arc, last_bone->tail);
01378         }
01379 
01380         if (contain_head)
01381         {
01382                 rg->head = arc->tail;
01383         }
01384 }
01385 
01386 /*******************************************************************************************************/
01387 static void RIG_findHead(RigGraph *rg)
01388 {
01389         if (rg->head == NULL)
01390         {
01391                 if (BLI_countlist(&rg->arcs) == 1)
01392                 {
01393                         RigArc *arc = rg->arcs.first;
01394                         
01395                         rg->head = (RigNode*)arc->head;
01396                 }
01397                 else
01398                 {
01399                         RigArc *arc;
01400                         
01401                         for (arc = rg->arcs.first; arc; arc = arc->next)
01402                         {
01403                                 RigEdge *edge = arc->edges.last;
01404                                 
01405                                 if (edge->bone->flag & (BONE_TIPSEL|BONE_SELECTED))
01406                                 {
01407                                         rg->head = arc->tail;
01408                                         break;
01409                                 }
01410                         }
01411                 }
01412                 
01413                 if (rg->head == NULL)
01414                 {
01415                         rg->head = rg->nodes.first;
01416                 }
01417         }
01418 }
01419 
01420 /*******************************************************************************************************/
01421 
01422 static void RIG_printNode(RigNode *node, const char name[])
01423 {
01424         printf("%s %p %i <%0.3f, %0.3f, %0.3f>\n", name, (void *)node, node->degree, node->p[0], node->p[1], node->p[2]);
01425         
01426         if (node->symmetry_flag & SYM_TOPOLOGICAL)
01427         {
01428                 if (node->symmetry_flag & SYM_AXIAL)
01429                         printf("Symmetry AXIAL\n");
01430                 else if (node->symmetry_flag & SYM_RADIAL)
01431                         printf("Symmetry RADIAL\n");
01432                         
01433                 print_v3("symmetry axis", node->symmetry_axis);
01434         }
01435 }
01436 
01437 void RIG_printArcBones(RigArc *arc)
01438 {
01439         RigEdge *edge;
01440 
01441         for (edge = arc->edges.first; edge; edge = edge->next)
01442         {
01443                 if (edge->bone)
01444                         printf("%s ", edge->bone->name);
01445                 else
01446                         printf("---- ");
01447         }
01448         printf("\n");
01449 }
01450 
01451 static void RIG_printCtrl(RigControl *ctrl, char *indent)
01452 {
01453         char text[128];
01454         
01455         printf("%sBone: %s\n", indent, ctrl->bone->name);
01456         printf("%sLink: %s\n", indent, ctrl->link ? ctrl->link->name : "!NONE!");
01457         
01458         sprintf(text, "%soffset", indent);
01459         print_v3(text, ctrl->offset);
01460         
01461         printf("%sFlag: %i\n", indent, ctrl->flag);
01462 }
01463 
01464 static void RIG_printLinkedCtrl(RigGraph *rg, EditBone *bone, int tabs)
01465 {
01466         RigControl *ctrl;
01467         char indent[64];
01468         char *s = indent;
01469         int i;
01470         
01471         for (i = 0; i < tabs; i++)
01472         {
01473                 s[0] = '\t';
01474                 s++;
01475         }
01476         s[0] = 0;
01477         
01478         for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next)
01479         {
01480                 if (ctrl->link == bone)
01481                 {
01482                         RIG_printCtrl(ctrl, indent);
01483                         RIG_printLinkedCtrl(rg, ctrl->bone, tabs + 1);
01484                 }
01485         }
01486 }
01487 
01488 void RIG_printArc(RigGraph *rg, RigArc *arc)
01489 {
01490         RigEdge *edge;
01491 
01492         RIG_printNode((RigNode*)arc->head, "head");
01493 
01494         for (edge = arc->edges.first; edge; edge = edge->next)
01495         {
01496                 printf("\tinner joints %0.3f %0.3f %0.3f\n", edge->tail[0], edge->tail[1], edge->tail[2]);
01497                 printf("\t\tlength %f\n", edge->length);
01498                 printf("\t\tangle %f\n", edge->angle * 180 / M_PI);
01499                 if (edge->bone)
01500                 {
01501                         printf("\t\t%s\n", edge->bone->name);
01502                         RIG_printLinkedCtrl(rg, edge->bone, 3);
01503                 }
01504         }       
01505         printf("symmetry level: %i flag: %i group %i\n", arc->symmetry_level, arc->symmetry_flag, arc->symmetry_group);
01506 
01507         RIG_printNode((RigNode*)arc->tail, "tail");
01508 }
01509 
01510 void RIG_printGraph(RigGraph *rg)
01511 {
01512         RigArc *arc;
01513 
01514         printf("---- ARCS ----\n");
01515         for (arc = rg->arcs.first; arc; arc = arc->next)
01516         {
01517                 RIG_printArc(rg, arc);  
01518                 printf("\n");
01519         }
01520 
01521         if (rg->head)
01522         {
01523                 RIG_printNode(rg->head, "HEAD NODE:");
01524         }
01525         else
01526         {
01527                 printf("HEAD NODE: NONE\n");
01528         }       
01529 }
01530 
01531 /*******************************************************************************************************/
01532 
01533 RigGraph *RIG_graphFromArmature(const bContext *C, Object *ob, bArmature *arm)
01534 {
01535         Object *obedit = CTX_data_edit_object(C);
01536         Scene *scene = CTX_data_scene(C);
01537         EditBone *ebone;
01538         RigGraph *rg;
01539 
01540         rg = newRigGraph();
01541         
01542         if (obedit == ob)
01543         {
01544                 rg->editbones = ((bArmature *)obedit->data)->edbo;
01545         }
01546         else
01547         {
01548                 rg->editbones = MEM_callocN(sizeof(ListBase), "EditBones");
01549                 make_boneList(rg->editbones, &arm->bonebase, NULL, NULL);
01550                 rg->flag |= RIG_FREE_BONELIST;
01551         }
01552         
01553         rg->ob = ob;
01554 
01555         /* Do the rotations */
01556         for (ebone = rg->editbones->first; ebone; ebone=ebone->next){
01557                 if (ebone->parent == NULL)
01558                 {
01559                         RIG_arcFromBoneChain(rg, rg->editbones, ebone, NULL, 0);
01560                 }
01561         }
01562         
01563         BLI_removeDoubleNodes((BGraph*)rg, 0.001);
01564         
01565         RIG_removeNormalNodes(rg);
01566         
01567         RIG_removeUneededOffsets(rg);
01568         
01569         BLI_buildAdjacencyList((BGraph*)rg);
01570         
01571         RIG_findHead(rg);
01572 
01573         BLI_markdownSymmetry((BGraph*)rg, (BNode*)rg->head, scene->toolsettings->skgen_symmetry_limit);
01574         
01575         RIG_reconnectControlBones(rg); /* after symmetry, because we use levels to find best match */
01576         
01577         if (BLI_isGraphCyclic((BGraph*)rg))
01578         {
01579                 printf("armature cyclic\n");
01580         }
01581         
01582         return rg;
01583 }
01584 
01585 static RigGraph *armatureSelectedToGraph(bContext *C, Object *ob, bArmature *arm)
01586 {
01587         Object *obedit = CTX_data_edit_object(C);
01588         Scene *scene = CTX_data_scene(C);
01589         EditBone *ebone;
01590         RigGraph *rg;
01591 
01592         rg = newRigGraph();
01593         
01594         if (obedit == ob)
01595         {
01596                 rg->editbones = arm->edbo;
01597         }
01598         else
01599         {
01600                 rg->editbones = MEM_callocN(sizeof(ListBase), "EditBones");
01601                 make_boneList(rg->editbones, &arm->bonebase, NULL, NULL);
01602                 rg->flag |= RIG_FREE_BONELIST;
01603         }
01604 
01605         rg->ob = ob;
01606 
01607         /* Do the rotations */
01608         for (ebone = rg->editbones->first; ebone; ebone=ebone->next){
01609                 if (ebone->parent == NULL)
01610                 {
01611                         RIG_arcFromBoneChain(rg, rg->editbones, ebone, NULL, 1);
01612                 }
01613         }
01614         
01615         BLI_removeDoubleNodes((BGraph*)rg, 0.001);
01616         
01617         RIG_removeNormalNodes(rg);
01618         
01619         RIG_removeUneededOffsets(rg);
01620         
01621         BLI_buildAdjacencyList((BGraph*)rg);
01622         
01623         RIG_findHead(rg);
01624 
01625         BLI_markdownSymmetry((BGraph*)rg, (BNode*)rg->head, scene->toolsettings->skgen_symmetry_limit);
01626         
01627         RIG_reconnectControlBones(rg); /* after symmetry, because we use levels to find best match */
01628         
01629         if (BLI_isGraphCyclic((BGraph*)rg))
01630         {
01631                 printf("armature cyclic\n");
01632         }
01633         
01634         return rg;
01635 }
01636 /************************************ GENERATING *****************************************************/
01637 
01638 #if 0
01639 static EditBone *add_editbonetolist(char *name, ListBase *list)
01640 {
01641         EditBone *bone= MEM_callocN(sizeof(EditBone), "eBone");
01642         
01643         BLI_strncpy(bone->name, name, sizeof(bone->name));
01644         unique_editbone_name(list, bone->name, NULL);
01645         
01646         BLI_addtail(list, bone);
01647         
01648         bone->flag |= BONE_TIPSEL;
01649         bone->weight= 1.0F;
01650         bone->dist= 0.25F;
01651         bone->xwidth= 0.1;
01652         bone->zwidth= 0.1;
01653         bone->ease1= 1.0;
01654         bone->ease2= 1.0;
01655         bone->rad_head= 0.10;
01656         bone->rad_tail= 0.05;
01657         bone->segments= 1;
01658         bone->layer=  1;//arm->layer;
01659         
01660         return bone;
01661 }
01662 #endif
01663 
01664 #if 0 /* UNUSED */
01665 static void generateMissingArcsFromNode(RigGraph *rigg, ReebNode *node, int multi_level_limit)
01666 {
01667         while (node->multi_level > multi_level_limit && node->link_up)
01668         {
01669                 node = node->link_up;
01670         }
01671         
01672         while (node->multi_level < multi_level_limit && node->link_down)
01673         {
01674                 node = node->link_down;
01675         }
01676         
01677         if (node->multi_level == multi_level_limit)
01678         {
01679                 int i;
01680                 
01681                 for (i = 0; i < node->degree; i++)
01682                 {
01683                         ReebArc *earc = node->arcs[i];
01684                         
01685                         if (earc->flag == ARC_FREE && earc->head == node)
01686                         {
01687                                 ReebNode *other = BIF_otherNodeFromIndex(earc, node);
01688                                 
01689                                 earc->flag = ARC_USED;
01690                                 
01691                                 //generateBonesForArc(rigg, earc, node, other);
01692                                 generateMissingArcsFromNode(rigg, other, multi_level_limit);
01693                         }
01694                 }
01695         }
01696 }
01697 
01698 static void generateMissingArcs(RigGraph *rigg)
01699 {
01700         ReebGraph *reebg;
01701         int multi_level_limit = 5;
01702         
01703         for (reebg = rigg->link_mesh; reebg; reebg = reebg->link_up)
01704         {
01705                 ReebArc *earc;
01706                 
01707                 for (earc = reebg->arcs.first; earc; earc = earc->next)
01708                 {
01709                         if (earc->flag == ARC_USED)
01710                         {
01711                                 generateMissingArcsFromNode(rigg, earc->head, multi_level_limit);
01712                                 generateMissingArcsFromNode(rigg, earc->tail, multi_level_limit);
01713                         }
01714                 }
01715         }
01716 }
01717 #endif
01718 
01719 /************************************ RETARGETTING *****************************************************/
01720 
01721 static void repositionControl(RigGraph *rigg, RigControl *ctrl, float head[3], float tail[3], float qrot[4], float resize);
01722 
01723 static void repositionTailControl(RigGraph *rigg, RigControl *ctrl);
01724 
01725 static void finalizeControl(RigGraph *rigg, RigControl *ctrl, float resize)
01726 {
01727         if ((ctrl->flag & RIG_CTRL_DONE) == RIG_CTRL_DONE)
01728         {
01729                 RigControl *ctrl_child;
01730 
01731 #if 0           
01732                 printf("CTRL: %s LINK: %s", ctrl->bone->name, ctrl->link->name);
01733                 
01734                 if (ctrl->link_tail)
01735                 {
01736                         printf(" TAIL: %s", ctrl->link_tail->name);
01737                 }
01738                 
01739                 printf("\n");
01740 #endif
01741                 
01742                 /* if there was a tail link: apply link, recalc resize factor and qrot */
01743                 if (ctrl->tail_mode != TL_NONE)
01744                 {
01745                         float *tail_vec = NULL;
01746                         float v1[3], v2[3], qtail[4];
01747                         
01748                         if (ctrl->tail_mode == TL_TAIL)
01749                         {
01750                                 tail_vec = ctrl->link_tail->tail;
01751                         }
01752                         else if (ctrl->tail_mode == TL_HEAD)
01753                         {
01754                                 tail_vec = ctrl->link_tail->head;
01755                         }
01756                         
01757                         sub_v3_v3v3(v1, ctrl->bone->tail, ctrl->bone->head);
01758                         sub_v3_v3v3(v2, tail_vec, ctrl->bone->head);
01759                         
01760                         VECCOPY(ctrl->bone->tail, tail_vec);
01761                         
01762                         rotation_between_vecs_to_quat(qtail, v1, v2);
01763                         mul_qt_qtqt(ctrl->qrot, qtail, ctrl->qrot);
01764                         
01765                         resize = len_v3(v2) / len_v3v3(ctrl->head, ctrl->tail);
01766                 }
01767                 
01768                 ctrl->bone->roll = rollBoneByQuat(ctrl->bone, ctrl->up_axis, ctrl->qrot);
01769         
01770                 /* Cascade to connected control bones */
01771                 for (ctrl_child = rigg->controls.first; ctrl_child; ctrl_child = ctrl_child->next)
01772                 {
01773                         if (ctrl_child->link == ctrl->bone)
01774                         {
01775                                 repositionControl(rigg, ctrl_child, ctrl->bone->head, ctrl->bone->tail, ctrl->qrot, resize);
01776                         }
01777                         if (ctrl_child->link_tail == ctrl->bone)
01778                         {
01779                                 repositionTailControl(rigg, ctrl_child);
01780                         }
01781                 }
01782         }       
01783 }
01784 
01785 static void repositionTailControl(RigGraph *rigg, RigControl *ctrl)
01786 {
01787         ctrl->flag |= RIG_CTRL_TAIL_DONE;
01788 
01789         finalizeControl(rigg, ctrl, 1); /* resize will be recalculated anyway so we don't need it */
01790 }
01791 
01792 static void repositionControl(RigGraph *rigg, RigControl *ctrl, float head[3], float UNUSED(tail[3]), float qrot[4], float resize)
01793 {
01794         float parent_offset[3], tail_offset[3];
01795         
01796         VECCOPY(parent_offset, ctrl->offset);
01797         mul_v3_fl(parent_offset, resize);
01798         mul_qt_v3(qrot, parent_offset);
01799         
01800         add_v3_v3v3(ctrl->bone->head, head, parent_offset); 
01801 
01802         ctrl->flag |= RIG_CTRL_HEAD_DONE;
01803 
01804         QUATCOPY(ctrl->qrot, qrot); 
01805 
01806         if (ctrl->tail_mode == TL_NONE)
01807         {
01808                 sub_v3_v3v3(tail_offset, ctrl->tail, ctrl->head);
01809                 mul_v3_fl(tail_offset, resize);
01810                 mul_qt_v3(qrot, tail_offset);
01811 
01812                 add_v3_v3v3(ctrl->bone->tail, ctrl->bone->head, tail_offset);
01813                 
01814                 ctrl->flag |= RIG_CTRL_TAIL_DONE;
01815         }
01816 
01817         finalizeControl(rigg, ctrl, resize);
01818 }
01819 
01820 static void repositionBone(bContext *C, RigGraph *rigg, RigEdge *edge, float vec0[3], float vec1[3], float up_axis[3])
01821 {
01822         Scene *scene = CTX_data_scene(C);
01823         EditBone *bone;
01824         RigControl *ctrl;
01825         float qrot[4], resize;
01826         float v1[3], v2[3];
01827         float l1, l2;
01828         
01829         bone = edge->bone;
01830         
01831         sub_v3_v3v3(v1, edge->tail, edge->head);
01832         sub_v3_v3v3(v2, vec1, vec0);
01833         
01834         l1 = normalize_v3(v1);
01835         l2 = normalize_v3(v2);
01836 
01837         resize = l2 / l1;
01838         
01839         rotation_between_vecs_to_quat(qrot, v1, v2);
01840         
01841         VECCOPY(bone->head, vec0);
01842         VECCOPY(bone->tail, vec1);
01843         
01844         if (!is_zero_v3(up_axis))
01845         {
01846                 float qroll[4];
01847 
01848                 if (scene->toolsettings->skgen_retarget_roll == SK_RETARGET_ROLL_VIEW)
01849                 {
01850                         bone->roll = rollBoneByQuatAligned(bone, edge->up_axis, qrot, qroll, up_axis);
01851                 }
01852                 else if (scene->toolsettings->skgen_retarget_roll == SK_RETARGET_ROLL_JOINT)
01853                 {
01854                         bone->roll = rollBoneByQuatJoint(edge, edge->prev, qrot, qroll, up_axis);
01855                 }
01856                 else
01857                 {
01858                         unit_qt(qroll);
01859                 }
01860                 
01861                 mul_qt_qtqt(qrot, qroll, qrot);
01862         }
01863         else
01864         {
01865                 bone->roll = rollBoneByQuat(bone, edge->up_axis, qrot);
01866         }
01867 
01868         for (ctrl = rigg->controls.first; ctrl; ctrl = ctrl->next)
01869         {
01870                 if (ctrl->link == bone)
01871                 {
01872                         repositionControl(rigg, ctrl, vec0, vec1, qrot, resize);
01873                 }
01874                 if (ctrl->link_tail == bone)
01875                 {
01876                         repositionTailControl(rigg, ctrl);
01877                 }
01878         }
01879 }
01880 
01881 static RetargetMode detectArcRetargetMode(RigArc *arc);
01882 static void retargetArctoArcLength(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode *inode_start);
01883 
01884 
01885 static RetargetMode detectArcRetargetMode(RigArc *iarc)
01886 {
01887         RetargetMode mode = RETARGET_AGGRESSIVE;
01888         ReebArc *earc = iarc->link_mesh;
01889         RigEdge *edge;
01890         int large_angle = 0;
01891         float avg_angle = 0;
01892         float avg_length = 0;
01893         int nb_edges = 0;
01894         
01895         
01896         for (edge = iarc->edges.first; edge; edge = edge->next)
01897         {
01898                 avg_angle += edge->angle;
01899                 nb_edges++;
01900         }
01901         
01902         avg_angle /= nb_edges - 1; /* -1 because last edge doesn't have an angle */
01903 
01904         avg_length = iarc->length / nb_edges;
01905         
01906         
01907         if (nb_edges > 2)
01908         {
01909                 for (edge = iarc->edges.first; edge; edge = edge->next)
01910                 {
01911                         if (fabs(edge->angle - avg_angle) > M_PI / 6)
01912                         {
01913                                 large_angle = 1;
01914                         }
01915                 }
01916         }
01917         else if (nb_edges == 2 && avg_angle > 0)
01918         {
01919                 large_angle = 1;
01920         }
01921                 
01922         
01923         if (large_angle == 0)
01924         {
01925                 mode = RETARGET_LENGTH;
01926         }
01927         
01928         if (earc->bcount <= (iarc->count - 1))
01929         {
01930                 mode = RETARGET_LENGTH;
01931         }
01932         
01933         return mode;
01934 }
01935 
01936 #ifndef USE_THREADS
01937 static void printMovesNeeded(int *positions, int nb_positions)
01938 {
01939         int moves = 0;
01940         int i;
01941         
01942         for (i = 0; i < nb_positions; i++)
01943         {
01944                 moves += positions[i] - (i + 1);
01945         }
01946         
01947         printf("%i moves needed\n", moves);
01948 }
01949 
01950 static void printPositions(int *positions, int nb_positions)
01951 {
01952         int i;
01953         
01954         for (i = 0; i < nb_positions; i++)
01955         {
01956                 printf("%i ", positions[i]);
01957         }
01958         printf("\n");
01959 }
01960 #endif
01961 
01962 #define MAX_COST FLT_MAX /* FIX ME */
01963 
01964 static float costDistance(BArcIterator *iter, float *vec0, float *vec1, int i0, int i1, float distance_weight)
01965 {
01966         EmbedBucket *bucket = NULL;
01967         float max_dist = 0;
01968         float v1[3], v2[3], c[3];
01969         float v1_inpf;
01970 
01971         if (distance_weight > 0)
01972         {
01973                 sub_v3_v3v3(v1, vec0, vec1);
01974                 
01975                 v1_inpf = dot_v3v3(v1, v1);
01976                 
01977                 if (v1_inpf > 0)
01978                 {
01979                         int j;
01980                         for (j = i0 + 1; j < i1 - 1; j++)
01981                         {
01982                                 float dist;
01983                                 
01984                                 bucket = IT_peek(iter, j);
01985         
01986                                 sub_v3_v3v3(v2, bucket->p, vec1);
01987                 
01988                                 cross_v3_v3v3(c, v1, v2);
01989                                 
01990                                 dist = dot_v3v3(c, c) / v1_inpf;
01991                                 
01992                                 max_dist = dist > max_dist ? dist : max_dist;
01993                         }
01994                         
01995                         return distance_weight * max_dist;
01996                 }
01997                 else
01998                 {
01999                         return MAX_COST;
02000                 }
02001         }
02002         else
02003         {
02004                 return 0;
02005         }
02006 }
02007 
02008 static float costAngle(float original_angle, float vec_first[3], float vec_second[3], float angle_weight)
02009 {
02010         if (angle_weight > 0)
02011         {
02012                 float current_angle;
02013                 
02014                 if (!is_zero_v3(vec_first) && !is_zero_v3(vec_second))
02015                 {
02016                         current_angle = saacos(dot_v3v3(vec_first, vec_second));
02017 
02018                         return angle_weight * fabs(current_angle - original_angle);
02019                 }
02020                 else
02021                 {
02022                         return angle_weight * M_PI;
02023                 }
02024         }
02025         else
02026         {
02027                 return 0;
02028         }
02029 }
02030 
02031 static float costLength(float original_length, float current_length, float length_weight)
02032 {
02033         if (current_length == 0)
02034         {
02035                 return MAX_COST;
02036         }
02037         else
02038         {
02039                 float length_ratio = fabs((current_length - original_length) / original_length);
02040                 return length_weight * length_ratio * length_ratio;
02041         }
02042 }
02043 
02044 #if 0
02045 static float calcCostLengthDistance(BArcIterator *iter, float **vec_cache, RigEdge *edge, float *vec1, float *vec2, int i1, int i2)
02046 {
02047         float vec[3];
02048         float length;
02049 
02050         sub_v3_v3v3(vec, vec2, vec1);
02051         length = normalize_v3(vec);
02052 
02053         return costLength(edge->length, length) + costDistance(iter, vec1, vec2, i1, i2);
02054 }
02055 #endif
02056 
02057 static float calcCostAngleLengthDistance(BArcIterator *iter, float **UNUSED(vec_cache), RigEdge *edge, float *vec0, float *vec1, float *vec2, int i1, int i2, float angle_weight, float length_weight, float distance_weight)
02058 {
02059         float vec_second[3], vec_first[3];
02060         float length2;
02061         float new_cost = 0;
02062 
02063         sub_v3_v3v3(vec_second, vec2, vec1);
02064         length2 = normalize_v3(vec_second);
02065 
02066 
02067         /* Angle cost */        
02068         if (edge->prev)
02069         {
02070                 sub_v3_v3v3(vec_first, vec1, vec0); 
02071                 normalize_v3(vec_first);
02072                 
02073                 new_cost += costAngle(edge->prev->angle, vec_first, vec_second, angle_weight);
02074         }
02075 
02076         /* Length cost */
02077         new_cost += costLength(edge->length, length2, length_weight);
02078 
02079         /* Distance cost */
02080         new_cost += costDistance(iter, vec1, vec2, i1, i2, distance_weight);
02081 
02082         return new_cost;
02083 }
02084 
02085 static int indexMemoNode(int nb_positions, int previous, int current, int joints_left)
02086 {
02087         return joints_left * nb_positions * nb_positions + current * nb_positions + previous;
02088 }
02089 
02090 static void copyMemoPositions(int *positions, MemoNode *table, int nb_positions, int joints_left)
02091 {
02092         int previous = 0, current = 0;
02093         int i = 0;
02094         
02095         for (i = 0; joints_left > 0; joints_left--, i++)
02096         {
02097                 MemoNode *node;
02098                 node = table + indexMemoNode(nb_positions, previous, current, joints_left);
02099                 
02100                 positions[i] = node->next;
02101                 
02102                 previous = current;
02103                 current = node->next;
02104         }
02105 }
02106 
02107 static MemoNode * solveJoints(MemoNode *table, BArcIterator *iter, float **vec_cache, int nb_joints, int nb_positions, int previous, int current, RigEdge *edge, int joints_left, float angle_weight, float length_weight, float distance_weight)
02108 {
02109         MemoNode *node;
02110         int index = indexMemoNode(nb_positions, previous, current, joints_left);
02111         
02112         node = table + index;
02113         
02114         if (node->weight != 0)
02115         {
02116                 return node;
02117         }
02118         else if (joints_left == 0)
02119         {
02120                 float *vec0 = vec_cache[previous];
02121                 float *vec1 = vec_cache[current];
02122                 float *vec2 = vec_cache[nb_positions + 1];
02123 
02124                 node->weight = calcCostAngleLengthDistance(iter, vec_cache, edge, vec0, vec1, vec2, current, iter->length, angle_weight, length_weight, distance_weight);
02125 
02126                 return node;
02127         }
02128         else
02129         {
02130                 MemoNode *min_node = NULL;
02131                 float *vec0 = vec_cache[previous];
02132                 float *vec1 = vec_cache[current];
02133                 float min_weight= 0.0f;
02134                 int min_next= 0;
02135                 int next;
02136                 
02137                 for (next = current + 1; next <= nb_positions - (joints_left - 1); next++)
02138                 {
02139                         MemoNode *next_node;
02140                         float *vec2 = vec_cache[next];
02141                         float weight = 0.0f;
02142                         
02143                         /* ADD WEIGHT OF PREVIOUS - CURRENT - NEXT triple */
02144                         weight = calcCostAngleLengthDistance(iter, vec_cache, edge, vec0, vec1, vec2, current, next, angle_weight, length_weight, distance_weight);
02145                         
02146                         if (weight >= MAX_COST)
02147                         {
02148                                 continue;
02149                         }
02150                         
02151                         /* add node weight */
02152                         next_node = solveJoints(table, iter, vec_cache, nb_joints, nb_positions, current, next, edge->next, joints_left - 1, angle_weight, length_weight, distance_weight);
02153                         weight += next_node->weight;
02154                         
02155                         if (min_node == NULL || weight < min_weight)
02156                         {
02157                                 min_weight = weight;
02158                                 min_node = next_node;
02159                                 min_next = next;
02160                         }
02161                 }
02162                 
02163                 if (min_node)
02164                 {
02165                         node->weight = min_weight;
02166                         node->next = min_next;
02167                         return node;
02168                 }
02169                 else
02170                 {
02171                         node->weight = MAX_COST;
02172                         return node;
02173                 }
02174         }
02175         
02176 }
02177 
02178 static int testFlipArc(RigArc *iarc, RigNode *inode_start)
02179 {
02180         ReebArc *earc = iarc->link_mesh;
02181         ReebNode *enode_start = BIF_NodeFromIndex(earc, inode_start->link_mesh);
02182         
02183         /* no flip needed if both nodes are the same */
02184         if ((enode_start == earc->head && inode_start == iarc->head) || (enode_start == earc->tail && inode_start == iarc->tail))
02185         {
02186                 return 0;
02187         }
02188         else
02189         {
02190                 return 1;
02191         }
02192 }
02193 
02194 static void retargetArctoArcAggresive(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode *inode_start)
02195 {
02196         ReebArcIterator arc_iter;
02197         BArcIterator *iter = (BArcIterator*)&arc_iter;
02198         RigEdge *edge;
02199         EmbedBucket *bucket = NULL;
02200         ReebNode *node_start, *node_end;
02201         ReebArc *earc = iarc->link_mesh;
02202         float angle_weight = 1.0; // GET FROM CONTEXT
02203         float length_weight = 1.0;
02204         float distance_weight = 1.0;
02205         float min_cost = FLT_MAX;
02206         float *vec0, *vec1;
02207         int *best_positions;
02208         int nb_edges = BLI_countlist(&iarc->edges);
02209         int nb_joints = nb_edges - 1;
02210         RetargetMethod method = METHOD_MEMOIZE;
02211         int i;
02212         
02213         if (nb_joints > earc->bcount)
02214         {
02215                 printf("NOT ENOUGH BUCKETS!\n");
02216                 return;
02217         }
02218 
02219         best_positions = MEM_callocN(sizeof(int) * nb_joints, "Best positions");
02220         
02221         if (testFlipArc(iarc, inode_start))
02222         {
02223                 node_start = earc->tail;
02224                 node_end = earc->head;
02225         }
02226         else
02227         {
02228                 node_start = earc->head;
02229                 node_end = earc->tail;
02230         }
02231 
02232         /* equal number of joints and potential position, just fill them in */
02233         if (nb_joints == earc->bcount)
02234         {
02235                 int i;
02236                 
02237                 /* init with first values */
02238                 for (i = 0; i < nb_joints; i++)
02239                 {
02240                         best_positions[i] = i + 1;
02241                 }
02242         }
02243         if (method == METHOD_MEMOIZE)
02244         {
02245                 int nb_positions = earc->bcount;
02246                 int nb_memo_nodes = nb_positions * nb_positions * (nb_joints + 1);
02247                 MemoNode *table = MEM_callocN(nb_memo_nodes * sizeof(MemoNode), "memoization table");
02248                 MemoNode *result;
02249                 float **positions_cache = MEM_callocN(sizeof(float*) * (nb_positions + 2), "positions cache");
02250                 int i;
02251                 
02252                 positions_cache[0] = node_start->p;
02253                 positions_cache[nb_positions + 1] = node_end->p;
02254                 
02255                 initArcIterator(iter, earc, node_start);
02256 
02257                 for (i = 1; i <= nb_positions; i++)
02258                 {
02259                         EmbedBucket *bucket = IT_peek(iter, i);
02260                         positions_cache[i] = bucket->p;
02261                 }
02262 
02263                 result = solveJoints(table, iter, positions_cache, nb_joints, earc->bcount, 0, 0, iarc->edges.first, nb_joints, angle_weight, length_weight, distance_weight);
02264                 
02265                 min_cost = result->weight;
02266                 copyMemoPositions(best_positions, table, earc->bcount, nb_joints);
02267                 
02268                 MEM_freeN(table);
02269                 MEM_freeN(positions_cache);
02270         }
02271 
02272         vec0 = node_start->p;
02273         initArcIterator(iter, earc, node_start);
02274         
02275 #ifndef USE_THREADS
02276         printPositions(best_positions, nb_joints);
02277         printMovesNeeded(best_positions, nb_joints);
02278         printf("min_cost %f\n", min_cost);
02279         printf("buckets: %i\n", earc->bcount);
02280 #endif
02281 
02282         /* set joints to best position */
02283         for (edge = iarc->edges.first, i = 0;
02284                  edge;
02285                  edge = edge->next, i++)
02286         {
02287                 float *no = NULL;
02288                 if (i < nb_joints)
02289                 {
02290                         bucket = IT_peek(iter, best_positions[i]);
02291                         vec1 = bucket->p;
02292                         no = bucket->no;
02293                 }
02294                 else
02295                 {
02296                         vec1 = node_end->p;
02297                         no = node_end->no;
02298                 }
02299                 
02300                 if (edge->bone)
02301                 {
02302                         repositionBone(C, rigg, edge, vec0, vec1, no);
02303                 }
02304                 
02305                 vec0 = vec1;
02306         }
02307 
02308         MEM_freeN(best_positions);
02309 }
02310 
02311 static void retargetArctoArcLength(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode *inode_start)
02312 {
02313         ReebArcIterator arc_iter;
02314         BArcIterator *iter = (BArcIterator*)&arc_iter;
02315         ReebArc *earc = iarc->link_mesh;
02316         ReebNode *node_start, *node_end;
02317         RigEdge *edge;
02318         EmbedBucket *bucket = NULL;
02319         float embedding_length = 0;
02320         float *vec0 = NULL;
02321         float *vec1 = NULL;
02322         float *previous_vec = NULL;
02323 
02324         
02325         if (testFlipArc(iarc, inode_start))
02326         {
02327                 node_start = (ReebNode*)earc->tail;
02328                 node_end = (ReebNode*)earc->head;
02329         }
02330         else
02331         {
02332                 node_start = (ReebNode*)earc->head;
02333                 node_end = (ReebNode*)earc->tail;
02334         }
02335         
02336         initArcIterator(iter, earc, node_start);
02337 
02338         bucket = IT_next(iter);
02339         
02340         vec0 = node_start->p;
02341         
02342         while (bucket != NULL)
02343         {
02344                 vec1 = bucket->p;
02345                 
02346                 embedding_length += len_v3v3(vec0, vec1);
02347                 
02348                 vec0 = vec1;
02349                 bucket = IT_next(iter);
02350         }
02351         
02352         embedding_length += len_v3v3(node_end->p, vec1);
02353         
02354         /* fit bones */
02355         initArcIterator(iter, earc, node_start);
02356 
02357         bucket = IT_next(iter);
02358 
02359         vec0 = node_start->p;
02360         previous_vec = vec0;
02361         vec1 = bucket->p;
02362         
02363         for (edge = iarc->edges.first; edge; edge = edge->next)
02364         {
02365                 float new_bone_length = edge->length / iarc->length * embedding_length;
02366                 float *no = NULL;
02367                 float length = 0;
02368 
02369                 while (bucket && new_bone_length > length)
02370                 {
02371                         length += len_v3v3(previous_vec, vec1);
02372                         bucket = IT_next(iter);
02373                         previous_vec = vec1;
02374                         vec1 = bucket->p;
02375                         no = bucket->no;
02376                 }
02377                 
02378                 if (bucket == NULL)
02379                 {
02380                         vec1 = node_end->p;
02381                         no = node_end->no;
02382                 }
02383 
02384                 /* no need to move virtual edges (space between unconnected bones) */           
02385                 if (edge->bone)
02386                 {
02387                         repositionBone(C, rigg, edge, vec0, vec1, no);
02388                 }
02389                 
02390                 vec0 = vec1;
02391                 previous_vec = vec1;
02392         }
02393 }
02394 
02395 static void retargetArctoArc(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode *inode_start)
02396 {
02397 #ifdef USE_THREADS
02398         RetargetParam *p = MEM_callocN(sizeof(RetargetParam), "RetargetParam");
02399         
02400         p->rigg = rigg;
02401         p->iarc = iarc;
02402         p->inode_start = inode_start;
02403         p->context = C;
02404         
02405         BLI_insert_work(rigg->worker, p);
02406 #else
02407         RetargetParam p;
02408 
02409         p.rigg = rigg;
02410         p.iarc = iarc;
02411         p.inode_start = inode_start;
02412         p.context = C;
02413         
02414         exec_retargetArctoArc(&p);
02415 #endif
02416 }
02417 
02418 void *exec_retargetArctoArc(void *param)
02419 {
02420         RetargetParam *p = (RetargetParam*)param;
02421         RigGraph *rigg = p->rigg;
02422         RigArc *iarc = p->iarc;
02423         bContext *C = p->context;       
02424         RigNode *inode_start = p->inode_start;
02425         ReebArc *earc = iarc->link_mesh;
02426         
02427         if (BLI_countlist(&iarc->edges) == 1)
02428         {
02429                 RigEdge *edge = iarc->edges.first;
02430 
02431                 if (testFlipArc(iarc, inode_start))
02432                 {
02433                         repositionBone(C, rigg, edge, earc->tail->p, earc->head->p, earc->head->no);
02434                 }
02435                 else
02436                 {
02437                         repositionBone(C, rigg, edge, earc->head->p, earc->tail->p, earc->tail->no);
02438                 }
02439         }
02440         else
02441         {
02442                 RetargetMode mode = detectArcRetargetMode(iarc);
02443                 
02444                 if (mode == RETARGET_AGGRESSIVE)
02445                 {
02446                         retargetArctoArcAggresive(C, rigg, iarc, inode_start);
02447                 }
02448                 else
02449                 {               
02450                         retargetArctoArcLength(C, rigg, iarc, inode_start);
02451                 }
02452         }
02453 
02454 #ifdef USE_THREADS
02455         MEM_freeN(p);
02456 #endif
02457         
02458         return NULL;
02459 }
02460 
02461 static void matchMultiResolutionNode(RigGraph *rigg, RigNode *inode, ReebNode *top_node)
02462 {
02463         ReebNode *enode = top_node;
02464         ReebGraph *reebg = BIF_graphForMultiNode(rigg->link_mesh, enode);
02465         int ishape, eshape;
02466         
02467         ishape = BLI_subtreeShape((BGraph*)rigg, (BNode*)inode, NULL, 0) % SHAPE_LEVELS;
02468         eshape = BLI_subtreeShape((BGraph*)reebg, (BNode*)enode, NULL, 0) % SHAPE_LEVELS;
02469         
02470         inode->link_mesh = enode;
02471 
02472         while (ishape == eshape && enode->link_down)
02473         {
02474                 inode->link_mesh = enode;
02475 
02476                 enode = enode->link_down;
02477                 reebg = BIF_graphForMultiNode(rigg->link_mesh, enode); /* replace with call to link_down once that exists */
02478                 eshape = BLI_subtreeShape((BGraph*)reebg, (BNode*)enode, NULL, 0) % SHAPE_LEVELS;
02479         } 
02480 }
02481 
02482 static void markMultiResolutionChildArc(ReebNode *end_enode, ReebNode *enode)
02483 {
02484         int i;
02485         
02486         for(i = 0; i < enode->degree; i++)
02487         {
02488                 ReebArc *earc = (ReebArc*)enode->arcs[i];
02489                 
02490                 if (earc->flag == ARC_FREE)
02491                 {
02492                         earc->flag = ARC_TAKEN;
02493                         
02494                         if (earc->tail->degree > 1 && earc->tail != end_enode)
02495                         {
02496                                 markMultiResolutionChildArc(end_enode, earc->tail);
02497                         }
02498                         break;
02499                 }
02500         }
02501 }
02502 
02503 static void markMultiResolutionArc(ReebArc *start_earc)
02504 {
02505         if (start_earc->link_up)
02506         {
02507                 ReebArc *earc;
02508                 for (earc = start_earc->link_up ; earc; earc = earc->link_up)
02509                 {
02510                         earc->flag = ARC_TAKEN;
02511                         
02512                         if (earc->tail->index != start_earc->tail->index)
02513                         {
02514                                 markMultiResolutionChildArc(earc->tail, earc->tail);
02515                         }
02516                 }
02517         }
02518 }
02519 
02520 static void matchMultiResolutionArc(RigGraph *rigg, RigNode *start_node, RigArc *next_iarc, ReebArc *next_earc)
02521 {
02522         ReebNode *enode = next_earc->head;
02523         ReebGraph *reebg = BIF_graphForMultiNode(rigg->link_mesh, enode);
02524         int ishape, eshape;
02525 
02526         ishape = BLI_subtreeShape((BGraph*)rigg, (BNode*)start_node, (BArc*)next_iarc, 1) % SHAPE_LEVELS;
02527         eshape = BLI_subtreeShape((BGraph*)reebg, (BNode*)enode, (BArc*)next_earc, 1) % SHAPE_LEVELS;
02528         
02529         while (ishape != eshape && next_earc->link_up)
02530         {
02531                 next_earc->flag = ARC_TAKEN; // mark previous as taken, to prevent backtrack on lower levels
02532                 
02533                 next_earc = next_earc->link_up;
02534                 reebg = reebg->link_up;
02535                 enode = next_earc->head;
02536                 eshape = BLI_subtreeShape((BGraph*)reebg, (BNode*)enode, (BArc*)next_earc, 1) % SHAPE_LEVELS;
02537         } 
02538 
02539         next_earc->flag = ARC_USED;
02540         next_iarc->link_mesh = next_earc;
02541         
02542         /* mark all higher levels as taken too */
02543         markMultiResolutionArc(next_earc);
02544 //      while (next_earc->link_up)
02545 //      {
02546 //              next_earc = next_earc->link_up;
02547 //              next_earc->flag = ARC_TAKEN;
02548 //      }
02549 }
02550 
02551 static void matchMultiResolutionStartingNode(RigGraph *rigg, ReebGraph *reebg, RigNode *inode)
02552 {
02553         ReebNode *enode;
02554         int ishape, eshape;
02555         
02556         enode = reebg->nodes.first;
02557         
02558         ishape = BLI_subtreeShape((BGraph*)rigg, (BNode*)inode, NULL, 0) % SHAPE_LEVELS;
02559         eshape = BLI_subtreeShape((BGraph*)rigg->link_mesh, (BNode*)enode, NULL, 0) % SHAPE_LEVELS;
02560         
02561         while (ishape != eshape && reebg->link_up)
02562         {
02563                 reebg = reebg->link_up;
02564                 
02565                 enode = reebg->nodes.first;
02566                 
02567                 eshape = BLI_subtreeShape((BGraph*)reebg, (BNode*)enode, NULL, 0) % SHAPE_LEVELS;
02568         } 
02569 
02570         inode->link_mesh = enode;
02571 }
02572 
02573 static void findCorrespondingArc(RigGraph *rigg, RigArc *start_arc, RigNode *start_node, RigArc *next_iarc, int root)
02574 {
02575         ReebNode *enode = start_node->link_mesh;
02576         ReebArc *next_earc;
02577         int symmetry_level = next_iarc->symmetry_level;
02578         int symmetry_group = next_iarc->symmetry_group;
02579         int symmetry_flag = next_iarc->symmetry_flag;
02580         int i;
02581         
02582         next_iarc->link_mesh = NULL;
02583                 
02584 //      if (root)
02585 //      {
02586 //              printf("-----------------------\n");
02587 //              printf("MATCHING LIMB\n");
02588 //              RIG_printArcBones(next_iarc);
02589 //      }
02590         
02591         for(i = 0; i < enode->degree; i++)
02592         {
02593                 next_earc = (ReebArc*)enode->arcs[i];
02594                 
02595 //              if (next_earc->flag == ARC_FREE)
02596 //              {
02597 //                      printf("candidate (level %i ?= %i) (flag %i ?= %i) (group %i ?= %i)\n",
02598 //                      symmetry_level, next_earc->symmetry_level,
02599 //                      symmetry_flag, next_earc->symmetry_flag, 
02600 //                      symmetry_group, next_earc->symmetry_flag);
02601 //              }
02602                 
02603                 if (next_earc->flag == ARC_FREE &&
02604                         next_earc->symmetry_flag == symmetry_flag &&
02605                         next_earc->symmetry_group == symmetry_group &&
02606                         next_earc->symmetry_level == symmetry_level)
02607                 {
02608 //                      printf("CORRESPONDING ARC FOUND\n");
02609 //                      printf("flag %i -- level %i -- flag %i -- group %i\n", next_earc->flag, next_earc->symmetry_level, next_earc->symmetry_flag, next_earc->symmetry_group);
02610                         
02611                         matchMultiResolutionArc(rigg, start_node, next_iarc, next_earc);
02612                         break;
02613                 }
02614         }
02615         
02616         /* not found, try at higher nodes (lower node might have filtered internal arcs, messing shape of tree */
02617         if (next_iarc->link_mesh == NULL)
02618         {
02619 //              printf("NO CORRESPONDING ARC FOUND - GOING TO HIGHER LEVELS\n");
02620                 
02621                 if (enode->link_up)
02622                 {
02623                         start_node->link_mesh = enode->link_up;
02624                         findCorrespondingArc(rigg, start_arc, start_node, next_iarc, 0);
02625                 }
02626         }
02627 
02628         /* still not found, print debug info */
02629         if (root && next_iarc->link_mesh == NULL)
02630         {
02631                 start_node->link_mesh = enode; /* linking back with root node */
02632                 
02633 //              printf("NO CORRESPONDING ARC FOUND\n");
02634 //              RIG_printArcBones(next_iarc);
02635 //              
02636 //              printf("ON NODE %i, multilevel %i\n", enode->index, enode->multi_level);
02637 //              
02638 //              printf("LOOKING FOR\n");
02639 //              printf("flag %i -- level %i -- flag %i -- group %i\n", ARC_FREE, symmetry_level, symmetry_flag, symmetry_group);
02640 //              
02641 //              printf("CANDIDATES\n");
02642 //              for(i = 0; i < enode->degree; i++)
02643 //              {
02644 //                      next_earc = (ReebArc*)enode->arcs[i];
02645 //                      printf("flag %i -- level %i -- flag %i -- group %i\n", next_earc->flag, next_earc->symmetry_level, next_earc->symmetry_flag, next_earc->symmetry_group);
02646 //              }
02647                 
02648                 /* Emergency matching */
02649                 for(i = 0; i < enode->degree; i++)
02650                 {
02651                         next_earc = (ReebArc*)enode->arcs[i];
02652                         
02653                         if (next_earc->flag == ARC_FREE && next_earc->symmetry_level == symmetry_level)
02654                         {
02655 //                              printf("USING: \n");
02656 //                              printf("flag %i -- level %i -- flag %i -- group %i\n", next_earc->flag, next_earc->symmetry_level, next_earc->symmetry_flag, next_earc->symmetry_group);
02657                                 matchMultiResolutionArc(rigg, start_node, next_iarc, next_earc);
02658                                 break;
02659                         }
02660                 }
02661         }
02662 
02663 }
02664 
02665 static void retargetSubgraph(bContext *C, RigGraph *rigg, RigArc *start_arc, RigNode *start_node)
02666 {
02667         RigNode *inode = start_node;
02668         int i;
02669 
02670         /* no start arc on first node */
02671         if (start_arc)
02672         {               
02673                 ReebNode *enode = start_node->link_mesh;
02674                 ReebArc *earc = start_arc->link_mesh;
02675                 
02676                 retargetArctoArc(C, rigg, start_arc, start_node);
02677                 
02678                 enode = BIF_otherNodeFromIndex(earc, enode);
02679                 inode = (RigNode*)BLI_otherNode((BArc*)start_arc, (BNode*)inode);
02680         
02681                 /* match with lowest node with correct shape */
02682                 matchMultiResolutionNode(rigg, inode, enode);
02683         }
02684         
02685         for(i = 0; i < inode->degree; i++)
02686         {
02687                 RigArc *next_iarc = (RigArc*)inode->arcs[i];
02688                 
02689                 /* no back tracking */
02690                 if (next_iarc != start_arc)
02691                 {
02692                         findCorrespondingArc(rigg, start_arc, inode, next_iarc, 1);
02693                         if (next_iarc->link_mesh)
02694                         {
02695                                 retargetSubgraph(C, rigg, next_iarc, inode);
02696                         }
02697                 }
02698         }
02699 }
02700 
02701 static void finishRetarget(RigGraph *rigg)
02702 {
02703 #ifdef USE_THREADS
02704         BLI_end_worker(rigg->worker);
02705 #endif
02706 }
02707 
02708 static void adjustGraphs(bContext *C, RigGraph *rigg)
02709 {
02710         bArmature *arm= rigg->ob->data;
02711         RigArc *arc;
02712         
02713         for (arc = rigg->arcs.first; arc; arc = arc->next)
02714         {
02715                 if (arc->link_mesh)
02716                 {
02717                         retargetArctoArc(C, rigg, arc, arc->head);
02718                 }
02719         }
02720 
02721         finishRetarget(rigg);
02722 
02723         /* Turn the list into an armature */
02724         arm->edbo = rigg->editbones;
02725         ED_armature_from_edit(rigg->ob);
02726         
02727         ED_undo_push(C, "Retarget Skeleton");
02728 }
02729 
02730 static void retargetGraphs(bContext *C, RigGraph *rigg)
02731 {
02732         bArmature *arm= rigg->ob->data;
02733         ReebGraph *reebg = rigg->link_mesh;
02734         RigNode *inode;
02735         
02736         /* flag all ReebArcs as free */
02737         BIF_flagMultiArcs(reebg, ARC_FREE);
02738         
02739         /* return to first level */
02740         inode = rigg->head;
02741         
02742         matchMultiResolutionStartingNode(rigg, reebg, inode);
02743 
02744         retargetSubgraph(C, rigg, NULL, inode);
02745         
02746         //generateMissingArcs(rigg);
02747         
02748         finishRetarget(rigg);
02749 
02750         /* Turn the list into an armature */
02751         arm->edbo = rigg->editbones;
02752         ED_armature_from_edit(rigg->ob);
02753 }
02754 
02755 const char *RIG_nameBone(RigGraph *rg, int arc_index, int bone_index)
02756 {
02757         RigArc *arc = BLI_findlink(&rg->arcs, arc_index);
02758         RigEdge *iedge;
02759 
02760         if (arc == NULL)
02761         {
02762                 return "None";
02763         }
02764         
02765         if (bone_index == BLI_countlist(&arc->edges))
02766         {
02767                 return "Last joint";
02768         }
02769 
02770         iedge = BLI_findlink(&arc->edges, bone_index);
02771         
02772         if (iedge == NULL)
02773         {
02774                 return "Done";
02775         }
02776         
02777         if (iedge->bone == NULL)
02778         {
02779                 return "Bone offset";
02780         }
02781         
02782         return iedge->bone->name;
02783 }
02784 
02785 int RIG_nbJoints(RigGraph *rg)
02786 {
02787         RigArc *arc;
02788         int total = 0;
02789         
02790         total += BLI_countlist(&rg->nodes);
02791         
02792         for (arc = rg->arcs.first; arc; arc = arc->next)
02793         {
02794                 total += BLI_countlist(&arc->edges) - 1; /* -1 because end nodes are already counted */
02795         }
02796         
02797         return total;
02798 }
02799 
02800 static void BIF_freeRetarget(void)
02801 {
02802         if (GLOBAL_RIGG)
02803         {
02804                 RIG_freeRigGraph((BGraph*)GLOBAL_RIGG);
02805                 GLOBAL_RIGG = NULL;
02806         }
02807 }
02808 
02809 void BIF_retargetArmature(bContext *C)
02810 {
02811         ReebGraph *reebg;
02812         double start_time, end_time;
02813         double gstart_time, gend_time;
02814         double reeb_time, rig_time=0.0, retarget_time=0.0, total_time;
02815         
02816         gstart_time = start_time = PIL_check_seconds_timer();
02817         
02818         reebg = BIF_ReebGraphMultiFromEditMesh(C);
02819         
02820         end_time = PIL_check_seconds_timer();
02821         reeb_time = end_time - start_time;
02822         
02823         printf("Reeb Graph created\n");
02824 
02825         CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
02826                 Object *ob = base->object;
02827 
02828                 if (ob->type==OB_ARMATURE)
02829                 {
02830                         RigGraph *rigg;
02831                         bArmature *arm;
02832 
02833                         arm = ob->data;
02834                 
02835                         /* Put the armature into editmode */
02836                         
02837                 
02838                         start_time = PIL_check_seconds_timer();
02839 
02840                         rigg = RIG_graphFromArmature(C, ob, arm);
02841                         
02842                         end_time = PIL_check_seconds_timer();
02843                         rig_time = end_time - start_time;
02844 
02845                         printf("Armature graph created\n");
02846         
02847                         //RIG_printGraph(rigg);
02848                         
02849                         rigg->link_mesh = reebg;
02850                         
02851                         printf("retargetting %s\n", ob->id.name);
02852                         
02853                         start_time = PIL_check_seconds_timer();
02854 
02855                         retargetGraphs(C, rigg);
02856                         
02857                         end_time = PIL_check_seconds_timer();
02858                         retarget_time = end_time - start_time;
02859 
02860                         BIF_freeRetarget();
02861                         
02862                         GLOBAL_RIGG = rigg;
02863                         
02864                         break; /* only one armature at a time */
02865                 }
02866         }
02867         CTX_DATA_END;
02868 
02869         
02870         gend_time = PIL_check_seconds_timer();
02871 
02872         total_time = gend_time - gstart_time;
02873 
02874         printf("-----------\n");
02875         printf("runtime: \t%.3f\n", total_time);
02876         printf("reeb: \t\t%.3f (%.1f%%)\n", reeb_time, reeb_time / total_time * 100);
02877         printf("rig: \t\t%.3f (%.1f%%)\n", rig_time, rig_time / total_time * 100);
02878         printf("retarget: \t%.3f (%.1f%%)\n", retarget_time, retarget_time / total_time * 100);
02879         printf("-----------\n");
02880         
02881         ED_undo_push(C, "Retarget Skeleton");
02882 
02883         // XXX  
02884 //      allqueue(REDRAWVIEW3D, 0);
02885 }
02886 
02887 void BIF_retargetArc(bContext *C, ReebArc *earc, RigGraph *template_rigg)
02888 {
02889         Object *obedit = CTX_data_edit_object(C);
02890         Scene *scene = CTX_data_scene(C);
02891         bArmature *armedit = obedit->data;
02892         Object *ob;
02893         RigGraph *rigg;
02894         RigArc *iarc;
02895         char *side_string = scene->toolsettings->skgen_side_string;
02896         char *num_string = scene->toolsettings->skgen_num_string;
02897         int free_template = 0;
02898         
02899         if (template_rigg)
02900         {
02901                 ob = template_rigg->ob;         
02902         }
02903         else
02904         {
02905                 free_template = 1;
02906                 ob = obedit;
02907                 template_rigg = armatureSelectedToGraph(C, ob, ob->data);
02908         }
02909         
02910         if (template_rigg->arcs.first == NULL)
02911         {
02912 //              XXX
02913 //              error("No Template and no deforming bones selected");
02914                 return;
02915         }
02916         
02917         rigg = cloneRigGraph(template_rigg, armedit->edbo, obedit, side_string, num_string);
02918         
02919         iarc = rigg->arcs.first;
02920         
02921         iarc->link_mesh = earc;
02922         iarc->head->link_mesh = earc->head;
02923         iarc->tail->link_mesh = earc->tail;
02924         
02925         retargetArctoArc(C, rigg, iarc, iarc->head);
02926         
02927         finishRetarget(rigg);
02928         
02929         /* free template if it comes from the edit armature */
02930         if (free_template)
02931         {
02932                 RIG_freeRigGraph((BGraph*)template_rigg);
02933         }
02934         RIG_freeRigGraph((BGraph*)rigg);
02935         
02936         ED_armature_validate_active(armedit);
02937 
02938 //      XXX
02939 //      allqueue(REDRAWVIEW3D, 0);
02940 }
02941 
02942 void BIF_adjustRetarget(bContext *C)
02943 {
02944         if (GLOBAL_RIGG)
02945         {
02946                 adjustGraphs(C, GLOBAL_RIGG);
02947         }
02948 }