Lots of code cleanup and some new features.
Clean and split editbone duplication methods for easy reuse. Copy and retarget selected bones to stroke conversion method. This is the start of the infamous templating system. A simple demo video is available: http://blenderartists.org/~theeth/bf/etch-a-ton/retarget.ogv and http://vimeo.com/2111535 (for those who dislike ogg/theora)
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user