diff --git a/source/blender/include/BIF_editarmature.h b/source/blender/include/BIF_editarmature.h index 4c3ba94ccc1..a89aecf854e 100644 --- a/source/blender/include/BIF_editarmature.h +++ b/source/blender/include/BIF_editarmature.h @@ -70,6 +70,13 @@ typedef struct EditBone EditBone *addEditBone(char *name, struct ListBase *ebones, struct bArmature *arm); +/* duplicate method */ +void preEditBoneDuplicate(struct ListBase *editbones); +EditBone *duplicateEditBone(EditBone *curBone, struct ListBase *editbones, struct Object *ob); +void updateDuplicateSubtarget(EditBone *dupBone, struct Object *ob); + +/* -- */ + float rollBoneToVector(EditBone *bone, float new_up_axis[3]); void make_boneList(struct ListBase *list, struct ListBase *bones, EditBone *parent); void editbones_to_armature (struct ListBase *list, struct Object *ob); diff --git a/source/blender/include/BIF_retarget.h b/source/blender/include/BIF_retarget.h index df46d309a94..867c90460ba 100644 --- a/source/blender/include/BIF_retarget.h +++ b/source/blender/include/BIF_retarget.h @@ -44,10 +44,7 @@ struct RigEdge; typedef struct RigGraph { ListBase arcs; ListBase nodes; - ListBase controls; - ListBase* editbones; - float length; FreeArc free_arc; @@ -56,6 +53,9 @@ typedef struct RigGraph { AxialSymmetry axial_symmetry; /*********************************/ + ListBase controls; + ListBase* editbones; + struct RigNode *head; ReebGraph *link_mesh; diff --git a/source/blender/include/reeb.h b/source/blender/include/reeb.h index 57f7d1b60cf..d8146ff8d6d 100644 --- a/source/blender/include/reeb.h +++ b/source/blender/include/reeb.h @@ -185,6 +185,7 @@ ReebNode *BIF_lowestLevelNode(ReebNode *node); ReebGraph *BIF_graphForMultiNode(ReebGraph *rg, ReebNode *node); void REEB_freeGraph(ReebGraph *rg); +void REEB_freeArc(BArc *barc); void REEB_exportGraph(ReebGraph *rg, int count); void REEB_draw(); diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index b5e588ee747..6f33ece2ee9 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -441,17 +441,15 @@ typedef struct ToolSettings { char skgen_postpro_passes; char skgen_subdivisions[3]; char skgen_multi_level; - char skgen_optimisation_method; - - char tpad[6]; /* Skeleton Sketching */ char bone_sketching; + char bone_sketching_convert; char skgen_subdivision_number; /* Alt+RMB option */ char edge_mode; - char pad3[6]; + char pad3[4]; } ToolSettings; /* Used by all brushes to store their properties, which can be directly set @@ -879,6 +877,12 @@ typedef struct Scene { #define BONE_SKETCHING 1 #define BONE_SKETCHING_QUICK 2 +/* toolsettings->bone_sketching_convert */ +#define SK_CONVERT_CUT_FIXED 1 +#define SK_CONVERT_CUT_LENGTH 2 +#define SK_CONVERT_CUT_CORRELATION 3 +#define SK_CONVERT_RETARGET 4 + #ifdef __cplusplus } #endif diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index f362fa815ce..26c0496f107 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -5246,7 +5246,6 @@ static void editing_panel_mesh_skgen_retarget(Object *ob, Mesh *me) uiDefButF(block, NUM, B_DIFF, "Ang:", 1025, 40, 83,19, &G.scene->toolsettings->skgen_retarget_angle_weight, 0, 10, 1, 0, "Angle Weight"); uiDefButF(block, NUM, B_DIFF, "Len:", 1108, 40, 83,19, &G.scene->toolsettings->skgen_retarget_length_weight, 0, 10, 1, 0, "Length Weight"); uiDefButF(block, NUM, B_DIFF, "Dist:", 1191, 40, 84,19, &G.scene->toolsettings->skgen_retarget_distance_weight, 0, 10, 1, 0, "Distance Weight"); - uiDefButC(block, NUM, B_DIFF, "Method:", 1025, 20, 125,19, &G.scene->toolsettings->skgen_optimisation_method, 0, 2, 1, 0,"Optimisation Method (0: brute, 1: memoize, 2: annealing max fixed"); } static void editing_panel_mesh_skgen(Object *ob, Mesh *me) diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index dbc9dcfd805..7f1e8122da6 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2297,35 +2297,52 @@ static void view3d_panel_bonesketch_spaces(short cntrl) uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl); uiSetPanelHandler(VIEW3D_HANDLER_BONESKETCH); // for close and esc - if(uiNewPanel(curarea, block, "Bone Sketching", "View3d", 10, 230, 318, height)==0) return; + if(uiNewPanel(curarea, block, "Bone Sketching", "View3d", 10, 230, 250, height)==0) return; uiNewPanelHeight(block, height); uiBlockBeginAlign(block); /* use real flag instead of 1 */ - uiDefButBitC(block, TOG, BONE_SKETCHING, B_REDR, "Use Bone Sketching", 10, 225, 130, 20, &G.scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Use sketching to create and edit bones"); - uiDefButBitC(block, TOG, BONE_SKETCHING_QUICK, B_REDR, "Q", 140, 225, 20, 20, &G.scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Automatically convert and delete on stroke end"); - but = uiDefBut(block, BUT, B_REDR, "Convert", 10,205,150,20, 0, 0, 0, 0, 0, "Convert sketch to armature"); + uiDefButBitC(block, TOG, BONE_SKETCHING, B_REDR, "Use Bone Sketching", 10, yco, 130, 20, &G.scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Use sketching to create and edit bones"); + uiDefButBitC(block, TOG, BONE_SKETCHING_QUICK, B_REDR, "Q", 140, yco, 20, 20, &G.scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Automatically convert and delete on stroke end"); + yco -= 20; + + but = uiDefBut(block, BUT, B_REDR, "Convert", 10,yco,150,20, 0, 0, 0, 0, 0, "Convert sketch to armature"); uiButSetFunc(but, convert_sketch_armature, NULL, NULL); - but = uiDefBut(block, BUT, B_REDR, "Delete", 10,185,150,20, 0, 0, 0, 0, 0, "Delete sketch"); + yco -= 20; + + but = uiDefBut(block, BUT, B_REDR, "Delete", 10,yco,150,20, 0, 0, 0, 0, 0, "Delete sketch"); uiButSetFunc(but, delete_sketch_armature, NULL, NULL); + yco -= 20; uiBlockEndAlign(block); uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, SKGEN_CUT_LENGTH, B_REDR, "Length", 10, 155, 60, 19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs in bones of equal length"); - uiDefButF(block, NUM, B_REDR, "L:", 70, 155, 90, 19, &G.scene->toolsettings->skgen_length_limit,0.1,50.0, 10, 0, "Maximum length of the bones when subdividing"); + uiDefButC(block, ROW, B_REDR, "Length", 10, yco, 60, 19, &G.scene->toolsettings->bone_sketching_convert, 0, SK_CONVERT_CUT_LENGTH, 0, 0, "Subdivide arcs in bones of equal length"); + uiDefButF(block, NUM, B_REDR, "L:", 70, yco, 90, 19, &G.scene->toolsettings->skgen_length_limit,0.1,50.0, 10, 0, "Maximum length of the bones when subdividing"); + yco -= 20; - uiDefButBitS(block, TOG, SKGEN_CUT_CORRELATION, B_REDR, "Correlation", 10, 135, 60, 19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs based on correlation"); - uiDefButF(block, NUM, B_REDR, "T:", 70, 135, 90, 19, &G.scene->toolsettings->skgen_correlation_limit,0.0, 1.0, 0.01, 0, "Specify the threshold correlation for subdivision"); + uiDefButC(block, ROW, B_REDR, "Correlation", 10, yco, 60, 19, &G.scene->toolsettings->bone_sketching_convert, 0, SK_CONVERT_CUT_CORRELATION, 0, 0, "Subdivide arcs based on correlation"); + uiDefButF(block, NUM, B_REDR, "T:", 70, yco, 90, 19, &G.scene->toolsettings->skgen_correlation_limit,0.0, 1.0, 0.01, 0, "Specify the threshold correlation for subdivision"); + yco -= 20; - uiDefButBitS(block, TOG, SKGEN_CUT_FIXED, B_REDR, "Fixed", 10, 115, 60, 19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs based on a fixed number of bones"); - uiDefButC(block, NUM, B_REDR, "N:", 70, 115, 90, 19, &G.scene->toolsettings->skgen_subdivision_number,1, 100, 1, 5, "Specify the bones to subdivide into"); + uiDefButC(block, ROW, B_REDR, "Fixed", 10, yco, 60, 19, &G.scene->toolsettings->bone_sketching_convert, 0, SK_CONVERT_CUT_FIXED, 0, 0, "Subdivide arcs based on a fixed number of bones"); + uiDefButC(block, NUM, B_REDR, "N:", 70, yco, 90, 19, &G.scene->toolsettings->skgen_subdivision_number,1, 100, 1, 5, "Specify the bones to subdivide into"); + yco -= 20; + + uiDefButC(block, ROW, B_REDR, "Retarget", 10, yco,150, 19, &G.scene->toolsettings->bone_sketching_convert, 0, SK_CONVERT_RETARGET, 0, 0, "Subdivide arcs based on a fixed number of bones"); + /* button here to select what to do (copy or not), template, ...*/ + yco -= 20; uiBlockEndAlign(block); + uiDefButF(block, NUM, B_DIFF, "Ang:", 10, yco, 50,19, &G.scene->toolsettings->skgen_retarget_angle_weight, 0, 10, 1, 0, "Angle Weight"); + uiDefButF(block, NUM, B_DIFF, "Len:", 60, yco, 50,19, &G.scene->toolsettings->skgen_retarget_length_weight, 0, 10, 1, 0, "Length Weight"); + uiDefButF(block, NUM, B_DIFF, "Dist:", 110,yco, 50,19, &G.scene->toolsettings->skgen_retarget_distance_weight, 0, 10, 1, 0, "Distance Weight"); + yco -= 20; + if(yco < 0) uiNewPanelHeight(block, height-yco); } } diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index 6fc94e4f997..63d5b9ce1f5 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -2212,7 +2212,20 @@ static EditBone *get_named_editbone(char *name) return NULL; } -static void update_dup_subtarget(EditBone *dupBone) +/* Call this before doing any duplications + * */ +void preEditBoneDuplicate(ListBase *editbones) +{ + EditBone *eBone; + + /* clear temp */ + for (eBone = editbones->first; eBone; eBone = eBone->next) + { + eBone->temp = NULL; + } +} + +void updateDuplicateSubtarget(EditBone *dupBone, Object *ob) { /* If an edit bone has been duplicated, lets * update it's constraints if the subtarget @@ -2223,7 +2236,7 @@ static void update_dup_subtarget(EditBone *dupBone) bConstraint *curcon; ListBase *conlist; - if ( (chan = verify_pose_channel(OBACT->pose, dupBone->name)) ) { + if ( (chan = verify_pose_channel(ob->pose, dupBone->name)) ) { if ( (conlist = &chan->constraints) ) { for (curcon = conlist->first; curcon; curcon=curcon->next) { /* does this constraint have a subtarget in @@ -2244,7 +2257,7 @@ static void update_dup_subtarget(EditBone *dupBone) * so, update the constraint to point at the * duplicate of the old subtarget. */ - if (oldtarget->flag & BONE_SELECTED){ + if (oldtarget->temp){ newtarget = (EditBone *) oldtarget->temp; strcpy(ct->subtarget, newtarget->name); } @@ -2260,6 +2273,67 @@ static void update_dup_subtarget(EditBone *dupBone) } } +EditBone *duplicateEditBone(EditBone *curBone, ListBase *editbones, Object *ob) +{ + EditBone *eBone = MEM_callocN(sizeof(EditBone), "addup_editbone"); + + /* Copy data from old bone to new bone */ + memcpy(eBone, curBone, sizeof(EditBone)); + + curBone->temp = eBone; + eBone->temp = curBone; + + unique_editbone_name(editbones, eBone->name); + BLI_addtail(editbones, eBone); + + /* Lets duplicate the list of constraints that the + * current bone has. + */ + if (ob->pose) { + bPoseChannel *chanold, *channew; + ListBase *listold, *listnew; + + chanold = verify_pose_channel(ob->pose, curBone->name); + if (chanold) { + listold = &chanold->constraints; + if (listold) { + /* WARNING: this creates a new posechannel, but there will not be an attached bone + * yet as the new bones created here are still 'EditBones' not 'Bones'. + */ + channew = + verify_pose_channel(ob->pose, eBone->name); + if (channew) { + /* copy transform locks */ + channew->protectflag = chanold->protectflag; + + /* copy bone group */ + channew->agrp_index= chanold->agrp_index; + + /* ik (dof) settings */ + channew->ikflag = chanold->ikflag; + VECCOPY(channew->limitmin, chanold->limitmin); + VECCOPY(channew->limitmax, chanold->limitmax); + VECCOPY(channew->stiffness, chanold->stiffness); + channew->ikstretch= chanold->ikstretch; + + /* constraints */ + listnew = &channew->constraints; + copy_constraints(listnew, listold); + + /* custom shape */ + channew->custom= chanold->custom; + } + } + } + } + + /* --------------------WARNING-------------------- + * + * need to call static void updateDuplicateSubtarget(EditBone *dupBone) at some point + * */ + + return eBone; +} void adduplicate_armature(void) { @@ -2269,6 +2343,8 @@ void adduplicate_armature(void) EditBone *firstDup=NULL; /* The beginning of the duplicated bones in the edbo list */ countall(); // flushes selection! + + preEditBoneDuplicate(&G.edbo); /* Select mirrored bones */ if (arm->flag & ARM_MIRROR_EDIT) { @@ -2282,6 +2358,7 @@ void adduplicate_armature(void) } } } + /* Find the selected bones and duplicate them as needed */ for (curBone=G.edbo.first; curBone && curBone!=firstDup; curBone=curBone->next) { @@ -2356,12 +2433,12 @@ void adduplicate_armature(void) */ if (!curBone->parent) eBone->parent = NULL; - /* If this bone has a parent that IS selected, + /* If this bone has a parent that was duplicated, Set the duplicate->parent to the curBone->parent->duplicate */ - else if (curBone->parent->flag & BONE_SELECTED) + else if (curBone->parent->temp) eBone->parent= (EditBone *)curBone->parent->temp; - /* If this bone has a parent that IS not selected, + /* If this bone has a parent that was not duplicated, Set the duplicate->parent to the curBone->parent */ else { @@ -2371,7 +2448,7 @@ void adduplicate_armature(void) /* Lets try to fix any constraint subtargets that might have been duplicated */ - update_dup_subtarget(eBone); + updateDuplicateSubtarget(eBone, OBACT); } } } diff --git a/source/blender/src/editarmature_retarget.c b/source/blender/src/editarmature_retarget.c index 51e1e789d8e..eef8c743823 100644 --- a/source/blender/src/editarmature_retarget.c +++ b/source/blender/src/editarmature_retarget.c @@ -93,8 +93,7 @@ typedef enum typedef enum { METHOD_BRUTE_FORCE = 0, - METHOD_MEMOIZE = 1, - METHOD_ANNEALING = 2 + METHOD_MEMOIZE = 1 } RetargetMethod; typedef enum @@ -374,6 +373,155 @@ static void RIG_addEdgeToArc(RigArc *arc, float tail[3], EditBone *bone) RIG_appendEdgeToArc(arc, edge); } +/************************************** CLONING TEMPLATES **********************************************/ + +static RigControl *cloneControl(RigGraph *rg, RigControl *src_ctrl, GHash *ptr_hash) +{ + RigControl *ctrl; + + ctrl = newRigControl(rg); + + VECCOPY(ctrl->head, src_ctrl->head); + VECCOPY(ctrl->tail, src_ctrl->tail); + VECCOPY(ctrl->up_axis, src_ctrl->up_axis); + VECCOPY(ctrl->offset, src_ctrl->offset); + + ctrl->flag = src_ctrl->flag; + + ctrl->bone = duplicateEditBone(src_ctrl->bone, rg->editbones, rg->ob); + ctrl->bone->flag &= ~(BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL); + BLI_ghash_insert(ptr_hash, src_ctrl->bone, ctrl->bone); + + ctrl->link = src_ctrl->link; + + return ctrl; +} + +static RigArc *cloneArc(RigGraph *rg, RigArc *src_arc, GHash *ptr_hash) +{ + RigEdge *src_edge; + RigArc *arc; + + arc = newRigArc(rg); + + arc->head = BLI_ghash_lookup(ptr_hash, src_arc->head); + arc->tail = BLI_ghash_lookup(ptr_hash, src_arc->tail); + + arc->head->degree++; + arc->tail->degree++; + + arc->length = src_arc->length; + + arc->count = src_arc->count; + + for (src_edge = src_arc->edges.first; src_edge; src_edge = src_edge->next) + { + RigEdge *edge; + + edge = MEM_callocN(sizeof(RigEdge), "rig edge"); + + VECCOPY(edge->head, src_edge->head); + VECCOPY(edge->tail, src_edge->tail); + VECCOPY(edge->up_axis, src_edge->up_axis); + + edge->length = src_edge->length; + edge->angle = src_edge->angle; + + if (src_edge->bone != NULL) + { + edge->bone = duplicateEditBone(src_edge->bone, rg->editbones, rg->ob); + edge->bone->flag &= ~(BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL); + BLI_ghash_insert(ptr_hash, src_edge->bone, edge->bone); + } + + BLI_addtail(&arc->edges, edge); + } + + return arc; +} + +static RigGraph *cloneRigGraph(RigGraph *src) +{ + GHash *ptr_hash; + RigNode *node; + RigArc *arc; + RigControl *ctrl; + RigGraph *rg; + + ptr_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + + rg = newRigGraph(); + + rg->ob = src->ob; + rg->editbones = src->editbones; + + preEditBoneDuplicate(rg->editbones); /* prime bones for duplication */ + + /* Clone nodes */ + for (node = src->nodes.first; node; node = node->next) + { + RigNode *cloned_node = newRigNode(rg, node->p); + BLI_ghash_insert(ptr_hash, node, cloned_node); + } + + rg->head = BLI_ghash_lookup(ptr_hash, src->head); + + /* Clone arcs */ + for (arc = src->arcs.first; arc; arc = arc->next) + { + cloneArc(rg, arc, ptr_hash); + } + + /* Clone controls */ + for (ctrl = src->controls.first; ctrl; ctrl = ctrl->next) + { + cloneControl(rg, ctrl, ptr_hash); + } + + /* Relink bones properly */ + for (arc = rg->arcs.first; arc; arc = arc->next) + { + RigEdge *edge; + + for (edge = arc->edges.first; edge; edge = edge->next) + { + if (edge->bone != NULL) + { + EditBone *bone; + + updateDuplicateSubtarget(edge->bone, rg->ob); + + bone = BLI_ghash_lookup(ptr_hash, edge->bone->parent); + + if (bone != NULL) + { + edge->bone->parent = bone; + } + } + } + } + + for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next) + { + EditBone *bone; + + updateDuplicateSubtarget(ctrl->bone, rg->ob); + + bone = BLI_ghash_lookup(ptr_hash, ctrl->bone->parent); + + if (bone != NULL) + { + ctrl->bone->parent = bone; + } + + ctrl->link = BLI_ghash_lookup(ptr_hash, ctrl->link); + } + + BLI_ghash_free(ptr_hash, NULL, NULL); + + return rg; +} + /*******************************************************************************************************/ @@ -606,8 +754,6 @@ static void RIG_reconnectControlBones(RigGraph *rg) { change = 0; - printf("-------------------------\n"); - for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next) { /* if control is not linked yet */ @@ -1577,29 +1723,6 @@ static RetargetMode detectArcRetargetMode(RigArc *iarc) } #ifndef USE_THREADS -static void printCostCube(float *cost_cube, int nb_joints) -{ - int i; - - for (i = 0; i < nb_joints; i++) - { - printf("%0.3f ", cost_cube[3 * i]); - } - printf("\n"); - - for (i = 0; i < nb_joints; i++) - { - printf("%0.3f ", cost_cube[3 * i + 1]); - } - printf("\n"); - - for (i = 0; i < nb_joints; i++) - { - printf("%0.3f ", cost_cube[3 * i + 2]); - } - printf("\n"); -} - static void printMovesNeeded(int *positions, int nb_positions) { int moves = 0; @@ -1746,187 +1869,6 @@ static float calcCostAngleLengthDistance(ReebArcIterator *iter, float **vec_cach return new_cost; } -static float calcCost(ReebArcIterator *iter, RigEdge *e1, RigEdge *e2, float *vec0, float *vec1, float *vec2, int i0, int i1, int i2) -{ - float vec_second[3], vec_first[3]; - float length1, length2; - float new_cost = 0; - - VecSubf(vec_second, vec2, vec1); - length2 = Normalize(vec_second); - - VecSubf(vec_first, vec1, vec0); - length1 = Normalize(vec_first); - - /* Angle cost */ - new_cost += costAngle(e1->angle, vec_first, vec_second); - - /* Length cost */ - new_cost += costLength(e1->length, length1); - new_cost += costLength(e2->length, length2); - - /* Distance cost */ - new_cost += costDistance(iter, vec0, vec1, i0, i1); - new_cost += costDistance(iter, vec1, vec2, i1, i2); - - return new_cost; -} - -static void calcGradient(RigEdge *e1, RigEdge *e2, ReebArcIterator *iter, int index, int nb_joints, float *cost_cube, int *positions, float **vec_cache) -{ - EmbedBucket *bucket = NULL; - float *vec0, *vec1, *vec2; - float current_cost; - int i0, i1, i2; - int next_position; - - vec0 = vec_cache[index]; - vec1 = vec_cache[index + 1]; - vec2 = vec_cache[index + 2]; - - if (index == 0) - { - i0 = 0; - } - else - { - i0 = positions[index - 1]; - } - - i1 = positions[index]; - - if (index +1 == nb_joints) - { - i2 = iter->length; - } - else - { - i2 = positions[index + 1]; - } - - - current_cost = calcCost(iter, e1, e2, vec0, vec1, vec2, i0, i1, i2); - cost_cube[index * 3 + 1] = current_cost; - - next_position = positions[index] + 1; - - if (index + 1 < nb_joints && next_position == positions[index + 1]) - { - cost_cube[index * 3 + 2] = MAX_COST; - } - else if (next_position > iter->length) /* positions are indexed at 1, so length is last */ - { - cost_cube[index * 3 + 2] = MAX_COST; - } - else - { - bucket = peekBucket(iter, next_position); - - if (bucket == NULL) - { - cost_cube[index * 3 + 2] = MAX_COST; - } - else - { - vec1 = bucket->p; - - cost_cube[index * 3 + 2] = calcCost(iter, e1, e2, vec0, vec1, vec2, i0, next_position, i2) - current_cost; - } - } - - next_position = positions[index] - 1; - - if (index - 1 > -1 && next_position == positions[index - 1]) - { - cost_cube[index * 3] = MAX_COST; - } - else if (next_position < 1) /* positions are indexed at 1, so 1 is first */ - { - cost_cube[index * 3] = MAX_COST; - } - else - { - bucket = peekBucket(iter, next_position); - - if (bucket == NULL) - { - cost_cube[index * 3] = MAX_COST; - } - else - { - vec1 = bucket->p; - - cost_cube[index * 3] = calcCost(iter, e1, e2, vec0, vec1, vec2, i0, next_position, i2) - current_cost; - } - } -} - -static float probability(float delta_cost, float temperature) -{ - if (delta_cost < 0) - { - return 1; - } - else - { - return (float)exp(delta_cost / temperature); - } -} - -static int neighbour(int nb_joints, float *cost_cube, int *moving_joint, int *moving_direction) -{ - int total = 0; - int chosen = 0; - int i; - - for (i = 0; i < nb_joints; i++) - { - if (cost_cube[i * 3] < MAX_COST) - { - total++; - } - - if (cost_cube[i * 3 + 2] < MAX_COST) - { - total++; - } - } - - if (total == 0) - { - return 0; - } - - chosen = (int)(BLI_drand() * total); - - for (i = 0; i < nb_joints; i++) - { - if (cost_cube[i * 3] < MAX_COST) - { - if (chosen == 0) - { - *moving_joint = i; - *moving_direction = -1; - break; - } - chosen--; - } - - if (cost_cube[i * 3 + 2] < MAX_COST) - { - if (chosen == 0) - { - *moving_joint = i; - *moving_direction = 1; - break; - } - chosen--; - } - } - - return 1; -} - static int indexMemoNode(int nb_positions, int previous, int current, int joints_left) { return joints_left * nb_positions * nb_positions + current * nb_positions + previous; @@ -2050,7 +1992,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino int *positions; int nb_edges = BLI_countlist(&iarc->edges); int nb_joints = nb_edges - 1; - RetargetMethod method = G.scene->toolsettings->skgen_optimisation_method; + RetargetMethod method = METHOD_MEMOIZE; int i; if (nb_joints > earc->bcount) @@ -2261,114 +2203,6 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino } } } - /* SIMULATED ANNEALING */ - else if (method == METHOD_ANNEALING) - { - RigEdge *previous; - float *cost_cube; - float cost; - int k; - int kmax; - - kmax = 100000; - - BLI_srand(nb_joints); - - /* [joint: index][position: -1, 0, +1] */ - cost_cube = MEM_callocN(sizeof(float) * 3 * nb_joints, "Cost Cube"); - - initArcIterator(&iter, earc, node_start); - - /* init vec_cache */ - for (i = 0; i < nb_joints; i++) - { - bucket = peekBucket(&iter, positions[i]); - vec_cache[i + 1] = bucket->p; - } - - cost = 0; - - /* init cost cube */ - for (previous = iarc->edges.first, edge = previous->next, i = 0; - edge; - previous = edge, edge = edge->next, i += 1) - { - calcGradient(previous, edge, &iter, i, nb_joints, cost_cube, positions, vec_cache); - - cost += cost_cube[3 * i + 1]; - } - -#ifndef USE_THREADS - printf("initial cost: %f\n", cost); - printf("kmax: %i\n", kmax); -#endif - - for (k = 0; k < kmax; k++) - { - int status; - int moving_joint = -1; - int move_direction = -1; - float delta_cost; - float temperature; - - status = neighbour(nb_joints, cost_cube, &moving_joint, &move_direction); - - if (status == 0) - { - /* if current state is still a minimum, copy it */ - if (cost < min_cost) - { - min_cost = cost; - memcpy(best_positions, positions, sizeof(int) * nb_joints); - } - break; - } - - delta_cost = cost_cube[moving_joint * 3 + (1 + move_direction)]; - - temperature = 1 - (float)k / (float)kmax; - if (probability(delta_cost, temperature) > BLI_frand()) - { - /* update position */ - positions[moving_joint] += move_direction; - - /* update vector cache */ - bucket = peekBucket(&iter, positions[moving_joint]); - vec_cache[moving_joint + 1] = bucket->p; - - cost += delta_cost; - - /* cost optimizing */ - if (cost < min_cost) - { - min_cost = cost; - memcpy(best_positions, positions, sizeof(int) * nb_joints); - } - - /* update cost cube */ - for (previous = iarc->edges.first, edge = previous->next, i = 0; - edge; - previous = edge, edge = edge->next, i += 1) - { - if (i == moving_joint - 1 || - i == moving_joint || - i == moving_joint + 1) - { - calcGradient(previous, edge, &iter, i, nb_joints, cost_cube, positions, vec_cache); - } - } - } - } - - //min_cost = cost; - //memcpy(best_positions, positions, sizeof(int) * nb_joints); - -// printf("k = %i\n", k); - - - MEM_freeN(cost_cube); - } - vec0 = node_start->p; initArcIterator(&iter, earc, node_start); @@ -2793,6 +2627,13 @@ static void retargetSubgraph(RigGraph *rigg, RigArc *start_arc, RigNode *start_n } } +static void finishRetarget(RigGraph *rigg) +{ +#ifdef USE_THREADS + BLI_end_worker(rigg->worker); +#endif +} + static void adjustGraphs(RigGraph *rigg) { RigArc *arc; @@ -2805,9 +2646,7 @@ static void adjustGraphs(RigGraph *rigg) } } -#ifdef USE_THREADS - BLI_end_worker(rigg->worker); -#endif + finishRetarget(rigg); /* Turn the list into an armature */ editbones_to_armature(rigg->editbones, rigg->ob); @@ -2834,9 +2673,7 @@ static void retargetGraphs(RigGraph *rigg) //generateMissingArcs(rigg); -#ifdef USE_THREADS - BLI_end_worker(rigg->worker); -#endif + finishRetarget(rigg); /* Turn the list into an armature */ editbones_to_armature(rigg->editbones, rigg->ob); @@ -2927,6 +2764,7 @@ void BIF_retargetArmature() void BIF_retargetArc(ReebArc *earc) { Object *ob; + RigGraph *template; RigGraph *rigg; RigArc *iarc; bArmature *arm; @@ -2934,7 +2772,9 @@ void BIF_retargetArc(ReebArc *earc) ob = G.obedit; arm = ob->data; - rigg = armatureSelectedToGraph(ob, arm); + template = armatureSelectedToGraph(ob, arm); + + rigg = cloneRigGraph(template); iarc = rigg->arcs.first; @@ -2944,11 +2784,10 @@ void BIF_retargetArc(ReebArc *earc) retargetArctoArc(rigg, iarc, iarc->head); -#ifdef USE_THREADS - BLI_end_worker(rigg->worker); -#endif + finishRetarget(rigg); - //RIG_freeRigGraph((BGraph*)rigg); + RIG_freeRigGraph((BGraph*)template); + RIG_freeRigGraph((BGraph*)rigg); BIF_undo_push("Retarget Arc"); diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 0cd0cd8ff29..22173e469cf 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -34,6 +34,7 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" +#include "BLI_graph.h" #include "BKE_utildefines.h" #include "BKE_global.h" @@ -392,7 +393,7 @@ void retargetStroke(SK_Stroke *stk) MEM_freeN(arc->head); MEM_freeN(arc->tail); - REEB_freeArc(arc); + REEB_freeArc((BArc*)arc); } /**************************************************************/ @@ -771,6 +772,12 @@ void sk_drawStrokeSubdivision(SK_Stroke *stk) int head_index = -1; int i; + if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET) + { + return; + } + + for (i = 0; i < stk->nb_points; i++) { SK_Point *pt = stk->points + i; @@ -785,15 +792,15 @@ void sk_drawStrokeSubdivision(SK_Stroke *stk) { if (i - head_index > 1) { - if (G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION) + if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_CORRELATION) { drawSubdividedStrokeBy(stk, head_index, i, nextCorrelationSubdivision); } - else if (G.scene->toolsettings->skgen_options & SKGEN_CUT_LENGTH) + else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH) { drawSubdividedStrokeBy(stk, head_index, i, nextLengthSubdivision); } - else if (G.scene->toolsettings->skgen_options & SKGEN_CUT_FIXED) + else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED) { drawSubdividedStrokeBy(stk, head_index, i, nextFixedSubdivision); } @@ -1545,15 +1552,15 @@ void sk_convertStroke(SK_Stroke *stk) if (i - head_index > 1) { - if (G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION) + if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_CORRELATION) { bone = subdivideStrokeBy(stk, head_index, i, invmat, tmat, nextCorrelationSubdivision); } - else if (G.scene->toolsettings->skgen_options & SKGEN_CUT_LENGTH) + else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH) { bone = subdivideStrokeBy(stk, head_index, i, invmat, tmat, nextLengthSubdivision); } - else if (G.scene->toolsettings->skgen_options & SKGEN_CUT_FIXED) + else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED) { bone = subdivideStrokeBy(stk, head_index, i, invmat, tmat, nextFixedSubdivision); } @@ -2313,10 +2320,16 @@ int sk_paint(SK_Sketch *sketch, short mbut) if (G.scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK) { - retargetStroke(stk); -// sk_convertStroke(stk); -// sk_removeStroke(sketch, stk); -// BIF_undo_push("Convert Sketch"); + if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET) + { + retargetStroke(stk); + } + else + { + sk_convertStroke(stk); + } + sk_removeStroke(sketch, stk); + BIF_undo_push("Convert Sketch"); allqueue(REDRAWBUTSEDIT, 0); } diff --git a/source/blender/src/reeb.c b/source/blender/src/reeb.c index 5f80a2c7227..3678106e9ef 100644 --- a/source/blender/src/reeb.c +++ b/source/blender/src/reeb.c @@ -69,9 +69,6 @@ #include "reeb.h" -/* REPLACE WITH NEW ONE IN UTILDEFINES ONCE PATCH IS APPLIED */ -#define FTOCHAR(val) (val<=0.0f)? 0 : ((val>(1.0f-0.5f/255.0f))? 255 : (char)((255.0f*val)+0.5f)) - ReebGraph *GLOBAL_RG = NULL; ReebGraph *FILTERED_RG = NULL;