diff options
Diffstat (limited to 'source/blender/editors')
-rw-r--r-- | source/blender/editors/armature/BIF_generate.h | 49 | ||||
-rw-r--r-- | source/blender/editors/armature/BIF_retarget.h | 171 | ||||
-rw-r--r-- | source/blender/editors/armature/CMakeLists.txt | 7 | ||||
-rw-r--r-- | source/blender/editors/armature/armature_intern.h | 13 | ||||
-rw-r--r-- | source/blender/editors/armature/armature_ops.c | 27 | ||||
-rw-r--r-- | source/blender/editors/armature/armature_select.c | 4 | ||||
-rw-r--r-- | source/blender/editors/armature/armature_skinning.c | 4 | ||||
-rw-r--r-- | source/blender/editors/armature/armature_utils.c | 2 | ||||
-rw-r--r-- | source/blender/editors/armature/editarmature_generate.c | 305 | ||||
-rw-r--r-- | source/blender/editors/armature/editarmature_retarget.c | 2641 | ||||
-rw-r--r-- | source/blender/editors/armature/editarmature_sketch.c | 2651 | ||||
-rw-r--r-- | source/blender/editors/armature/reeb.c | 3201 | ||||
-rw-r--r-- | source/blender/editors/armature/reeb.h | 207 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_paint.c | 2 | ||||
-rw-r--r-- | source/blender/editors/include/ED_armature.h | 20 |
15 files changed, 1 insertions, 9303 deletions
diff --git a/source/blender/editors/armature/BIF_generate.h b/source/blender/editors/armature/BIF_generate.h deleted file mode 100644 index 71109574fe0..00000000000 --- a/source/blender/editors/armature/BIF_generate.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/editors/armature/BIF_generate.h - * \ingroup edarmature - */ - - -#ifndef __BIF_GENERATE_H__ -#define __BIF_GENERATE_H__ - -struct ToolSettings; -struct EditBone; -struct BArcIterator; -struct bArmature; -struct ListBase; - -typedef int (NextSubdivisionFunc)(struct ToolSettings *, struct BArcIterator *, int, int, float[3], float[3]); - -float calcArcCorrelation(struct BArcIterator *iter, int start, int end, float v0[3], float n[3]); - -int nextFixedSubdivision(struct ToolSettings *toolsettings, struct BArcIterator *iter, int start, int end, float head[3], float p[3]); -int nextLengthSubdivision(struct ToolSettings *toolsettings, struct BArcIterator *iter, int start, int end, float head[3], float p[3]); -int nextAdaptativeSubdivision(struct ToolSettings *toolsettings, struct BArcIterator *iter, int start, int end, float head[3], float p[3]); - -struct EditBone *subdivideArcBy(struct ToolSettings *toolsettings, struct bArmature *arm, ListBase *editbones, struct BArcIterator *iter, - float invmat[4][4], float tmat[3][3], NextSubdivisionFunc next_subdividion); - -void setBoneRollFromNormal(struct EditBone *bone, const float no[3], float invmat[4][4], float tmat[3][3]); - - -#endif /* __BIF_GENERATE_H__ */ diff --git a/source/blender/editors/armature/BIF_retarget.h b/source/blender/editors/armature/BIF_retarget.h deleted file mode 100644 index aa56f847f00..00000000000 --- a/source/blender/editors/armature/BIF_retarget.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/editors/armature/BIF_retarget.h - * \ingroup edarmature - */ - -#ifndef __BIF_RETARGET_H__ -#define __BIF_RETARGET_H__ - -#include "DNA_listBase.h" - -#include "BLI_graph.h" -#include "BLI_ghash.h" -#include "BLI_task.h" -#include "BLI_threads.h" - -#include "reeb.h" - -struct Object; -struct bArmature; -struct bContext; - -struct EditBone; - -struct RigGraph; -struct RigNode; -struct RigArc; -struct RigEdge; - -#define USE_THREADS - -typedef struct RigGraph { - ListBase arcs; - ListBase nodes; - - float length; - - FreeArc free_arc; - FreeNode free_node; - RadialSymmetry radial_symmetry; - AxialSymmetry axial_symmetry; - /*********************************/ - - int flag; - - ListBase controls; - ListBase *editbones; - - struct RigNode *head; - ReebGraph *link_mesh; - - - TaskScheduler *task_scheduler; - TaskPool *task_pool; - - GHash *bones_map; /* map of editbones by name */ - GHash *controls_map; /* map of rigcontrols by bone pointer */ - - struct Object *ob; -} RigGraph; - -typedef struct RigNode { - void *next, *prev; - float p[3]; - int flag; - - int degree; - struct BArc **arcs; - - int subgraph_index; - - int symmetry_level; - int symmetry_flag; - float symmetry_axis[3]; - /*********************************/ - - ReebNode *link_mesh; -} RigNode; - -typedef struct RigArc { - void *next, *prev; - RigNode *head, *tail; - int flag; - - float length; - - int symmetry_level; - int symmetry_group; - int symmetry_flag; - /*********************************/ - - ListBase edges; - int count; - ReebArc *link_mesh; -} RigArc; - -typedef struct RigEdge { - struct RigEdge *next, *prev; - float head[3], tail[3]; - float length; - float angle; /* angle to next edge */ - float up_angle; /* angle between up_axis and the joint normal (defined as Previous edge CrossProduct Current edge */ - struct EditBone *bone; - float up_axis[3]; -} RigEdge; - -/* Graph flags */ -#define RIG_FREE_BONELIST 1 - -/* Control flags */ -#define RIG_CTRL_HEAD_DONE 1 -#define RIG_CTRL_TAIL_DONE 2 -#define RIG_CTRL_PARENT_DEFORM 4 -#define RIG_CTRL_FIT_ROOT 8 -#define RIG_CTRL_FIT_BONE 16 - -#define RIG_CTRL_DONE (RIG_CTRL_HEAD_DONE | RIG_CTRL_TAIL_DONE) - -/* Control tail flags */ -typedef enum { - TL_NONE = 0, - TL_TAIL, - TL_HEAD -} LinkTailMode; - -typedef struct RigControl { - struct RigControl *next, *prev; - float head[3], tail[3]; - struct EditBone *bone; - struct EditBone *link; - struct EditBone *link_tail; - float up_axis[3]; - float offset[3]; - float qrot[4]; /* for dual linked bones, store the rotation of the linked bone for the finalization */ - int flag; - LinkTailMode tail_mode; -} RigControl; - -void BIF_retargetArc(struct bContext *C, ReebArc *earc, RigGraph *template_rigg); -RigGraph *RIG_graphFromArmature(const struct bContext *C, struct Object *ob, struct bArmature *arm); -int RIG_nbJoints(RigGraph *rg); -const char *RIG_nameBone(RigGraph *rg, int arc_index, int bone_index); -void RIG_freeRigGraph(BGraph *rg); - -/* UNUSED */ -void BIF_retargetArmature(bContext *C); -void BIF_adjustRetarget(bContext *C); -/* UNUSED / print funcs */ -void RIG_printArc(struct RigGraph *rg, struct RigArc *arc); -void RIG_printGraph(struct RigGraph *rg); -void RIG_printArcBones(struct RigArc *arc); - -#endif /* __BIF_RETARGET_H__ */ diff --git a/source/blender/editors/armature/CMakeLists.txt b/source/blender/editors/armature/CMakeLists.txt index 8a40ea3b383..96467ee2c2a 100644 --- a/source/blender/editors/armature/CMakeLists.txt +++ b/source/blender/editors/armature/CMakeLists.txt @@ -47,9 +47,6 @@ set(SRC armature_select.c armature_skinning.c armature_utils.c - editarmature_generate.c - editarmature_retarget.c - editarmature_sketch.c editarmature_undo.c meshlaplacian.c pose_edit.c @@ -59,13 +56,9 @@ set(SRC pose_slide.c pose_transform.c pose_utils.c - reeb.c - BIF_generate.h - BIF_retarget.h armature_intern.h meshlaplacian.h - reeb.h ) if(WITH_INTERNATIONAL) diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h index 575d1597cc4..7bc8764443f 100644 --- a/source/blender/editors/armature/armature_intern.h +++ b/source/blender/editors/armature/armature_intern.h @@ -139,18 +139,6 @@ void POSE_OT_quaternions_flip(struct wmOperatorType *ot); void POSE_OT_bone_layers(struct wmOperatorType *ot); /* ******************************************************* */ -/* Etch-A-Ton (Skeleton Sketching) Operators */ - -void SKETCH_OT_gesture(struct wmOperatorType *ot); -void SKETCH_OT_delete(struct wmOperatorType *ot); -void SKETCH_OT_draw_stroke(struct wmOperatorType *ot); -void SKETCH_OT_draw_preview(struct wmOperatorType *ot); -void SKETCH_OT_finish_stroke(struct wmOperatorType *ot); -void SKETCH_OT_cancel_stroke(struct wmOperatorType *ot); -void SKETCH_OT_convert(struct wmOperatorType *ot); -void SKETCH_OT_select(struct wmOperatorType *ot); - -/* ******************************************************* */ /* Pose Tool Utilities (for PoseLib, Pose Sliding, etc.) */ /* pose_utils.c */ @@ -225,7 +213,6 @@ void POSE_OT_propagate(struct wmOperatorType *ot); */ EditBone *make_boneList(struct ListBase *edbo, struct ListBase *bones, struct EditBone *parent, struct Bone *actBone); -bool BIF_sk_selectStroke(struct bContext *C, const int mval[2], const bool extend); /* duplicate method */ void preEditBoneDuplicate(struct ListBase *editbones); diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c index 5622cd0437d..c9cebadb47d 100644 --- a/source/blender/editors/armature/armature_ops.c +++ b/source/blender/editors/armature/armature_ops.c @@ -85,16 +85,6 @@ void ED_operatortypes_armature(void) WM_operatortype_append(ARMATURE_OT_armature_layers); WM_operatortype_append(ARMATURE_OT_bone_layers); - /* SKETCH */ - WM_operatortype_append(SKETCH_OT_gesture); - WM_operatortype_append(SKETCH_OT_delete); - WM_operatortype_append(SKETCH_OT_draw_stroke); - WM_operatortype_append(SKETCH_OT_draw_preview); - WM_operatortype_append(SKETCH_OT_finish_stroke); - WM_operatortype_append(SKETCH_OT_cancel_stroke); - WM_operatortype_append(SKETCH_OT_convert); - WM_operatortype_append(SKETCH_OT_select); - /* POSE */ WM_operatortype_append(POSE_OT_hide); WM_operatortype_append(POSE_OT_reveal); @@ -203,23 +193,6 @@ void ED_keymap_armature(wmKeyConfig *keyconf) /* Armature ------------------------ */ keymap = WM_keymap_find(keyconf, "Armature", 0, 0); keymap->poll = ED_operator_editarmature; - - /* Armature -> Etch-A-Ton ------------------------ */ - WM_keymap_add_item(keymap, "SKETCH_OT_delete", XKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "SKETCH_OT_delete", DELKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "SKETCH_OT_finish_stroke", RIGHTMOUSE, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "SKETCH_OT_cancel_stroke", ESCKEY, KM_PRESS, 0, 0); - /* Already part of view3d select */ - //WM_keymap_add_item(keymap, "SKETCH_OT_select", SELECTMOUSE, KM_PRESS, 0, 0); - - /* sketch poll checks mode */ - WM_keymap_add_item(keymap, "SKETCH_OT_gesture", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "SKETCH_OT_draw_stroke", LEFTMOUSE, KM_PRESS, 0, 0); - kmi = WM_keymap_add_item(keymap, "SKETCH_OT_draw_stroke", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); - RNA_boolean_set(kmi->ptr, "snap", true); - WM_keymap_add_item(keymap, "SKETCH_OT_draw_preview", MOUSEMOVE, KM_ANY, 0, 0); - kmi = WM_keymap_add_item(keymap, "SKETCH_OT_draw_preview", MOUSEMOVE, KM_ANY, KM_CTRL, 0); - RNA_boolean_set(kmi->ptr, "snap", true); /* only set in editmode armature, by space_view3d listener */ kmi = WM_keymap_add_item(keymap, "ARMATURE_OT_hide", HKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index 2c6b84c2aef..af0483cf1dc 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -625,10 +625,6 @@ bool ED_armature_edit_select_pick(bContext *C, const int mval[2], bool extend, b vc.mval[0] = mval[0]; vc.mval[1] = mval[1]; - if (BIF_sk_selectStroke(C, mval, extend)) { - return true; - } - nearBone = get_nearest_editbonepoint(&vc, true, true, &basact, &selmask); if (nearBone) { ED_view3d_viewcontext_init_object(&vc, basact->object); diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c index c98eb9218cc..1722cbd5c5c 100644 --- a/source/blender/editors/armature/armature_skinning.c +++ b/source/blender/editors/armature/armature_skinning.c @@ -60,10 +60,6 @@ #include "armature_intern.h" #include "meshlaplacian.h" -#if 0 -#include "reeb.h" -#endif - /* ********************************** Bone Skinning *********************************************** */ static int bone_skinnable_cb(Object *UNUSED(ob), Bone *bone, void *datap) diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c index c4580a370c9..ffa8b9f5007 100644 --- a/source/blender/editors/armature/armature_utils.c +++ b/source/blender/editors/armature/armature_utils.c @@ -716,8 +716,6 @@ void ED_armature_to_edit(bArmature *arm) ED_armature_edit_free(arm); arm->edbo = MEM_callocN(sizeof(ListBase), "edbo armature"); arm->act_edbone = make_boneList(arm->edbo, &arm->bonebase, NULL, arm->act_bone); - -// BIF_freeTemplates(); /* force template update when entering editmode */ } /* *************************************************************** */ diff --git a/source/blender/editors/armature/editarmature_generate.c b/source/blender/editors/armature/editarmature_generate.c deleted file mode 100644 index 57843265496..00000000000 --- a/source/blender/editors/armature/editarmature_generate.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/editors/armature/editarmature_generate.c - * \ingroup edarmature - */ - -#include "DNA_scene_types.h" -#include "DNA_armature_types.h" - -#include "BLI_math.h" -#include "BLI_graph.h" - -#include "ED_armature.h" -#include "BIF_generate.h" - -void setBoneRollFromNormal(EditBone *bone, const float no[3], float UNUSED(invmat[4][4]), float tmat[3][3]) -{ - if (no != NULL && !is_zero_v3(no)) { - float normal[3]; - - copy_v3_v3(normal, no); - mul_m3_v3(tmat, normal); - - bone->roll = ED_armature_ebone_roll_to_vector(bone, normal, false); - } -} - -float calcArcCorrelation(BArcIterator *iter, int start, int end, float v0[3], float n[3]) -{ - int len = 2 + abs(end - start); - - if (len > 2) { - float avg_t = 0.0f; - float s_t = 0.0f; - float s_xyz = 0.0f; - int i; - - /* First pass, calculate average */ - for (i = start; i <= end; i++) { - float v[3]; - - IT_peek(iter, i); - sub_v3_v3v3(v, iter->p, v0); - avg_t += dot_v3v3(v, n); - } - - avg_t /= dot_v3v3(n, n); - avg_t += 1.0f; /* adding start (0) and end (1) values */ - avg_t /= len; - - /* Second pass, calculate s_xyz and s_t */ - for (i = start; i <= end; i++) { - float v[3], d[3]; - float dt; - - IT_peek(iter, i); - sub_v3_v3v3(v, iter->p, v0); - project_v3_v3v3(d, v, n); - sub_v3_v3(v, d); - - dt = len_v3(d) - avg_t; - - s_t += dt * dt; - s_xyz += dot_v3v3(v, v); - } - - /* adding start(0) and end(1) values to s_t */ - s_t += (avg_t * avg_t) + (1 - avg_t) * (1 - avg_t); - - return 1.0f - s_xyz / s_t; - } - else { - return 1.0f; - } -} - -int nextFixedSubdivision(ToolSettings *toolsettings, BArcIterator *iter, int start, int end, float UNUSED(head[3]), float p[3]) -{ - static float stroke_length = 0; - static float current_length; - static char n; - float *v1, *v2; - float length_threshold; - int i; - - if (stroke_length == 0) { - current_length = 0; - - IT_peek(iter, start); - v1 = iter->p; - - for (i = start + 1; i <= end; i++) { - IT_peek(iter, i); - v2 = iter->p; - - stroke_length += len_v3v3(v1, v2); - - v1 = v2; - } - - n = 0; - current_length = 0; - } - - n++; - - length_threshold = n * stroke_length / toolsettings->skgen_subdivision_number; - - IT_peek(iter, start); - v1 = iter->p; - - /* < and not <= because we don't care about end, it is P_EXACT anyway */ - for (i = start + 1; i < end; i++) { - IT_peek(iter, i); - v2 = iter->p; - - current_length += len_v3v3(v1, v2); - - if (current_length >= length_threshold) { - copy_v3_v3(p, v2); - return i; - } - - v1 = v2; - } - - stroke_length = 0; - - return -1; -} -int nextAdaptativeSubdivision(ToolSettings *toolsettings, BArcIterator *iter, int start, int end, float head[3], float p[3]) -{ - float correlation_threshold = toolsettings->skgen_correlation_limit; - float *start_p; - float n[3]; - int i; - - IT_peek(iter, start); - start_p = iter->p; - - for (i = start + 2; i <= end; i++) { - /* Calculate normal */ - IT_peek(iter, i); - sub_v3_v3v3(n, iter->p, head); - - if (calcArcCorrelation(iter, start, i, start_p, n) < correlation_threshold) { - IT_peek(iter, i - 1); - copy_v3_v3(p, iter->p); - return i - 1; - } - } - - return -1; -} - -int nextLengthSubdivision(ToolSettings *toolsettings, BArcIterator *iter, int start, int end, float head[3], float p[3]) -{ - float lengthLimit = toolsettings->skgen_length_limit; - int same = 1; - int i; - - i = start + 1; - while (i <= end) { - float *vec0; - float *vec1; - - IT_peek(iter, i - 1); - vec0 = iter->p; - - IT_peek(iter, i); - vec1 = iter->p; - - /* If lengthLimit hits the current segment */ - if (len_v3v3(vec1, head) > lengthLimit) { - if (same == 0) { - float dv[3], off[3]; - float a, b, c, f; - - /* Solve quadratic distance equation */ - sub_v3_v3v3(dv, vec1, vec0); - a = dot_v3v3(dv, dv); - - sub_v3_v3v3(off, vec0, head); - b = 2 * dot_v3v3(dv, off); - - c = dot_v3v3(off, off) - (lengthLimit * lengthLimit); - - f = (-b + sqrtf(b * b - 4 * a * c)) / (2 * a); - - //printf("a %f, b %f, c %f, f %f\n", a, b, c, f); - - if (isnan(f) == 0 && f < 1.0f) { - copy_v3_v3(p, dv); - mul_v3_fl(p, f); - add_v3_v3(p, vec0); - } - else { - copy_v3_v3(p, vec1); - } - } - else { - float dv[3]; - - sub_v3_v3v3(dv, vec1, vec0); - normalize_v3(dv); - - copy_v3_v3(p, dv); - mul_v3_fl(p, lengthLimit); - add_v3_v3(p, head); - } - - return i - 1; /* restart at lower bound */ - } - else { - i++; - same = 0; // Reset same - } - } - - return -1; -} - -EditBone *subdivideArcBy(ToolSettings *toolsettings, bArmature *arm, ListBase *UNUSED(editbones), BArcIterator *iter, - float invmat[4][4], float tmat[3][3], NextSubdivisionFunc next_subdividion) -{ - EditBone *lastBone = NULL; - EditBone *child = NULL; - EditBone *parent = NULL; - float *normal = NULL; - float size_buffer = 1.2; - int bone_start = 0; - int end = iter->length; - int index; - - IT_head(iter); - - parent = ED_armature_ebone_add(arm, "Bone"); - copy_v3_v3(parent->head, iter->p); - - if (iter->size > FLT_EPSILON) { - parent->rad_head = iter->size * size_buffer; - } - - normal = iter->no; - - index = next_subdividion(toolsettings, iter, bone_start, end, parent->head, parent->tail); - while (index != -1) { - IT_peek(iter, index); - - child = ED_armature_ebone_add(arm, "Bone"); - copy_v3_v3(child->head, parent->tail); - child->parent = parent; - child->flag |= BONE_CONNECTED; - - if (iter->size > FLT_EPSILON) { - child->rad_head = iter->size * size_buffer; - parent->rad_tail = iter->size * size_buffer; - } - - /* going to next bone, fix parent */ - mul_m4_v3(invmat, parent->tail); - mul_m4_v3(invmat, parent->head); - setBoneRollFromNormal(parent, normal, invmat, tmat); - - parent = child; // new child is next parent - bone_start = index; // start next bone from current index - - normal = iter->no; /* use normal at head, not tail */ - - index = next_subdividion(toolsettings, iter, bone_start, end, parent->head, parent->tail); - } - - iter->tail(iter); - - copy_v3_v3(parent->tail, iter->p); - if (iter->size > FLT_EPSILON) { - parent->rad_tail = iter->size * size_buffer; - } - - /* fix last bone */ - mul_m4_v3(invmat, parent->tail); - mul_m4_v3(invmat, parent->head); - setBoneRollFromNormal(parent, iter->no, invmat, tmat); - lastBone = parent; - - return lastBone; -} diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c deleted file mode 100644 index 6b2893780d7..00000000000 --- a/source/blender/editors/armature/editarmature_retarget.c +++ /dev/null @@ -1,2641 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributor(s): Martin Poirier - * - * ***** END GPL LICENSE BLOCK ***** - * autoarmature.c: Interface for automagically manipulating armature (retarget, created, ...) - */ - -/** \file blender/editors/armature/editarmature_retarget.c - * \ingroup edarmature - */ - -#include "MEM_guardedalloc.h" - -#include "PIL_time.h" - -#include "DNA_armature_types.h" -#include "DNA_constraint_types.h" -#include "DNA_scene_types.h" -#include "DNA_object_types.h" - -#include "BLI_blenlib.h" -#include "BLI_math.h" - -#include "BKE_constraint.h" -#include "BKE_armature.h" -#include "BKE_context.h" - -#include "ED_armature.h" -#include "ED_undo.h" - -#include "BIF_retarget.h" - -#include "armature_intern.h" - -/************ RIG RETARGET DATA STRUCTURES ***************/ - -typedef struct MemoNode { - float weight; - int next; -} MemoNode; - -typedef struct RetargetParam { - RigGraph *rigg; - RigArc *iarc; - RigNode *inode_start; - bContext *context; -} RetargetParam; - -typedef enum { - RETARGET_LENGTH, - RETARGET_AGGRESSIVE -} RetargetMode; - -typedef enum { - METHOD_BRUTE_FORCE = 0, - METHOD_MEMOIZE = 1 -} RetargetMethod; - -typedef enum { - ARC_FREE = 0, - ARC_TAKEN = 1, - ARC_USED = 2 -} ArcUsageFlags; - -static RigGraph *GLOBAL_RIGG = NULL; - -/*******************************************************************************************************/ - -void exec_retargetArctoArc(TaskPool * __restrict pool, void *taskdata, int threadid); - -static void RIG_calculateEdgeAngles(RigEdge *edge_first, RigEdge *edge_second); -float rollBoneByQuat(EditBone *bone, float old_up_axis[3], float qrot[4]); - -/* two levels */ -#define SHAPE_LEVELS (SHAPE_RADIX * SHAPE_RADIX) - -/*********************************** EDITBONE UTILS ****************************************************/ - -static int countEditBoneChildren(ListBase *list, EditBone *parent) -{ - EditBone *ebone; - int count = 0; - - for (ebone = list->first; ebone; ebone = ebone->next) { - if (ebone->parent == parent) { - count++; - } - } - - return count; -} - -static EditBone *nextEditBoneChild(ListBase *list, EditBone *parent, int n) -{ - EditBone *ebone; - - for (ebone = list->first; ebone; ebone = ebone->next) { - if (ebone->parent == parent) { - if (n == 0) { - return ebone; - } - n--; - } - } - - return NULL; -} - -static void getEditBoneRollUpAxis(EditBone *bone, float roll, float up_axis[3]) -{ - float mat[3][3], nor[3]; - - sub_v3_v3v3(nor, bone->tail, bone->head); - - vec_roll_to_mat3(nor, roll, mat); - copy_v3_v3(up_axis, mat[2]); -} - -static float rollBoneByQuatAligned(EditBone *bone, float old_up_axis[3], float qrot[4], float qroll[4], float aligned_axis[3]) -{ - float nor[3], new_up_axis[3], x_axis[3], z_axis[3]; - - copy_v3_v3(new_up_axis, old_up_axis); - mul_qt_v3(qrot, new_up_axis); - - sub_v3_v3v3(nor, bone->tail, bone->head); - - cross_v3_v3v3(x_axis, nor, aligned_axis); - cross_v3_v3v3(z_axis, x_axis, nor); - - normalize_v3(new_up_axis); - normalize_v3(x_axis); - normalize_v3(z_axis); - - if (dot_v3v3(new_up_axis, x_axis) < 0) { - negate_v3(x_axis); - } - - if (dot_v3v3(new_up_axis, z_axis) < 0) { - negate_v3(z_axis); - } - - if (angle_normalized_v3v3(x_axis, new_up_axis) < angle_normalized_v3v3(z_axis, new_up_axis)) { - rotation_between_vecs_to_quat(qroll, new_up_axis, x_axis); /* set roll rotation quat */ - return ED_armature_ebone_roll_to_vector(bone, x_axis, false); - } - else { - rotation_between_vecs_to_quat(qroll, new_up_axis, z_axis); /* set roll rotation quat */ - return ED_armature_ebone_roll_to_vector(bone, z_axis, false); - } -} - -static float rollBoneByQuatJoint(RigEdge *edge, RigEdge *previous, float qrot[4], float qroll[4], float up_axis[3]) -{ - if (previous == NULL) { - /* default to up_axis if no previous */ - return rollBoneByQuatAligned(edge->bone, edge->up_axis, qrot, qroll, up_axis); - } - else { - float new_up_axis[3]; - float vec_first[3], vec_second[3], normal[3]; - - if (previous->bone) { - sub_v3_v3v3(vec_first, previous->bone->tail, previous->bone->head); - } - else if (previous->prev->bone) { - sub_v3_v3v3(vec_first, edge->bone->head, previous->prev->bone->tail); - } - else { - /* default to up_axis if first bone in the chain is an offset */ - return rollBoneByQuatAligned(edge->bone, edge->up_axis, qrot, qroll, up_axis); - } - - sub_v3_v3v3(vec_second, edge->bone->tail, edge->bone->head); - - normalize_v3(vec_first); - normalize_v3(vec_second); - - cross_v3_v3v3(normal, vec_first, vec_second); - normalize_v3(normal); - - axis_angle_to_quat(qroll, vec_second, edge->up_angle); - - mul_qt_v3(qroll, normal); - - copy_v3_v3(new_up_axis, edge->up_axis); - mul_qt_v3(qrot, new_up_axis); - - normalize_v3(new_up_axis); - - /* real qroll between normal and up_axis */ - rotation_between_vecs_to_quat(qroll, new_up_axis, normal); - - return ED_armature_ebone_roll_to_vector(edge->bone, normal, false); - } -} - -float rollBoneByQuat(EditBone *bone, float old_up_axis[3], float qrot[4]) -{ - float new_up_axis[3]; - - copy_v3_v3(new_up_axis, old_up_axis); - mul_qt_v3(qrot, new_up_axis); - - return ED_armature_ebone_roll_to_vector(bone, new_up_axis, false); -} - -/************************************ DESTRUCTORS ******************************************************/ - -static void RIG_freeRigArc(BArc *arc) -{ - BLI_freelistN(&((RigArc *)arc)->edges); -} - -void RIG_freeRigGraph(BGraph *rg) -{ - RigGraph *rigg = (RigGraph *)rg; - BNode *node; - BArc *arc; - - BLI_task_pool_free(rigg->task_pool); - BLI_task_scheduler_free(rigg->task_scheduler); - - if (rigg->link_mesh) { - REEB_freeGraph(rigg->link_mesh); - } - - for (arc = rg->arcs.first; arc; arc = arc->next) { - RIG_freeRigArc(arc); - } - BLI_freelistN(&rg->arcs); - - for (node = rg->nodes.first; node; node = node->next) { - BLI_freeNode(rg, (BNode *)node); - } - BLI_freelistN(&rg->nodes); - - BLI_freelistN(&rigg->controls); - - BLI_ghash_free(rigg->bones_map, NULL, NULL); - BLI_ghash_free(rigg->controls_map, NULL, NULL); - - if (rigg->flag & RIG_FREE_BONELIST) { - BLI_freelistN(rigg->editbones); - MEM_freeN(rigg->editbones); - } - - MEM_freeN(rg); -} - -/************************************* ALLOCATORS ******************************************************/ - -static RigGraph *newRigGraph(void) -{ - RigGraph *rg; - int totthread; - - rg = MEM_callocN(sizeof(RigGraph), "rig graph"); - - rg->head = NULL; - - rg->bones_map = BLI_ghash_str_new("newRigGraph bones gh"); - rg->controls_map = BLI_ghash_str_new("newRigGraph cont gh"); - - rg->free_arc = RIG_freeRigArc; - rg->free_node = NULL; - -#ifdef USE_THREADS - totthread = TASK_SCHEDULER_AUTO_THREADS; -#else - totthread = TASK_SCHEDULER_SINGLE_THREAD; -#endif - - rg->task_scheduler = BLI_task_scheduler_create(totthread); - rg->task_pool = BLI_task_pool_create(rg->task_scheduler, NULL); - - return rg; -} - -static RigArc *newRigArc(RigGraph *rg) -{ - RigArc *arc; - - arc = MEM_callocN(sizeof(RigArc), "rig arc"); - arc->count = 0; - BLI_addtail(&rg->arcs, arc); - - return arc; -} - -static RigControl *newRigControl(RigGraph *rg) -{ - RigControl *ctrl; - - ctrl = MEM_callocN(sizeof(RigControl), "rig control"); - - BLI_addtail(&rg->controls, ctrl); - - return ctrl; -} - -static RigNode *newRigNodeHead(RigGraph *rg, RigArc *arc, float p[3]) -{ - RigNode *node; - node = MEM_callocN(sizeof(RigNode), "rig node"); - BLI_addtail(&rg->nodes, node); - - copy_v3_v3(node->p, p); - node->degree = 1; - node->arcs = NULL; - - arc->head = node; - - return node; -} - -static void addRigNodeHead(RigGraph *UNUSED(rg), RigArc *arc, RigNode *node) -{ - node->degree++; - - arc->head = node; -} - -static RigNode *newRigNode(RigGraph *rg, float p[3]) -{ - RigNode *node; - node = MEM_callocN(sizeof(RigNode), "rig node"); - BLI_addtail(&rg->nodes, node); - - copy_v3_v3(node->p, p); - node->degree = 0; - node->arcs = NULL; - - return node; -} - -static RigNode *newRigNodeTail(RigGraph *rg, RigArc *arc, float p[3]) -{ - RigNode *node = newRigNode(rg, p); - - node->degree = 1; - arc->tail = node; - - return node; -} - -static void RIG_appendEdgeToArc(RigArc *arc, RigEdge *edge) -{ - BLI_addtail(&arc->edges, edge); - - if (edge->prev == NULL) { - copy_v3_v3(edge->head, arc->head->p); - } - else { - RigEdge *last_edge = edge->prev; - copy_v3_v3(edge->head, last_edge->tail); - RIG_calculateEdgeAngles(last_edge, edge); - } - - edge->length = len_v3v3(edge->head, edge->tail); - - arc->length += edge->length; - - arc->count += 1; -} - -static void RIG_addEdgeToArc(RigArc *arc, float tail[3], EditBone *bone) -{ - RigEdge *edge; - - edge = MEM_callocN(sizeof(RigEdge), "rig edge"); - - copy_v3_v3(edge->tail, tail); - edge->bone = bone; - - if (bone) { - getEditBoneRollUpAxis(bone, bone->roll, edge->up_axis); - } - - RIG_appendEdgeToArc(arc, edge); -} -/************************************** CLONING TEMPLATES **********************************************/ - -static void renameTemplateBone(char *name, char *template_name, ListBase *editbones, char *side_string, char *num_string) -{ - int i, j; - - for (i = 0, j = 0; i < (MAXBONENAME - 1) && j < (MAXBONENAME - 1) && template_name[i] != '\0'; i++) { - if (template_name[i] == '&') { - if (template_name[i + 1] == 'S' || template_name[i + 1] == 's') { - j += BLI_strncpy_rlen(name + j, side_string, MAXBONENAME); - i++; - } - else if (template_name[i + 1] == 'N' || template_name[i + 1] == 'n') { - j += BLI_strncpy_rlen(name + j, num_string, MAXBONENAME); - i++; - } - else { - name[j] = template_name[i]; - j++; - } - } - else { - name[j] = template_name[i]; - j++; - } - } - - name[j] = '\0'; - - ED_armature_ebone_unique_name(editbones, name, NULL); -} - -static RigControl *cloneControl(RigGraph *rg, RigGraph *src_rg, RigControl *src_ctrl, GHash *ptr_hash, char *side_string, char *num_string) -{ - RigControl *ctrl; - char name[MAXBONENAME]; - - ctrl = newRigControl(rg); - - copy_v3_v3(ctrl->head, src_ctrl->head); - copy_v3_v3(ctrl->tail, src_ctrl->tail); - copy_v3_v3(ctrl->up_axis, src_ctrl->up_axis); - copy_v3_v3(ctrl->offset, src_ctrl->offset); - - ctrl->tail_mode = src_ctrl->tail_mode; - ctrl->flag = src_ctrl->flag; - - renameTemplateBone(name, src_ctrl->bone->name, rg->editbones, side_string, num_string); - ctrl->bone = duplicateEditBoneObjects(src_ctrl->bone, name, rg->editbones, src_rg->ob, rg->ob); - ctrl->bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL); - BLI_ghash_insert(ptr_hash, src_ctrl->bone, ctrl->bone); - - ctrl->link = src_ctrl->link; - ctrl->link_tail = src_ctrl->link_tail; - - return ctrl; -} - -static RigArc *cloneArc(RigGraph *rg, RigGraph *src_rg, RigArc *src_arc, GHash *ptr_hash, char *side_string, char *num_string) -{ - 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"); - - copy_v3_v3(edge->head, src_edge->head); - copy_v3_v3(edge->tail, src_edge->tail); - copy_v3_v3(edge->up_axis, src_edge->up_axis); - - edge->length = src_edge->length; - edge->angle = src_edge->angle; - edge->up_angle = src_edge->up_angle; - - if (src_edge->bone != NULL) { - char name[MAXBONENAME]; - renameTemplateBone(name, src_edge->bone->name, rg->editbones, side_string, num_string); - edge->bone = duplicateEditBoneObjects(src_edge->bone, name, rg->editbones, src_rg->ob, rg->ob); - edge->bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL); - BLI_ghash_insert(ptr_hash, src_edge->bone, edge->bone); - } - - BLI_addtail(&arc->edges, edge); - } - - return arc; -} - -static RigGraph *cloneRigGraph(RigGraph *src, ListBase *editbones, Object *ob, char *side_string, char *num_string) -{ - GHash *ptr_hash; - RigNode *node; - RigArc *arc; - RigControl *ctrl; - RigGraph *rg; - - ptr_hash = BLI_ghash_ptr_new("cloneRigGraph gh"); - - rg = newRigGraph(); - - rg->ob = ob; - rg->editbones = editbones; - - preEditBoneDuplicate(rg->editbones); /* prime bones for duplication */ - preEditBoneDuplicate(src->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, src, arc, ptr_hash, side_string, num_string); - } - - /* Clone controls */ - for (ctrl = src->controls.first; ctrl; ctrl = ctrl->next) { - cloneControl(rg, src, ctrl, ptr_hash, side_string, num_string); - } - - /* 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; - - updateDuplicateSubtargetObjects(edge->bone, src->editbones, src->ob, rg->ob); - - if (edge->bone->parent) { - bone = BLI_ghash_lookup(ptr_hash, edge->bone->parent); - - if (bone != NULL) { - edge->bone->parent = bone; - } - else { - /* disconnect since parent isn't cloned - * this will only happen when cloning from selected bones - * */ - edge->bone->flag &= ~BONE_CONNECTED; - } - } - } - } - } - - for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next) { - EditBone *bone; - - updateDuplicateSubtargetObjects(ctrl->bone, src->editbones, src->ob, rg->ob); - - if (ctrl->bone->parent) { - bone = BLI_ghash_lookup(ptr_hash, ctrl->bone->parent); - - if (bone != NULL) { - ctrl->bone->parent = bone; - } - else { - /* disconnect since parent isn't cloned - * this will only happen when cloning from selected bones - * */ - ctrl->bone->flag &= ~BONE_CONNECTED; - } - } - - ctrl->link = BLI_ghash_lookup(ptr_hash, ctrl->link); - ctrl->link_tail = BLI_ghash_lookup(ptr_hash, ctrl->link_tail); - } - - BLI_ghash_free(ptr_hash, NULL, NULL); - - return rg; -} - - -/*******************************************************************************************************/ - -static void RIG_calculateEdgeAngles(RigEdge *edge_first, RigEdge *edge_second) -{ - float vec_first[3], vec_second[3]; - - sub_v3_v3v3(vec_first, edge_first->tail, edge_first->head); - sub_v3_v3v3(vec_second, edge_second->tail, edge_second->head); - - normalize_v3(vec_first); - normalize_v3(vec_second); - - edge_first->angle = angle_normalized_v3v3(vec_first, vec_second); - - if (edge_second->bone != NULL) { - float normal[3]; - - cross_v3_v3v3(normal, vec_first, vec_second); - normalize_v3(normal); - - edge_second->up_angle = angle_normalized_v3v3(normal, edge_second->up_axis); - } -} - -/************************************ CONTROL BONES ****************************************************/ - -static void RIG_addControlBone(RigGraph *rg, EditBone *bone) -{ - RigControl *ctrl = newRigControl(rg); - ctrl->bone = bone; - copy_v3_v3(ctrl->head, bone->head); - copy_v3_v3(ctrl->tail, bone->tail); - getEditBoneRollUpAxis(bone, bone->roll, ctrl->up_axis); - ctrl->tail_mode = TL_NONE; - - BLI_ghash_insert(rg->controls_map, bone->name, ctrl); -} - -static int RIG_parentControl(RigControl *ctrl, EditBone *link) -{ - if (link) { - float offset[3]; - int flag = 0; - - sub_v3_v3v3(offset, ctrl->bone->head, link->head); - - /* if root matches, check for direction too */ - if (dot_v3v3(offset, offset) < 0.0001f) { - float vbone[3], vparent[3]; - - flag |= RIG_CTRL_FIT_ROOT; - - sub_v3_v3v3(vbone, ctrl->bone->tail, ctrl->bone->head); - sub_v3_v3v3(vparent, link->tail, link->head); - - /* test for opposite direction */ - if (dot_v3v3(vbone, vparent) > 0) { - float nor[3]; - float len; - - cross_v3_v3v3(nor, vbone, vparent); - - len = dot_v3v3(nor, nor); - if (len < 0.0001f) { - flag |= RIG_CTRL_FIT_BONE; - } - } - } - - /* Bail out if old one is automatically better */ - if (flag < ctrl->flag) { - return 0; - } - - /* if there's already a link - * overwrite only if new link is higher in the chain */ - if (ctrl->link && flag == ctrl->flag) { - EditBone *bone = NULL; - - for (bone = ctrl->link; bone; bone = bone->parent) { - /* if link is in the chain, break and use that one */ - if (bone == link) { - break; - } - } - - /* not in chain, don't update link */ - if (bone == NULL) { - return 0; - } - } - - - ctrl->link = link; - ctrl->flag = flag; - - copy_v3_v3(ctrl->offset, offset); - - return 1; - } - - return 0; -} - -static void RIG_reconnectControlBones(RigGraph *rg) -{ - RigControl *ctrl; - bool changed = true; - - /* first pass, link to deform bones */ - for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next) { - bPoseChannel *pchan; - bConstraint *con; - int found = 0; - - /* DO SOME MAGIC HERE */ - for (pchan = rg->ob->pose->chanbase.first; pchan; pchan = pchan->next) { - for (con = pchan->constraints.first; con; con = con->next) { - const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); - ListBase targets = {NULL, NULL}; - bConstraintTarget *ct; - - /* constraint targets */ - if (cti && cti->get_constraint_targets) { - int target_index; - - cti->get_constraint_targets(con, &targets); - - for (target_index = 0, ct = targets.first; ct; target_index++, ct = ct->next) { - if ((ct->tar == rg->ob) && STREQ(ct->subtarget, ctrl->bone->name)) { - /* SET bone link to bone corresponding to pchan */ - EditBone *link = BLI_ghash_lookup(rg->bones_map, pchan->name); - - /* Making sure bone is in this armature */ - if (link != NULL) { - /* for pole targets, link to parent bone instead, if possible */ - if (con->type == CONSTRAINT_TYPE_KINEMATIC && target_index == 1) { - if (link->parent && BLI_ghash_haskey(rg->bones_map, link->parent->name)) { - link = link->parent; - } - } - - found = RIG_parentControl(ctrl, link); - } - } - } - - if (cti->flush_constraint_targets) - cti->flush_constraint_targets(con, &targets, 0); - } - } - } - - /* if not found yet, check parent */ - if (found == 0) { - if (ctrl->bone->parent) { - /* make sure parent is a deforming bone - * NULL if not - * */ - EditBone *link = BLI_ghash_lookup(rg->bones_map, ctrl->bone->parent->name); - - found = RIG_parentControl(ctrl, link); - } - - /* check if bone is not superposed on another one */ - { - RigArc *arc; - RigArc *best_arc = NULL; - EditBone *link = NULL; - - for (arc = rg->arcs.first; arc; arc = arc->next) { - RigEdge *edge; - for (edge = arc->edges.first; edge; edge = edge->next) { - if (edge->bone) { - int fit = 0; - - fit = len_v3v3(ctrl->bone->head, edge->bone->head) < 0.0001f; - fit = fit || len_v3v3(ctrl->bone->tail, edge->bone->tail) < 0.0001f; - - if (fit) { - /* pick the bone on the arc with the lowest symmetry level - * means you connect control to the trunk of the skeleton */ - if (best_arc == NULL || arc->symmetry_level < best_arc->symmetry_level) { - best_arc = arc; - link = edge->bone; - } - } - } - } - } - - found = RIG_parentControl(ctrl, link); - } - } - - /* if not found yet, check child */ - if (found == 0) { - RigArc *arc; - RigArc *best_arc = NULL; - EditBone *link = NULL; - - for (arc = rg->arcs.first; arc; arc = arc->next) { - RigEdge *edge; - for (edge = arc->edges.first; edge; edge = edge->next) { - if (edge->bone && edge->bone->parent == ctrl->bone) { - /* pick the bone on the arc with the lowest symmetry level - * means you connect control to the trunk of the skeleton */ - if (best_arc == NULL || arc->symmetry_level < best_arc->symmetry_level) { - best_arc = arc; - link = edge->bone; - } - } - } - } - - found = RIG_parentControl(ctrl, link); - } - - } - - - /* second pass, make chains in control bones */ - while (changed) { - changed = false; - - for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next) { - /* if control is not linked yet */ - if (ctrl->link == NULL) { - bPoseChannel *pchan; - bConstraint *con; - RigControl *ctrl_parent = NULL; - RigControl *ctrl_child; - int found = 0; - - if (ctrl->bone->parent) { - ctrl_parent = BLI_ghash_lookup(rg->controls_map, ctrl->bone->parent->name); - } - - /* check constraints first */ - - /* DO SOME MAGIC HERE */ - for (pchan = rg->ob->pose->chanbase.first; pchan; pchan = pchan->next) { - for (con = pchan->constraints.first; con; con = con->next) { - const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); - ListBase targets = {NULL, NULL}; - bConstraintTarget *ct; - - /* constraint targets */ - if (cti && cti->get_constraint_targets) { - cti->get_constraint_targets(con, &targets); - - for (ct = targets.first; ct; ct = ct->next) { - if ((ct->tar == rg->ob) && STREQ(ct->subtarget, ctrl->bone->name)) { - /* SET bone link to ctrl corresponding to pchan */ - RigControl *link = BLI_ghash_lookup(rg->controls_map, pchan->name); - - /* if owner is a control bone, link with it */ - if (link && link->link) { - RIG_parentControl(ctrl, link->bone); - found = 1; - break; - } - } - } - - if (cti->flush_constraint_targets) - cti->flush_constraint_targets(con, &targets, 0); - } - } - } - - if (found == 0) { - /* check if parent is already linked */ - if (ctrl_parent && ctrl_parent->link) { - RIG_parentControl(ctrl, ctrl_parent->bone); - changed = true; - } - else { - /* check childs */ - for (ctrl_child = rg->controls.first; ctrl_child; ctrl_child = ctrl_child->next) { - /* if a child is linked, link to that one */ - if (ctrl_child->link && ctrl_child->bone->parent == ctrl->bone) { - RIG_parentControl(ctrl, ctrl_child->bone); - changed = true; - break; - } - } - } - } - } - } - } - - /* third pass, link control tails */ - for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next) { - /* fit bone already means full match, so skip those */ - if ((ctrl->flag & RIG_CTRL_FIT_BONE) == 0) { - GHashIterator ghi; - - /* look on deform bones first */ - BLI_ghashIterator_init(&ghi, rg->bones_map); - - for (; !BLI_ghashIterator_done(&ghi); BLI_ghashIterator_step(&ghi)) { - EditBone *bone = (EditBone *)BLI_ghashIterator_getValue(&ghi); - - /* don't link with parent */ - if (bone->parent != ctrl->bone) { - if (len_v3v3(ctrl->bone->tail, bone->head) < 0.01f) { - ctrl->tail_mode = TL_HEAD; - ctrl->link_tail = bone; - break; - } - else if (len_v3v3(ctrl->bone->tail, bone->tail) < 0.01f) { - ctrl->tail_mode = TL_TAIL; - ctrl->link_tail = bone; - break; - } - } - } - - /* if we haven't found one yet, look in control bones */ - if (ctrl->tail_mode == TL_NONE) { - /* pass */ - } - } - } - -} - -/*******************************************************************************************************/ - -static void RIG_joinArcs(RigGraph *rg, RigNode *node, RigArc *joined_arc1, RigArc *joined_arc2) -{ - RigEdge *edge, *next_edge; - - /* ignore cases where joint is at start or end */ - if (joined_arc1->head == joined_arc2->head || joined_arc1->tail == joined_arc2->tail) { - return; - } - - /* swap arcs to make sure arc1 is before arc2 */ - if (joined_arc1->head == joined_arc2->tail) { - RigArc *tmp = joined_arc1; - joined_arc1 = joined_arc2; - joined_arc2 = tmp; - } - - for (edge = joined_arc2->edges.first; edge; edge = next_edge) { - next_edge = edge->next; - - RIG_appendEdgeToArc(joined_arc1, edge); - } - - joined_arc1->tail = joined_arc2->tail; - - BLI_listbase_clear(&joined_arc2->edges); - - BLI_removeArc((BGraph *)rg, (BArc *)joined_arc2); - - BLI_removeNode((BGraph *)rg, (BNode *)node); -} - -static void RIG_removeNormalNodes(RigGraph *rg) -{ - RigNode *node, *next_node; - - for (node = rg->nodes.first; node; node = next_node) { - next_node = node->next; - - if (node->degree == 2) { - RigArc *arc, *joined_arc1 = NULL, *joined_arc2 = NULL; - - for (arc = rg->arcs.first; arc; arc = arc->next) { - if (arc->head == node || arc->tail == node) { - if (joined_arc1 == NULL) { - joined_arc1 = arc; - } - else { - joined_arc2 = arc; - break; - } - } - } - - RIG_joinArcs(rg, node, joined_arc1, joined_arc2); - } - } -} - -static void RIG_removeUneededOffsets(RigGraph *rg) -{ - RigArc *arc; - - for (arc = rg->arcs.first; arc; arc = arc->next) { - RigEdge *first_edge, *last_edge; - - first_edge = arc->edges.first; - last_edge = arc->edges.last; - - if (first_edge->bone == NULL) { - if (first_edge->bone == NULL && len_v3v3(first_edge->tail, arc->head->p) <= 0.001f) { - BLI_remlink(&arc->edges, first_edge); - MEM_freeN(first_edge); - } - else if (arc->head->degree == 1) { - RigNode *new_node = (RigNode *)BLI_FindNodeByPosition((BGraph *)rg, first_edge->tail, 0.001f); - - if (new_node) { - BLI_remlink(&arc->edges, first_edge); - MEM_freeN(first_edge); - BLI_replaceNodeInArc((BGraph *)rg, (BArc *)arc, (BNode *)new_node, (BNode *)arc->head); - } - else { - RigEdge *next_edge = first_edge->next; - - if (next_edge) { - BLI_remlink(&arc->edges, first_edge); - MEM_freeN(first_edge); - - copy_v3_v3(arc->head->p, next_edge->head); - } - } - } - else { - /* check if all arc connected start with a null edge */ - RigArc *other_arc; - for (other_arc = rg->arcs.first; other_arc; other_arc = other_arc->next) { - if (other_arc != arc) { - RigEdge *test_edge; - if (other_arc->head == arc->head) { - test_edge = other_arc->edges.first; - - if (test_edge->bone != NULL) { - break; - } - } - else if (other_arc->tail == arc->head) { - test_edge = other_arc->edges.last; - - if (test_edge->bone != NULL) { - break; - } - } - } - } - - if (other_arc == NULL) { - RigNode *new_node = (RigNode *)BLI_FindNodeByPosition((BGraph *)rg, first_edge->tail, 0.001); - - if (new_node) { - /* remove null edge in other arcs too */ - for (other_arc = rg->arcs.first; other_arc; other_arc = other_arc->next) { - if (other_arc != arc) { - RigEdge *test_edge; - if (other_arc->head == arc->head) { - BLI_replaceNodeInArc((BGraph *)rg, (BArc *)other_arc, (BNode *)new_node, (BNode *)other_arc->head); - test_edge = other_arc->edges.first; - BLI_remlink(&other_arc->edges, test_edge); - MEM_freeN(test_edge); - } - else if (other_arc->tail == arc->head) { - BLI_replaceNodeInArc((BGraph *)rg, (BArc *)other_arc, (BNode *)new_node, (BNode *)other_arc->tail); - test_edge = other_arc->edges.last; - BLI_remlink(&other_arc->edges, test_edge); - MEM_freeN(test_edge); - } - } - } - - BLI_remlink(&arc->edges, first_edge); - MEM_freeN(first_edge); - BLI_replaceNodeInArc((BGraph *)rg, (BArc *)arc, (BNode *)new_node, (BNode *)arc->head); - } - else { - RigEdge *next_edge = first_edge->next; - - if (next_edge) { - BLI_remlink(&arc->edges, first_edge); - MEM_freeN(first_edge); - - copy_v3_v3(arc->head->p, next_edge->head); - - /* remove null edge in other arcs too */ - for (other_arc = rg->arcs.first; other_arc; other_arc = other_arc->next) { - if (other_arc != arc) { - RigEdge *test_edge; - if (other_arc->head == arc->head) { - test_edge = other_arc->edges.first; - BLI_remlink(&other_arc->edges, test_edge); - MEM_freeN(test_edge); - } - else if (other_arc->tail == arc->head) { - test_edge = other_arc->edges.last; - BLI_remlink(&other_arc->edges, test_edge); - MEM_freeN(test_edge); - } - } - } - } - } - } - } - } - - if (last_edge->bone == NULL) { - if (len_v3v3(last_edge->head, arc->tail->p) <= 0.001f) { - BLI_remlink(&arc->edges, last_edge); - MEM_freeN(last_edge); - } - else if (arc->tail->degree == 1) { - RigNode *new_node = (RigNode *)BLI_FindNodeByPosition((BGraph *)rg, last_edge->head, 0.001f); - - if (new_node) { - RigEdge *previous_edge = last_edge->prev; - - BLI_remlink(&arc->edges, last_edge); - MEM_freeN(last_edge); - BLI_replaceNodeInArc((BGraph *)rg, (BArc *)arc, (BNode *)new_node, (BNode *)arc->tail); - - /* set previous angle to 0, since there's no following edges */ - if (previous_edge) { - previous_edge->angle = 0; - } - } - else { - RigEdge *previous_edge = last_edge->prev; - - if (previous_edge) { - BLI_remlink(&arc->edges, last_edge); - MEM_freeN(last_edge); - - copy_v3_v3(arc->tail->p, previous_edge->tail); - previous_edge->angle = 0; - } - } - } - } - } -} - -static void RIG_arcFromBoneChain(RigGraph *rg, ListBase *list, EditBone *root_bone, RigNode *starting_node, bool selected) -{ - EditBone *bone, *last_bone = root_bone; - RigArc *arc = NULL; - int contain_head = 0; - - for (bone = root_bone; bone; bone = nextEditBoneChild(list, bone, 0)) { - int nb_children; - - if (selected == 0 || (bone->flag & BONE_SELECTED)) { - if ((bone->flag & BONE_NO_DEFORM) == 0) { - BLI_ghash_insert(rg->bones_map, bone->name, bone); - - if (arc == NULL) { - arc = newRigArc(rg); - - if (starting_node == NULL) { - starting_node = newRigNodeHead(rg, arc, root_bone->head); - } - else { - addRigNodeHead(rg, arc, starting_node); - } - } - - if (bone->parent && (bone->flag & BONE_CONNECTED) == 0) { - RIG_addEdgeToArc(arc, bone->head, NULL); - } - - RIG_addEdgeToArc(arc, bone->tail, bone); - - last_bone = bone; - - if (STREQ(bone->name, "head")) { - contain_head = 1; - } - } - else if ((bone->flag & BONE_EDITMODE_LOCKED) == 0) { /* ignore locked bones */ - RIG_addControlBone(rg, bone); - } - } - - nb_children = countEditBoneChildren(list, bone); - if (nb_children > 1) { - RigNode *end_node = NULL; - int i; - - if (arc != NULL) { - end_node = newRigNodeTail(rg, arc, bone->tail); - } - else { - end_node = newRigNode(rg, bone->tail); - } - - for (i = 0; i < nb_children; i++) { - root_bone = nextEditBoneChild(list, bone, i); - RIG_arcFromBoneChain(rg, list, root_bone, end_node, selected); - } - - /* arc ends here, break */ - break; - } - } - - /* If the loop exited without forking */ - if (arc != NULL && bone == NULL) { - newRigNodeTail(rg, arc, last_bone->tail); - } - - if (contain_head) { - rg->head = arc->tail; - } -} - -/*******************************************************************************************************/ -static void RIG_findHead(RigGraph *rg) -{ - if (rg->head == NULL) { - if (BLI_listbase_is_single(&rg->arcs)) { - RigArc *arc = rg->arcs.first; - - rg->head = (RigNode *)arc->head; - } - else { - RigArc *arc; - - for (arc = rg->arcs.first; arc; arc = arc->next) { - RigEdge *edge = arc->edges.last; - - if (edge->bone->flag & (BONE_TIPSEL | BONE_SELECTED)) { - rg->head = arc->tail; - break; - } - } - } - - if (rg->head == NULL) { - rg->head = rg->nodes.first; - } - } -} - -/*******************************************************************************************************/ - -static void RIG_printNode(RigNode *node, const char name[]) -{ - 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]); - - if (node->symmetry_flag & SYM_TOPOLOGICAL) { - if (node->symmetry_flag & SYM_AXIAL) - printf("Symmetry AXIAL\n"); - else if (node->symmetry_flag & SYM_RADIAL) - printf("Symmetry RADIAL\n"); - - print_v3("symmetry axis", node->symmetry_axis); - } -} - -void RIG_printArcBones(RigArc *arc) -{ - RigEdge *edge; - - for (edge = arc->edges.first; edge; edge = edge->next) { - if (edge->bone) - printf("%s ", edge->bone->name); - else - printf("---- "); - } - printf("\n"); -} - -static void RIG_printCtrl(RigControl *ctrl, char *indent) -{ - char text[128]; - - printf("%sBone: %s\n", indent, ctrl->bone->name); - printf("%sLink: %s\n", indent, ctrl->link ? ctrl->link->name : "!NONE!"); - - BLI_snprintf(text, sizeof(text), "%soffset", indent); - print_v3(text, ctrl->offset); - - printf("%sFlag: %i\n", indent, ctrl->flag); -} - -static void RIG_printLinkedCtrl(RigGraph *rg, EditBone *bone, int tabs) -{ - RigControl *ctrl; - char indent[64]; - char *s = indent; - int i; - - for (i = 0; i < tabs; i++) { - s[0] = '\t'; - s++; - } - s[0] = 0; - - for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next) { - if (ctrl->link == bone) { - RIG_printCtrl(ctrl, indent); - RIG_printLinkedCtrl(rg, ctrl->bone, tabs + 1); - } - } -} - -void RIG_printArc(RigGraph *rg, RigArc *arc) -{ - RigEdge *edge; - - RIG_printNode((RigNode *)arc->head, "head"); - - for (edge = arc->edges.first; edge; edge = edge->next) { - printf("\tinner joints %0.3f %0.3f %0.3f\n", edge->tail[0], edge->tail[1], edge->tail[2]); - printf("\t\tlength %f\n", edge->length); - printf("\t\tangle %f\n", edge->angle * (float)(180 / M_PI)); - if (edge->bone) { - printf("\t\t%s\n", edge->bone->name); - RIG_printLinkedCtrl(rg, edge->bone, 3); - } - } - printf("symmetry level: %i flag: %i group %i\n", arc->symmetry_level, arc->symmetry_flag, arc->symmetry_group); - - RIG_printNode((RigNode *)arc->tail, "tail"); -} - -void RIG_printGraph(RigGraph *rg) -{ - RigArc *arc; - - printf("---- ARCS ----\n"); - for (arc = rg->arcs.first; arc; arc = arc->next) { - RIG_printArc(rg, arc); - printf("\n"); - } - - if (rg->head) { - RIG_printNode(rg->head, "HEAD NODE:"); - } - else { - printf("HEAD NODE: NONE\n"); - } -} - -/*******************************************************************************************************/ - -RigGraph *RIG_graphFromArmature(const bContext *C, Object *ob, bArmature *arm) -{ - Object *obedit = CTX_data_edit_object(C); - Scene *scene = CTX_data_scene(C); - EditBone *ebone; - RigGraph *rg; - - rg = newRigGraph(); - - if (obedit == ob) { - rg->editbones = ((bArmature *)obedit->data)->edbo; - } - else { - rg->editbones = MEM_callocN(sizeof(ListBase), "EditBones"); - make_boneList(rg->editbones, &arm->bonebase, NULL, NULL); - rg->flag |= RIG_FREE_BONELIST; - } - - rg->ob = ob; - - /* Do the rotations */ - for (ebone = rg->editbones->first; ebone; ebone = ebone->next) { - if (ebone->parent == NULL) { - RIG_arcFromBoneChain(rg, rg->editbones, ebone, NULL, 0); - } - } - - BLI_removeDoubleNodes((BGraph *)rg, 0.001); - - RIG_removeNormalNodes(rg); - - RIG_removeUneededOffsets(rg); - - BLI_buildAdjacencyList((BGraph *)rg); - - RIG_findHead(rg); - - BLI_markdownSymmetry((BGraph *)rg, (BNode *)rg->head, scene->toolsettings->skgen_symmetry_limit); - - RIG_reconnectControlBones(rg); /* after symmetry, because we use levels to find best match */ - - if (BLI_isGraphCyclic((BGraph *)rg)) { - printf("armature cyclic\n"); - } - - return rg; -} - -static RigGraph *armatureSelectedToGraph(bContext *C, Object *ob, bArmature *arm) -{ - Object *obedit = CTX_data_edit_object(C); - Scene *scene = CTX_data_scene(C); - EditBone *ebone; - RigGraph *rg; - - rg = newRigGraph(); - - if (obedit == ob) { - rg->editbones = arm->edbo; - } - else { - rg->editbones = MEM_callocN(sizeof(ListBase), "EditBones"); - make_boneList(rg->editbones, &arm->bonebase, NULL, NULL); - rg->flag |= RIG_FREE_BONELIST; - } - - rg->ob = ob; - - /* Do the rotations */ - for (ebone = rg->editbones->first; ebone; ebone = ebone->next) { - if (ebone->parent == NULL) { - RIG_arcFromBoneChain(rg, rg->editbones, ebone, NULL, 1); - } - } - - BLI_removeDoubleNodes((BGraph *)rg, 0.001); - - RIG_removeNormalNodes(rg); - - RIG_removeUneededOffsets(rg); - - BLI_buildAdjacencyList((BGraph *)rg); - - RIG_findHead(rg); - - BLI_markdownSymmetry((BGraph *)rg, (BNode *)rg->head, scene->toolsettings->skgen_symmetry_limit); - - RIG_reconnectControlBones(rg); /* after symmetry, because we use levels to find best match */ - - if (BLI_isGraphCyclic((BGraph *)rg)) { - printf("armature cyclic\n"); - } - - return rg; -} -/************************************ GENERATING *****************************************************/ - -#if 0 -static EditBone *add_editbonetolist(char *name, ListBase *list) -{ - EditBone *bone = MEM_callocN(sizeof(EditBone), "eBone"); - - BLI_strncpy(bone->name, name, sizeof(bone->name)); - ED_armature_ebone_unique_name(list, bone->name, NULL); - - BLI_addtail(list, bone); - - bone->flag |= BONE_TIPSEL; - bone->weight = 1.0F; - bone->dist = 0.25F; - bone->xwidth = 0.1; - bone->zwidth = 0.1; - bone->rad_head = 0.10; - bone->rad_tail = 0.05; - bone->segments = 1; - bone->layer = 1; //arm->layer; - - /* Bendy-Bone parameters */ - bone->roll1 = 0.0f; - bone->roll2 = 0.0f; - bone->curveInX = 0.0f; - bone->curveInY = 0.0f; - bone->curveOutX = 0.0f; - bone->curveOutY = 0.0f; - bone->ease1 = 1.0f; - bone->ease2 = 1.0f; - bone->scaleIn = 1.0f; - bone->scaleOut = 1.0f; - - return bone; -} -#endif - -#if 0 /* UNUSED */ -static void generateMissingArcsFromNode(RigGraph *rigg, ReebNode *node, int multi_level_limit) -{ - while (node->multi_level > multi_level_limit && node->link_up) - { - node = node->link_up; - } - - while (node->multi_level < multi_level_limit && node->link_down) - { - node = node->link_down; - } - - if (node->multi_level == multi_level_limit) - { - int i; - - for (i = 0; i < node->degree; i++) - { - ReebArc *earc = node->arcs[i]; - - if (earc->flag == ARC_FREE && earc->head == node) - { - ReebNode *other = BIF_otherNodeFromIndex(earc, node); - - earc->flag = ARC_USED; - - //generateBonesForArc(rigg, earc, node, other); - generateMissingArcsFromNode(rigg, other, multi_level_limit); - } - } - } -} - -static void generateMissingArcs(RigGraph *rigg) -{ - ReebGraph *reebg; - int multi_level_limit = 5; - - for (reebg = rigg->link_mesh; reebg; reebg = reebg->link_up) - { - ReebArc *earc; - - for (earc = reebg->arcs.first; earc; earc = earc->next) - { - if (earc->flag == ARC_USED) - { - generateMissingArcsFromNode(rigg, earc->head, multi_level_limit); - generateMissingArcsFromNode(rigg, earc->tail, multi_level_limit); - } - } - } -} -#endif - -/************************************ RETARGETTING *****************************************************/ - -static void repositionControl(RigGraph *rigg, RigControl *ctrl, float head[3], float tail[3], float qrot[4], float resize); - -static void repositionTailControl(RigGraph *rigg, RigControl *ctrl); - -static void finalizeControl(RigGraph *rigg, RigControl *ctrl, float resize) -{ - if ((ctrl->flag & RIG_CTRL_DONE) == RIG_CTRL_DONE) { - RigControl *ctrl_child; - -#if 0 - printf("CTRL: %s LINK: %s", ctrl->bone->name, ctrl->link->name); - - if (ctrl->link_tail) - { - printf(" TAIL: %s", ctrl->link_tail->name); - } - - printf("\n"); -#endif - - /* if there was a tail link: apply link, recalc resize factor and qrot */ - if (ctrl->tail_mode != TL_NONE) { - float *tail_vec = NULL; - float v1[3], v2[3], qtail[4]; - - if (ctrl->tail_mode == TL_TAIL) { - tail_vec = ctrl->link_tail->tail; - } - else if (ctrl->tail_mode == TL_HEAD) { - tail_vec = ctrl->link_tail->head; - } - - sub_v3_v3v3(v1, ctrl->bone->tail, ctrl->bone->head); - sub_v3_v3v3(v2, tail_vec, ctrl->bone->head); - - copy_v3_v3(ctrl->bone->tail, tail_vec); - - rotation_between_vecs_to_quat(qtail, v1, v2); - mul_qt_qtqt(ctrl->qrot, qtail, ctrl->qrot); - - resize = len_v3(v2) / len_v3v3(ctrl->head, ctrl->tail); - } - - ctrl->bone->roll = rollBoneByQuat(ctrl->bone, ctrl->up_axis, ctrl->qrot); - - /* Cascade to connected control bones */ - for (ctrl_child = rigg->controls.first; ctrl_child; ctrl_child = ctrl_child->next) { - if (ctrl_child->link == ctrl->bone) { - repositionControl(rigg, ctrl_child, ctrl->bone->head, ctrl->bone->tail, ctrl->qrot, resize); - } - if (ctrl_child->link_tail == ctrl->bone) { - repositionTailControl(rigg, ctrl_child); - } - } - } -} - -static void repositionTailControl(RigGraph *rigg, RigControl *ctrl) -{ - ctrl->flag |= RIG_CTRL_TAIL_DONE; - - finalizeControl(rigg, ctrl, 1); /* resize will be recalculated anyway so we don't need it */ -} - -static void repositionControl(RigGraph *rigg, RigControl *ctrl, float head[3], float UNUSED(tail[3]), float qrot[4], float resize) -{ - float parent_offset[3], tail_offset[3]; - - copy_v3_v3(parent_offset, ctrl->offset); - mul_v3_fl(parent_offset, resize); - mul_qt_v3(qrot, parent_offset); - - add_v3_v3v3(ctrl->bone->head, head, parent_offset); - - ctrl->flag |= RIG_CTRL_HEAD_DONE; - - copy_qt_qt(ctrl->qrot, qrot); - - if (ctrl->tail_mode == TL_NONE) { - sub_v3_v3v3(tail_offset, ctrl->tail, ctrl->head); - mul_v3_fl(tail_offset, resize); - mul_qt_v3(qrot, tail_offset); - - add_v3_v3v3(ctrl->bone->tail, ctrl->bone->head, tail_offset); - - ctrl->flag |= RIG_CTRL_TAIL_DONE; - } - - finalizeControl(rigg, ctrl, resize); -} - -static void repositionBone(bContext *C, RigGraph *rigg, RigEdge *edge, float vec0[3], float vec1[3], float up_axis[3]) -{ - Scene *scene = CTX_data_scene(C); - EditBone *bone; - RigControl *ctrl; - float qrot[4], resize; - float v1[3], v2[3]; - float l1, l2; - - bone = edge->bone; - - sub_v3_v3v3(v1, edge->tail, edge->head); - sub_v3_v3v3(v2, vec1, vec0); - - l1 = normalize_v3(v1); - l2 = normalize_v3(v2); - - resize = l2 / l1; - - rotation_between_vecs_to_quat(qrot, v1, v2); - - copy_v3_v3(bone->head, vec0); - copy_v3_v3(bone->tail, vec1); - - if (!is_zero_v3(up_axis)) { - float qroll[4]; - - if (scene->toolsettings->skgen_retarget_roll == SK_RETARGET_ROLL_VIEW) { - bone->roll = rollBoneByQuatAligned(bone, edge->up_axis, qrot, qroll, up_axis); - } - else if (scene->toolsettings->skgen_retarget_roll == SK_RETARGET_ROLL_JOINT) { - bone->roll = rollBoneByQuatJoint(edge, edge->prev, qrot, qroll, up_axis); - } - else { - unit_qt(qroll); - } - - mul_qt_qtqt(qrot, qroll, qrot); - } - else { - bone->roll = rollBoneByQuat(bone, edge->up_axis, qrot); - } - - for (ctrl = rigg->controls.first; ctrl; ctrl = ctrl->next) { - if (ctrl->link == bone) { - repositionControl(rigg, ctrl, vec0, vec1, qrot, resize); - } - if (ctrl->link_tail == bone) { - repositionTailControl(rigg, ctrl); - } - } -} - -static RetargetMode detectArcRetargetMode(RigArc *arc); -static void retargetArctoArcLength(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode *inode_start); - - -static RetargetMode detectArcRetargetMode(RigArc *iarc) -{ - RetargetMode mode = RETARGET_AGGRESSIVE; - ReebArc *earc = iarc->link_mesh; - RigEdge *edge; - int large_angle = 0; - float avg_angle = 0; - /* float avg_length = 0; */ /* UNUSED */ - int nb_edges = 0; - - - for (edge = iarc->edges.first; edge; edge = edge->next) { - avg_angle += edge->angle; - nb_edges++; - } - - avg_angle /= nb_edges - 1; /* -1 because last edge doesn't have an angle */ - - /* avg_length = iarc->length / nb_edges; */ /* UNUSED */ - - - if (nb_edges > 2) { - for (edge = iarc->edges.first; edge; edge = edge->next) { - if (fabsf(edge->angle - avg_angle) > (float)(M_PI / 6)) { - large_angle = 1; - } - } - } - else if (nb_edges == 2 && avg_angle > 0) { - large_angle = 1; - } - - - if (large_angle == 0) { - mode = RETARGET_LENGTH; - } - - if (earc->bcount <= (iarc->count - 1)) { - mode = RETARGET_LENGTH; - } - - return mode; -} - -#ifndef USE_THREADS -static void printMovesNeeded(int *positions, int nb_positions) -{ - int moves = 0; - int i; - - for (i = 0; i < nb_positions; i++) { - moves += positions[i] - (i + 1); - } - - printf("%i moves needed\n", moves); -} - -static void printPositions(int *positions, int nb_positions) -{ - int i; - - for (i = 0; i < nb_positions; i++) { - printf("%i ", positions[i]); - } - printf("\n"); -} -#endif - -#define MAX_COST FLT_MAX /* FIX ME */ - -static float costDistance(BArcIterator *iter, float *vec0, float *vec1, int i0, int i1, float distance_weight) -{ - EmbedBucket *bucket = NULL; - float max_dist = 0; - float v1[3], v2[3], c[3]; - float v1_inpf; - - if (distance_weight > 0) { - sub_v3_v3v3(v1, vec0, vec1); - - v1_inpf = dot_v3v3(v1, v1); - - if (v1_inpf > 0) { - int j; - for (j = i0 + 1; j < i1 - 1; j++) { - float dist; - - bucket = IT_peek(iter, j); - - sub_v3_v3v3(v2, bucket->p, vec1); - - cross_v3_v3v3(c, v1, v2); - - dist = dot_v3v3(c, c) / v1_inpf; - - max_dist = dist > max_dist ? dist : max_dist; - } - - return distance_weight * max_dist; - } - else { - return MAX_COST; - } - } - else { - return 0; - } -} - -static float costAngle(float original_angle, float vec_first[3], float vec_second[3], float angle_weight) -{ - if (angle_weight > 0) { - float current_angle; - - if (!is_zero_v3(vec_first) && !is_zero_v3(vec_second)) { - current_angle = saacos(dot_v3v3(vec_first, vec_second)); - - return angle_weight * fabsf(current_angle - original_angle); - } - else { - return angle_weight * (float)M_PI; - } - } - else { - return 0; - } -} - -static float costLength(float original_length, float current_length, float length_weight) -{ - if (current_length == 0) { - return MAX_COST; - } - else { - float length_ratio = fabsf((current_length - original_length) / original_length); - return length_weight * length_ratio * length_ratio; - } -} - -#if 0 -static float calcCostLengthDistance(BArcIterator *iter, float **vec_cache, RigEdge *edge, float *vec1, float *vec2, int i1, int i2) -{ - float vec[3]; - float length; - - sub_v3_v3v3(vec, vec2, vec1); - length = normalize_v3(vec); - - return costLength(edge->length, length) + costDistance(iter, vec1, vec2, i1, i2); -} -#endif - -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) -{ - float vec_second[3], vec_first[3]; - float length2; - float new_cost = 0; - - sub_v3_v3v3(vec_second, vec2, vec1); - length2 = normalize_v3(vec_second); - - - /* Angle cost */ - if (edge->prev) { - sub_v3_v3v3(vec_first, vec1, vec0); - normalize_v3(vec_first); - - new_cost += costAngle(edge->prev->angle, vec_first, vec_second, angle_weight); - } - - /* Length cost */ - new_cost += costLength(edge->length, length2, length_weight); - - /* Distance cost */ - new_cost += costDistance(iter, vec1, vec2, i1, i2, distance_weight); - - return new_cost; -} - -static int indexMemoNode(int nb_positions, int previous, int current, int joints_left) -{ - return joints_left * nb_positions * nb_positions + current * nb_positions + previous; -} - -static void copyMemoPositions(int *positions, MemoNode *table, int nb_positions, int joints_left) -{ - int previous = 0, current = 0; - int i = 0; - - for (i = 0; joints_left > 0; joints_left--, i++) { - MemoNode *node; - node = table + indexMemoNode(nb_positions, previous, current, joints_left); - - positions[i] = node->next; - - previous = current; - current = node->next; - } -} - -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) -{ - MemoNode *node; - int index = indexMemoNode(nb_positions, previous, current, joints_left); - - node = table + index; - - if (node->weight != 0) { - return node; - } - else if (joints_left == 0) { - float *vec0 = vec_cache[previous]; - float *vec1 = vec_cache[current]; - float *vec2 = vec_cache[nb_positions + 1]; - - node->weight = calcCostAngleLengthDistance(iter, vec_cache, edge, vec0, vec1, vec2, current, iter->length, angle_weight, length_weight, distance_weight); - - return node; - } - else { - MemoNode *min_node = NULL; - float *vec0 = vec_cache[previous]; - float *vec1 = vec_cache[current]; - float min_weight = 0.0f; - int min_next = 0; - int next; - - for (next = current + 1; next <= nb_positions - (joints_left - 1); next++) { - MemoNode *next_node; - float *vec2 = vec_cache[next]; - float weight = 0.0f; - - /* ADD WEIGHT OF PREVIOUS - CURRENT - NEXT triple */ - weight = calcCostAngleLengthDistance(iter, vec_cache, edge, vec0, vec1, vec2, current, next, angle_weight, length_weight, distance_weight); - - if (weight >= MAX_COST) { - continue; - } - - /* add node weight */ - next_node = solveJoints(table, iter, vec_cache, nb_joints, nb_positions, current, next, edge->next, joints_left - 1, angle_weight, length_weight, distance_weight); - weight += next_node->weight; - - if (min_node == NULL || weight < min_weight) { - min_weight = weight; - min_node = next_node; - min_next = next; - } - } - - if (min_node) { - node->weight = min_weight; - node->next = min_next; - return node; - } - else { - node->weight = MAX_COST; - return node; - } - } - -} - -static int testFlipArc(RigArc *iarc, RigNode *inode_start) -{ - ReebArc *earc = iarc->link_mesh; - ReebNode *enode_start = BIF_NodeFromIndex(earc, inode_start->link_mesh); - - /* no flip needed if both nodes are the same */ - if ((enode_start == earc->head && inode_start == iarc->head) || - (enode_start == earc->tail && inode_start == iarc->tail)) - { - return 0; - } - else { - return 1; - } -} - -static void retargetArctoArcAggresive(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode *inode_start) -{ - ReebArcIterator arc_iter; - BArcIterator *iter = (BArcIterator *)&arc_iter; - RigEdge *edge; - ReebNode *node_start, *node_end; - ReebArc *earc = iarc->link_mesh; - float angle_weight = 1.0; // GET FROM CONTEXT - float length_weight = 1.0; - float distance_weight = 1.0; -#ifndef USE_THREADS - float min_cost = FLT_MAX; -#endif - float *vec0, *vec1; - int *best_positions; - int nb_edges = BLI_listbase_count(&iarc->edges); - int nb_joints = nb_edges - 1; - RetargetMethod method = METHOD_MEMOIZE; - int i; - - if (nb_joints > earc->bcount) { - printf("NOT ENOUGH BUCKETS!\n"); - return; - } - - best_positions = MEM_callocN(sizeof(int) * nb_joints, "Best positions"); - - if (testFlipArc(iarc, inode_start)) { - node_start = earc->tail; - node_end = earc->head; - } - else { - node_start = earc->head; - node_end = earc->tail; - } - - /* equal number of joints and potential position, just fill them in */ - if (nb_joints == earc->bcount) { - /* init with first values */ - for (i = 0; i < nb_joints; i++) { - best_positions[i] = i + 1; - } - } - if (method == METHOD_MEMOIZE) { - int nb_positions = earc->bcount; - int nb_memo_nodes = nb_positions * nb_positions * (nb_joints + 1); - MemoNode *table = MEM_callocN(nb_memo_nodes * sizeof(MemoNode), "memoization table"); -#ifndef USE_THREADS - MemoNode *result; -#endif - float **positions_cache = MEM_callocN(sizeof(float *) * (nb_positions + 2), "positions cache"); - - positions_cache[0] = node_start->p; - positions_cache[nb_positions + 1] = node_end->p; - - initArcIterator(iter, earc, node_start); - - for (i = 1; i <= nb_positions; i++) { - EmbedBucket *bucket = IT_peek(iter, i); - positions_cache[i] = bucket->p; - } - -#ifndef USE_THREADS - result = solveJoints(table, iter, positions_cache, nb_joints, earc->bcount, 0, 0, iarc->edges.first, nb_joints, angle_weight, length_weight, distance_weight); - min_cost = result->weight; -#else - solveJoints(table, iter, positions_cache, nb_joints, earc->bcount, 0, 0, iarc->edges.first, nb_joints, angle_weight, length_weight, distance_weight); -#endif - - copyMemoPositions(best_positions, table, earc->bcount, nb_joints); - - MEM_freeN(table); - MEM_freeN(positions_cache); - } - - vec0 = node_start->p; - initArcIterator(iter, earc, node_start); - -#ifndef USE_THREADS - printPositions(best_positions, nb_joints); - printMovesNeeded(best_positions, nb_joints); - printf("min_cost %f\n", min_cost); - printf("buckets: %i\n", earc->bcount); -#endif - - /* set joints to best position */ - for (edge = iarc->edges.first, i = 0; - edge; - edge = edge->next, i++) - { - float *no = NULL; - if (i < nb_joints) { - EmbedBucket *bucket = IT_peek(iter, best_positions[i]); - vec1 = bucket->p; - no = bucket->no; - } - else { - vec1 = node_end->p; - no = node_end->no; - } - - if (edge->bone) { - repositionBone(C, rigg, edge, vec0, vec1, no); - } - - vec0 = vec1; - } - - MEM_freeN(best_positions); -} - -static void retargetArctoArcLength(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode *inode_start) -{ - ReebArcIterator arc_iter; - BArcIterator *iter = (BArcIterator *)&arc_iter; - ReebArc *earc = iarc->link_mesh; - ReebNode *node_start, *node_end; - RigEdge *edge; - EmbedBucket *bucket = NULL; - float embedding_length = 0; - float *vec0 = NULL; - float *vec1 = NULL; - float *previous_vec = NULL; - - - if (testFlipArc(iarc, inode_start)) { - node_start = (ReebNode *)earc->tail; - node_end = (ReebNode *)earc->head; - } - else { - node_start = (ReebNode *)earc->head; - node_end = (ReebNode *)earc->tail; - } - - initArcIterator(iter, earc, node_start); - - bucket = IT_next(iter); - - vec0 = node_start->p; - - while (bucket != NULL) { - vec1 = bucket->p; - - embedding_length += len_v3v3(vec0, vec1); - - vec0 = vec1; - bucket = IT_next(iter); - } - - embedding_length += len_v3v3(node_end->p, vec1); - - /* fit bones */ - initArcIterator(iter, earc, node_start); - - bucket = IT_next(iter); - - vec0 = node_start->p; - previous_vec = vec0; - vec1 = bucket->p; - - for (edge = iarc->edges.first; edge; edge = edge->next) { - float new_bone_length = edge->length / iarc->length * embedding_length; - float *no = NULL; - float length = 0; - - while (bucket && new_bone_length > length) { - length += len_v3v3(previous_vec, vec1); - bucket = IT_next(iter); - previous_vec = vec1; - vec1 = bucket->p; - no = bucket->no; - } - - if (bucket == NULL) { - vec1 = node_end->p; - no = node_end->no; - } - - /* no need to move virtual edges (space between unconnected bones) */ - if (edge->bone) { - repositionBone(C, rigg, edge, vec0, vec1, no); - } - - vec0 = vec1; - previous_vec = vec1; - } -} - -static void retargetArctoArc(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode *inode_start) -{ - RetargetParam *p = MEM_callocN(sizeof(RetargetParam), "RetargetParam"); - - p->rigg = rigg; - p->iarc = iarc; - p->inode_start = inode_start; - p->context = C; - - BLI_task_pool_push(rigg->task_pool, exec_retargetArctoArc, p, true, TASK_PRIORITY_HIGH); -} - -void exec_retargetArctoArc(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid)) -{ - RetargetParam *p = (RetargetParam *)taskdata; - RigGraph *rigg = p->rigg; - RigArc *iarc = p->iarc; - bContext *C = p->context; - RigNode *inode_start = p->inode_start; - ReebArc *earc = iarc->link_mesh; - - if (BLI_listbase_is_single(&iarc->edges)) { - RigEdge *edge = iarc->edges.first; - - if (testFlipArc(iarc, inode_start)) { - repositionBone(C, rigg, edge, earc->tail->p, earc->head->p, earc->head->no); - } - else { - repositionBone(C, rigg, edge, earc->head->p, earc->tail->p, earc->tail->no); - } - } - else { - RetargetMode mode = detectArcRetargetMode(iarc); - - if (mode == RETARGET_AGGRESSIVE) { - retargetArctoArcAggresive(C, rigg, iarc, inode_start); - } - else { - retargetArctoArcLength(C, rigg, iarc, inode_start); - } - } -} - -static void matchMultiResolutionNode(RigGraph *rigg, RigNode *inode, ReebNode *top_node) -{ - ReebNode *enode = top_node; - ReebGraph *reebg = BIF_graphForMultiNode(rigg->link_mesh, enode); - int ishape, eshape; - - ishape = BLI_subtreeShape((BGraph *)rigg, (BNode *)inode, NULL, 0) % SHAPE_LEVELS; - eshape = BLI_subtreeShape((BGraph *)reebg, (BNode *)enode, NULL, 0) % SHAPE_LEVELS; - - inode->link_mesh = enode; - - while (ishape == eshape && enode->link_down) { - inode->link_mesh = enode; - - enode = enode->link_down; - reebg = BIF_graphForMultiNode(rigg->link_mesh, enode); /* replace with call to link_down once that exists */ - eshape = BLI_subtreeShape((BGraph *)reebg, (BNode *)enode, NULL, 0) % SHAPE_LEVELS; - } -} - -static void markMultiResolutionChildArc(ReebNode *end_enode, ReebNode *enode) -{ - int i; - - for (i = 0; i < enode->degree; i++) { - ReebArc *earc = (ReebArc *)enode->arcs[i]; - - if (earc->flag == ARC_FREE) { - earc->flag = ARC_TAKEN; - - if (earc->tail->degree > 1 && earc->tail != end_enode) { - markMultiResolutionChildArc(end_enode, earc->tail); - } - break; - } - } -} - -static void markMultiResolutionArc(ReebArc *start_earc) -{ - if (start_earc->link_up) { - ReebArc *earc; - for (earc = start_earc->link_up; earc; earc = earc->link_up) { - earc->flag = ARC_TAKEN; - - if (earc->tail->index != start_earc->tail->index) { - markMultiResolutionChildArc(earc->tail, earc->tail); - } - } - } -} - -static void matchMultiResolutionArc(RigGraph *rigg, RigNode *start_node, RigArc *next_iarc, ReebArc *next_earc) -{ - ReebNode *enode = next_earc->head; - ReebGraph *reebg = BIF_graphForMultiNode(rigg->link_mesh, enode); - int ishape, eshape; - - ishape = BLI_subtreeShape((BGraph *)rigg, (BNode *)start_node, (BArc *)next_iarc, 1) % SHAPE_LEVELS; - eshape = BLI_subtreeShape((BGraph *)reebg, (BNode *)enode, (BArc *)next_earc, 1) % SHAPE_LEVELS; - - while (ishape != eshape && next_earc->link_up) { - next_earc->flag = ARC_TAKEN; // mark previous as taken, to prevent backtrack on lower levels - - next_earc = next_earc->link_up; - reebg = reebg->link_up; - enode = next_earc->head; - eshape = BLI_subtreeShape((BGraph *)reebg, (BNode *)enode, (BArc *)next_earc, 1) % SHAPE_LEVELS; - } - - next_earc->flag = ARC_USED; - next_iarc->link_mesh = next_earc; - - /* mark all higher levels as taken too */ - markMultiResolutionArc(next_earc); -// while (next_earc->link_up) -// { -// next_earc = next_earc->link_up; -// next_earc->flag = ARC_TAKEN; -// } -} - -static void matchMultiResolutionStartingNode(RigGraph *rigg, ReebGraph *reebg, RigNode *inode) -{ - ReebNode *enode; - int ishape, eshape; - - enode = reebg->nodes.first; - - ishape = BLI_subtreeShape((BGraph *)rigg, (BNode *)inode, NULL, 0) % SHAPE_LEVELS; - eshape = BLI_subtreeShape((BGraph *)rigg->link_mesh, (BNode *)enode, NULL, 0) % SHAPE_LEVELS; - - while (ishape != eshape && reebg->link_up) { - reebg = reebg->link_up; - - enode = reebg->nodes.first; - - eshape = BLI_subtreeShape((BGraph *)reebg, (BNode *)enode, NULL, 0) % SHAPE_LEVELS; - } - - inode->link_mesh = enode; -} - -static void findCorrespondingArc(RigGraph *rigg, RigArc *start_arc, RigNode *start_node, RigArc *next_iarc, int root) -{ - ReebNode *enode = start_node->link_mesh; - ReebArc *next_earc; - int symmetry_level = next_iarc->symmetry_level; - int symmetry_group = next_iarc->symmetry_group; - int symmetry_flag = next_iarc->symmetry_flag; - int i; - - next_iarc->link_mesh = NULL; - -// if (root) -// { -// printf("-----------------------\n"); -// printf("MATCHING LIMB\n"); -// RIG_printArcBones(next_iarc); -// } - - for (i = 0; i < enode->degree; i++) { - next_earc = (ReebArc *)enode->arcs[i]; - -// if (next_earc->flag == ARC_FREE) -// { -// printf("candidate (level %i ?= %i) (flag %i ?= %i) (group %i ?= %i)\n", -// symmetry_level, next_earc->symmetry_level, -// symmetry_flag, next_earc->symmetry_flag, -// symmetry_group, next_earc->symmetry_flag); -// } - - if (next_earc->flag == ARC_FREE && - next_earc->symmetry_flag == symmetry_flag && - next_earc->symmetry_group == symmetry_group && - next_earc->symmetry_level == symmetry_level) - { -// printf("CORRESPONDING ARC FOUND\n"); -// 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); - - matchMultiResolutionArc(rigg, start_node, next_iarc, next_earc); - break; - } - } - - /* not found, try at higher nodes (lower node might have filtered internal arcs, messing shape of tree */ - if (next_iarc->link_mesh == NULL) { -// printf("NO CORRESPONDING ARC FOUND - GOING TO HIGHER LEVELS\n"); - - if (enode->link_up) { - start_node->link_mesh = enode->link_up; - findCorrespondingArc(rigg, start_arc, start_node, next_iarc, 0); - } - } - - /* still not found, print debug info */ - if (root && next_iarc->link_mesh == NULL) { - start_node->link_mesh = enode; /* linking back with root node */ - -// printf("NO CORRESPONDING ARC FOUND\n"); -// RIG_printArcBones(next_iarc); -// -// printf("ON NODE %i, multilevel %i\n", enode->index, enode->multi_level); -// -// printf("LOOKING FOR\n"); -// printf("flag %i -- level %i -- flag %i -- group %i\n", ARC_FREE, symmetry_level, symmetry_flag, symmetry_group); -// -// printf("CANDIDATES\n"); -// for (i = 0; i < enode->degree; i++) -// { -// next_earc = (ReebArc *)enode->arcs[i]; -// 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); -// } - - /* Emergency matching */ - for (i = 0; i < enode->degree; i++) { - next_earc = (ReebArc *)enode->arcs[i]; - - if (next_earc->flag == ARC_FREE && next_earc->symmetry_level == symmetry_level) { -// printf("USING:\n"); -// 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); - matchMultiResolutionArc(rigg, start_node, next_iarc, next_earc); - break; - } - } - } - -} - -static void retargetSubgraph(bContext *C, RigGraph *rigg, RigArc *start_arc, RigNode *start_node) -{ - RigNode *inode = start_node; - int i; - - /* no start arc on first node */ - if (start_arc) { - ReebNode *enode = start_node->link_mesh; - ReebArc *earc = start_arc->link_mesh; - - retargetArctoArc(C, rigg, start_arc, start_node); - - enode = BIF_otherNodeFromIndex(earc, enode); - inode = (RigNode *)BLI_otherNode((BArc *)start_arc, (BNode *)inode); - - /* match with lowest node with correct shape */ - matchMultiResolutionNode(rigg, inode, enode); - } - - for (i = 0; i < inode->degree; i++) { - RigArc *next_iarc = (RigArc *)inode->arcs[i]; - - /* no back tracking */ - if (next_iarc != start_arc) { - findCorrespondingArc(rigg, start_arc, inode, next_iarc, 1); - if (next_iarc->link_mesh) { - retargetSubgraph(C, rigg, next_iarc, inode); - } - } - } -} - -static void finishRetarget(RigGraph *rigg) -{ - BLI_task_pool_work_and_wait(rigg->task_pool); -} - -static void adjustGraphs(bContext *C, RigGraph *rigg) -{ - bArmature *arm = rigg->ob->data; - RigArc *arc; - - for (arc = rigg->arcs.first; arc; arc = arc->next) { - if (arc->link_mesh) { - retargetArctoArc(C, rigg, arc, arc->head); - } - } - - finishRetarget(rigg); - - /* Turn the list into an armature */ - arm->edbo = rigg->editbones; - ED_armature_from_edit(arm); - - ED_undo_push(C, "Retarget Skeleton"); -} - -static void retargetGraphs(bContext *C, RigGraph *rigg) -{ - bArmature *arm = rigg->ob->data; - ReebGraph *reebg = rigg->link_mesh; - RigNode *inode; - - /* flag all ReebArcs as free */ - BIF_flagMultiArcs(reebg, ARC_FREE); - - /* return to first level */ - inode = rigg->head; - - matchMultiResolutionStartingNode(rigg, reebg, inode); - - retargetSubgraph(C, rigg, NULL, inode); - - //generateMissingArcs(rigg); - - finishRetarget(rigg); - - /* Turn the list into an armature */ - arm->edbo = rigg->editbones; - ED_armature_from_edit(arm); -} - -const char *RIG_nameBone(RigGraph *rg, int arc_index, int bone_index) -{ - RigArc *arc = BLI_findlink(&rg->arcs, arc_index); - RigEdge *iedge; - - if (arc == NULL) { - return "None"; - } - - if (bone_index == BLI_listbase_count(&arc->edges)) { - return "Last joint"; - } - - iedge = BLI_findlink(&arc->edges, bone_index); - - if (iedge == NULL) { - return "Done"; - } - - if (iedge->bone == NULL) { - return "Bone offset"; - } - - return iedge->bone->name; -} - -int RIG_nbJoints(RigGraph *rg) -{ - RigArc *arc; - int total = 0; - - total += BLI_listbase_count(&rg->nodes); - - for (arc = rg->arcs.first; arc; arc = arc->next) { - total += BLI_listbase_count(&arc->edges) - 1; /* -1 because end nodes are already counted */ - } - - return total; -} - -static void BIF_freeRetarget(void) -{ - if (GLOBAL_RIGG) { - RIG_freeRigGraph((BGraph *)GLOBAL_RIGG); - GLOBAL_RIGG = NULL; - } -} - -void BIF_retargetArmature(bContext *C) -{ - ReebGraph *reebg; - double start_time, end_time; - double gstart_time, gend_time; - double reeb_time, rig_time = 0.0, retarget_time = 0.0, total_time; - - gstart_time = start_time = PIL_check_seconds_timer(); - - reebg = BIF_ReebGraphMultiFromEditMesh(C); - - end_time = PIL_check_seconds_timer(); - reeb_time = end_time - start_time; - - printf("Reeb Graph created\n"); - - CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) - { - Object *ob = base->object; - - if (ob->type == OB_ARMATURE) { - RigGraph *rigg; - bArmature *arm; - - arm = ob->data; - - /* Put the armature into editmode */ - - - start_time = PIL_check_seconds_timer(); - - rigg = RIG_graphFromArmature(C, ob, arm); - - end_time = PIL_check_seconds_timer(); - rig_time = end_time - start_time; - - printf("Armature graph created\n"); - - //RIG_printGraph(rigg); - - rigg->link_mesh = reebg; - - printf("retargetting %s\n", ob->id.name); - - start_time = PIL_check_seconds_timer(); - - retargetGraphs(C, rigg); - - end_time = PIL_check_seconds_timer(); - retarget_time = end_time - start_time; - - BIF_freeRetarget(); - - GLOBAL_RIGG = rigg; - - break; /* only one armature at a time */ - } - } - CTX_DATA_END; - - - gend_time = PIL_check_seconds_timer(); - - total_time = gend_time - gstart_time; - - printf("-----------\n"); - printf("runtime: \t%.3f\n", total_time); - printf("reeb: \t\t%.3f (%.1f%%)\n", reeb_time, reeb_time / total_time * 100); - printf("rig: \t\t%.3f (%.1f%%)\n", rig_time, rig_time / total_time * 100); - printf("retarget: \t%.3f (%.1f%%)\n", retarget_time, retarget_time / total_time * 100); - printf("-----------\n"); - - ED_undo_push(C, "Retarget Skeleton"); - - // XXX -// allqueue(REDRAWVIEW3D, 0); -} - -void BIF_retargetArc(bContext *C, ReebArc *earc, RigGraph *template_rigg) -{ - Object *obedit = CTX_data_edit_object(C); - Scene *scene = CTX_data_scene(C); - bArmature *armedit = obedit->data; - Object *ob; - RigGraph *rigg; - RigArc *iarc; - char *side_string = scene->toolsettings->skgen_side_string; - char *num_string = scene->toolsettings->skgen_num_string; - int free_template = 0; - - if (template_rigg) { - ob = template_rigg->ob; - } - else { - free_template = 1; - ob = obedit; - template_rigg = armatureSelectedToGraph(C, ob, ob->data); - } - - if (BLI_listbase_is_empty(&template_rigg->arcs)) { -// XXX -// error("No Template and no deforming bones selected"); - return; - } - - rigg = cloneRigGraph(template_rigg, armedit->edbo, obedit, side_string, num_string); - - iarc = rigg->arcs.first; - - iarc->link_mesh = earc; - iarc->head->link_mesh = earc->head; - iarc->tail->link_mesh = earc->tail; - - retargetArctoArc(C, rigg, iarc, iarc->head); - - finishRetarget(rigg); - - /* free template if it comes from the edit armature */ - if (free_template) { - RIG_freeRigGraph((BGraph *)template_rigg); - } - RIG_freeRigGraph((BGraph *)rigg); - - ED_armature_edit_validate_active(armedit); - -// XXX -// allqueue(REDRAWVIEW3D, 0); -} - -void BIF_adjustRetarget(bContext *C) -{ - if (GLOBAL_RIGG) { - adjustGraphs(C, GLOBAL_RIGG); - } -} diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c deleted file mode 100644 index 753d4001b5d..00000000000 --- a/source/blender/editors/armature/editarmature_sketch.c +++ /dev/null @@ -1,2651 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/editors/armature/editarmature_sketch.c - * \ingroup edarmature - */ - -#include "MEM_guardedalloc.h" - -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_armature_types.h" - -#include "BLI_blenlib.h" -#include "BLI_math.h" - -#include "BKE_context.h" -#include "BKE_sketch.h" -#include "BKE_layer.h" - -#include "RNA_define.h" -#include "RNA_access.h" - -#include "ED_view3d.h" -#include "ED_screen.h" - -#include "BIF_gl.h" -#include "ED_armature.h" -#include "armature_intern.h" -#include "BIF_retarget.h" -#include "BIF_generate.h" - -#include "ED_transform.h" -#include "ED_transform_snap_object_context.h" - -#include "DEG_depsgraph.h" - -#include "WM_api.h" -#include "WM_types.h" - -#include "GPU_select.h" -#include "GPU_matrix.h" -#include "GPU_batch.h" -#include "GPU_immediate.h" -#include "GPU_immediate_util.h" - -typedef int (*GestureDetectFct)(bContext *, SK_Gesture *, SK_Sketch *); -typedef void (*GestureApplyFct)(bContext *, SK_Gesture *, SK_Sketch *); - -typedef struct SK_GestureAction { - char name[64]; - GestureDetectFct detect; - GestureApplyFct apply; -} SK_GestureAction; - -#if 0 /* UNUSED 2.5 */ -static SK_Point boneSnap; -#endif - -static int LAST_SNAP_POINT_VALID = 0; -static float LAST_SNAP_POINT[3]; - - -typedef struct SK_StrokeIterator { - HeadFct head; - TailFct tail; - PeekFct peek; - NextFct next; - NextNFct nextN; - PreviousFct previous; - StoppedFct stopped; - - float *p, *no; - float size; - - int length; - int index; - /*********************************/ - SK_Stroke *stroke; - int start; - int end; - int stride; -} SK_StrokeIterator; - -/******************** PROTOTYPES ******************************/ - -void initStrokeIterator(BArcIterator *iter, SK_Stroke *stk, int start, int end); - -int sk_detectCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -void sk_applyCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -int sk_detectTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -void sk_applyTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -int sk_detectCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -void sk_applyCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -int sk_detectDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -void sk_applyDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -int sk_detectMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -void sk_applyMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -int sk_detectReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -void sk_applyReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -int sk_detectConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -void sk_applyConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); - -SK_Sketch *contextSketch(const bContext *c, int create); -SK_Sketch *viewcontextSketch(ViewContext *vc, int create); - -void sk_resetOverdraw(SK_Sketch *sketch); -int sk_hasOverdraw(SK_Sketch *sketch, SK_Stroke *stk); - -/******************** GESTURE ACTIONS ******************************/ - -static SK_GestureAction GESTURE_ACTIONS[] = { - {"Cut", sk_detectCutGesture, sk_applyCutGesture}, - {"Trim", sk_detectTrimGesture, sk_applyTrimGesture}, - {"Command", sk_detectCommandGesture, sk_applyCommandGesture}, - {"Delete", sk_detectDeleteGesture, sk_applyDeleteGesture}, - {"Merge", sk_detectMergeGesture, sk_applyMergeGesture}, - {"Reverse", sk_detectReverseGesture, sk_applyReverseGesture}, - {"Convert", sk_detectConvertGesture, sk_applyConvertGesture}, - {"", NULL, NULL} -}; - -/******************** TEMPLATES UTILS *************************/ - -static char *TEMPLATES_MENU = NULL; -static int TEMPLATES_CURRENT = 0; -static GHash *TEMPLATES_HASH = NULL; -static RigGraph *TEMPLATE_RIGG = NULL; - -void BIF_makeListTemplates(const bContext *C) -{ - Object *obedit = CTX_data_edit_object(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - ToolSettings *ts = CTX_data_tool_settings(C); - int index = 0; - - if (TEMPLATES_HASH != NULL) { - BLI_ghash_free(TEMPLATES_HASH, NULL, NULL); - } - - TEMPLATES_HASH = BLI_ghash_int_new("makeListTemplates gh"); - TEMPLATES_CURRENT = 0; - - FOREACH_OBJECT_BEGIN(view_layer, ob) - { - if (ob != obedit && ob->type == OB_ARMATURE) { - index++; - BLI_ghash_insert(TEMPLATES_HASH, SET_INT_IN_POINTER(index), ob); - - if (ob == ts->skgen_template) { - TEMPLATES_CURRENT = index; - } - } - } - FOREACH_OBJECT_END; -} - -#if 0 /* UNUSED */ -const char *BIF_listTemplates(const bContext *UNUSED(C)) -{ - GHashIterator ghi; - const char *menu_header = IFACE_("Template %t|None %x0|"); - char *p; - const size_t template_size = (BLI_ghash_len(TEMPLATES_HASH) * 32 + 30); - - if (TEMPLATES_MENU != NULL) { - MEM_freeN(TEMPLATES_MENU); - } - - TEMPLATES_MENU = MEM_callocN(sizeof(char) * template_size, "skeleton template menu"); - - p = TEMPLATES_MENU; - p += BLI_strncpy_rlen(p, menu_header, template_size); - - BLI_ghashIterator_init(&ghi, TEMPLATES_HASH); - - while (!BLI_ghashIterator_done(&ghi)) { - Object *ob = BLI_ghashIterator_getValue(&ghi); - int key = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&ghi)); - - p += sprintf(p, "|%s %%x%i", ob->id.name + 2, key); - - BLI_ghashIterator_step(&ghi); - } - - return TEMPLATES_MENU; -} -#endif - -int BIF_currentTemplate(const bContext *C) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - - if (TEMPLATES_CURRENT == 0 && ts->skgen_template != NULL) { - GHashIterator ghi; - BLI_ghashIterator_init(&ghi, TEMPLATES_HASH); - - while (!BLI_ghashIterator_done(&ghi)) { - Object *ob = BLI_ghashIterator_getValue(&ghi); - int key = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&ghi)); - - if (ob == ts->skgen_template) { - TEMPLATES_CURRENT = key; - break; - } - - BLI_ghashIterator_step(&ghi); - } - } - - return TEMPLATES_CURRENT; -} - -static RigGraph *sk_makeTemplateGraph(const bContext *C, Object *ob) -{ - Object *obedit = CTX_data_edit_object(C); - if (ob == obedit) { - return NULL; - } - - if (ob != NULL) { - if (TEMPLATE_RIGG && TEMPLATE_RIGG->ob != ob) { - RIG_freeRigGraph((BGraph *)TEMPLATE_RIGG); - TEMPLATE_RIGG = NULL; - } - - if (TEMPLATE_RIGG == NULL) { - bArmature *arm; - - arm = ob->data; - - TEMPLATE_RIGG = RIG_graphFromArmature(C, ob, arm); - } - } - - return TEMPLATE_RIGG; -} - -int BIF_nbJointsTemplate(const bContext *C) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - RigGraph *rg = sk_makeTemplateGraph(C, ts->skgen_template); - - if (rg) { - return RIG_nbJoints(rg); - } - else { - return -1; - } -} - -const char *BIF_nameBoneTemplate(const bContext *C) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - SK_Sketch *stk = contextSketch(C, 1); - RigGraph *rg; - int index = 0; - - if (stk && stk->active_stroke != NULL) { - index = stk->active_stroke->nb_points; - } - - rg = sk_makeTemplateGraph(C, ts->skgen_template); - - if (rg == NULL) { - return ""; - } - - return RIG_nameBone(rg, 0, index); -} - -void BIF_freeTemplates(bContext *UNUSED(C)) -{ - if (TEMPLATES_MENU != NULL) { - MEM_freeN(TEMPLATES_MENU); - TEMPLATES_MENU = NULL; - } - - if (TEMPLATES_HASH != NULL) { - BLI_ghash_free(TEMPLATES_HASH, NULL, NULL); - TEMPLATES_HASH = NULL; - } - - if (TEMPLATE_RIGG != NULL) { - RIG_freeRigGraph((BGraph *)TEMPLATE_RIGG); - TEMPLATE_RIGG = NULL; - } -} - -void BIF_setTemplate(bContext *C, int index) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - if (index > 0) { - ts->skgen_template = BLI_ghash_lookup(TEMPLATES_HASH, SET_INT_IN_POINTER(index)); - } - else { - ts->skgen_template = NULL; - - if (TEMPLATE_RIGG != NULL) { - RIG_freeRigGraph((BGraph *)TEMPLATE_RIGG); - } - TEMPLATE_RIGG = NULL; - } -} - -/*********************** CONVERSION ***************************/ - -static void sk_autoname(bContext *C, ReebArc *arc) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - if (ts->skgen_retarget_options & SK_RETARGET_AUTONAME) { - if (arc == NULL) { - char *num = ts->skgen_num_string; - int i = atoi(num); - i++; - BLI_snprintf(num, 8, "%i", i); - } - else { - char *side = ts->skgen_side_string; - int valid = 0; - int caps = 0; - - if (side[0] == '\0') { - valid = 1; - } - else if (STREQ(side, "R") || STREQ(side, "L")) { - valid = 1; - caps = 1; - } - else if (STREQ(side, "r") || STREQ(side, "l")) { - valid = 1; - caps = 0; - } - - if (valid) { - if (arc->head->p[0] < 0) { - BLI_snprintf(side, 8, caps ? "R" : "r"); - } - else { - BLI_snprintf(side, 8, caps ? "L" : "l"); - } - } - } - } -} - -static ReebNode *sk_pointToNode(SK_Point *pt, float imat[4][4], float tmat[3][3]) -{ - ReebNode *node; - - node = MEM_callocN(sizeof(ReebNode), "reeb node"); - copy_v3_v3(node->p, pt->p); - mul_m4_v3(imat, node->p); - - copy_v3_v3(node->no, pt->no); - mul_m3_v3(tmat, node->no); - - return node; -} - -static ReebArc *sk_strokeToArc(SK_Stroke *stk, float imat[4][4], float tmat[3][3]) -{ - ReebArc *arc; - int i; - - arc = MEM_callocN(sizeof(ReebArc), "reeb arc"); - arc->head = sk_pointToNode(stk->points, imat, tmat); - arc->tail = sk_pointToNode(sk_lastStrokePoint(stk), imat, tmat); - - arc->bcount = stk->nb_points - 2; /* first and last are nodes, don't count */ - arc->buckets = MEM_callocN(sizeof(EmbedBucket) * arc->bcount, "Buckets"); - - for (i = 0; i < arc->bcount; i++) { - copy_v3_v3(arc->buckets[i].p, stk->points[i + 1].p); - mul_m4_v3(imat, arc->buckets[i].p); - - copy_v3_v3(arc->buckets[i].no, stk->points[i + 1].no); - mul_m3_v3(tmat, arc->buckets[i].no); - } - - return arc; -} - -static void sk_retargetStroke(bContext *C, SK_Stroke *stk) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - Object *obedit = CTX_data_edit_object(C); - float imat[4][4]; - float tmat[3][3]; - ReebArc *arc; - RigGraph *rg; - - invert_m4_m4(imat, obedit->obmat); - transpose_m3_m4(tmat, obedit->obmat); - - arc = sk_strokeToArc(stk, imat, tmat); - - sk_autoname(C, arc); - - rg = sk_makeTemplateGraph(C, ts->skgen_template); - - BIF_retargetArc(C, arc, rg); - - sk_autoname(C, NULL); - - MEM_freeN(arc->head); - MEM_freeN(arc->tail); - REEB_freeArc((BArc *)arc); -} - -/**************************************************************/ -static void sk_cancelStroke(SK_Sketch *sketch) -{ - if (sketch->active_stroke != NULL) { - sk_resetOverdraw(sketch); - sk_removeStroke(sketch, sketch->active_stroke); - } -} - - -static float sk_clampPointSize(SK_Point *pt, float size) -{ - return max_ff(size * pt->size, size / 2); -} - -static void sk_drawPoint(SK_Point *pt, float size, float color[4]) -{ - Gwn_Batch *batch = NULL; - - gpuTranslate3fv(pt->p); - - gpuPushMatrix(); - - gpuScaleUniform(sk_clampPointSize(pt, size)); - - batch = GPU_batch_preset_sphere(0); - GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); - GWN_batch_uniform_4fv(batch, "color", color); - - GWN_batch_draw(batch); - - gpuPopMatrix(); -} - -static void sk_drawEdge(SK_Point *pt0, SK_Point *pt1, float size, float color[4]) -{ - float vec1[3], vec2[3] = { 0, 0, 1 }, axis[3]; - float angle, length; - - Gwn_VertFormat *format = immVertexFormat(); - unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); - - sub_v3_v3v3(vec1, pt1->p, pt0->p); - length = normalize_v3(vec1); - cross_v3_v3v3(axis, vec2, vec1); - - if (is_zero_v3(axis)) { - axis[1] = 1; - } - - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - immUniformColor4fv(color); - - angle = angle_normalized_v3v3(vec2, vec1); - gpuRotate3fv(angle * (float)(180.0 / M_PI) + 180.0f, axis); - imm_draw_cylinder_fill_3d(pos, sk_clampPointSize(pt1, size), sk_clampPointSize(pt0, size), length, 8, 8); - - immUnbindProgram(); -} - -static void sk_drawNormal(SK_Point *pt, float size, float height) -{ - float vec2[3] = { 0, 0, 1 }, axis[3]; - float angle; - float color[3] = { 0.0f, 1.0f, 1.0f }; - - Gwn_VertFormat *format = immVertexFormat(); - unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); - - gpuPushMatrix(); - - cross_v3_v3v3(axis, vec2, pt->no); - - if (is_zero_v3(axis)) { - axis[1] = 1; - } - - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - immUniformColor4fv(color); - - angle = angle_normalized_v3v3(vec2, pt->no); - gpuRotate3fv(angle * (float)(180.0 / M_PI), axis); - - imm_draw_cylinder_fill_3d(pos, sk_clampPointSize(pt, size), 0, sk_clampPointSize(pt, height), 10, 2); - - immUnbindProgram(); - - gpuPopMatrix(); -} - -static void sk_drawStroke(SK_Stroke *stk, int id, float color[3], int start, int end) -{ - float rgb[3]; - float zero_color[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; - int i; - - if (id != -1) { - GPU_select_load_id(id); - - for (i = 0; i < stk->nb_points; i++) { - gpuPushMatrix(); - - sk_drawPoint(stk->points + i, 0.1, zero_color); - - if (i > 0) { - sk_drawEdge(stk->points + i - 1, stk->points + i, 0.1, zero_color); - } - - gpuPopMatrix(); - } - - } - else { - float d_rgb[3] = { 1, 1, 1 }; - float tmp_color[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; - - copy_v3_v3(rgb, color); - sub_v3_v3(d_rgb, rgb); - mul_v3_fl(d_rgb, 1.0f / (float)stk->nb_points); - - for (i = 0; i < stk->nb_points; i++) { - SK_Point *pt = stk->points + i; - - gpuPushMatrix(); - - if (pt->type == PT_EXACT) { - sk_drawPoint(pt, 0.15, zero_color); - sk_drawNormal(pt, 0.05, 0.9); - } - - if (i >= start && i <= end) { - copy_v4_fl4(tmp_color, 0.3f, 0.3f, 0.3f, 1.0f); - } - else { - copy_v4_fl4(tmp_color, rgb[0], rgb[1], rgb[2], 1.0f); - } - - if (pt->type != PT_EXACT) { - sk_drawPoint(pt, 0.1, tmp_color); - } - - if (i > 0) { - sk_drawEdge(pt - 1, pt, 0.1, tmp_color); - } - - gpuPopMatrix(); - - add_v3_v3(rgb, d_rgb); - } - } - -} - -static void drawSubdividedStrokeBy(ToolSettings *toolsettings, BArcIterator *iter, NextSubdivisionFunc next_subdividion) -{ - SK_Stroke *stk = ((SK_StrokeIterator *)iter)->stroke; - float head[3], tail[3]; - float color[4] = { 0.0f, 1.0f, 0.0f, 1.0f }; - int bone_start = 0; - int end = iter->length; - int index; - - iter->head(iter); - copy_v3_v3(head, iter->p); - - index = next_subdividion(toolsettings, iter, bone_start, end, head, tail); - while (index != -1) { - SK_Point *pt = stk->points + index; - - gpuPushMatrix(); - - sk_drawPoint(pt, 0.15, color); - - sk_drawNormal(pt, 0.05, 0.9); - - gpuPopMatrix(); - - copy_v3_v3(head, tail); - bone_start = index; // start next bone from current index - - index = next_subdividion(toolsettings, iter, bone_start, end, head, tail); - } -} - -static void sk_drawStrokeSubdivision(ToolSettings *toolsettings, SK_Stroke *stk) -{ - int head_index = -1; - int i; - - if (toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET) { - return; - } - - - for (i = 0; i < stk->nb_points; i++) { - SK_Point *pt = stk->points + i; - - if (pt->type == PT_EXACT || i == stk->nb_points - 1) /* stop on exact or on last point */ { - if (head_index == -1) { - head_index = i; - } - else { - if (i - head_index > 1) { - SK_StrokeIterator sk_iter; - BArcIterator *iter = (BArcIterator *)&sk_iter; - - initStrokeIterator(iter, stk, head_index, i); - - if (toolsettings->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE) { - drawSubdividedStrokeBy(toolsettings, iter, nextAdaptativeSubdivision); - } - else if (toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH) { - drawSubdividedStrokeBy(toolsettings, iter, nextLengthSubdivision); - } - else if (toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED) { - drawSubdividedStrokeBy(toolsettings, iter, nextFixedSubdivision); - } - - } - - head_index = i; - } - } - } -} - -static SK_Point *sk_snapPointStroke(bContext *C, SK_Stroke *stk, int mval[2], float *r_dist_px, int *index, int all_pts) -{ - ARegion *ar = CTX_wm_region(C); - SK_Point *pt = NULL; - int i; - - for (i = 0; i < stk->nb_points; i++) { - if (all_pts || stk->points[i].type == PT_EXACT) { - short pval[2]; - int pdist; - - if (ED_view3d_project_short_global(ar, stk->points[i].p, pval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - - pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]); - - if (pdist < *r_dist_px) { - *r_dist_px = pdist; - pt = stk->points + i; - - if (index != NULL) { - *index = i; - } - } - } - } - } - - return pt; -} - -#if 0 /* UNUSED 2.5 */ -static SK_Point *sk_snapPointArmature(bContext *C, Object *ob, ListBase *ebones, int mval[2], int *dist) -{ - ARegion *ar = CTX_wm_region(C); - SK_Point *pt = NULL; - EditBone *bone; - - for (bone = ebones->first; bone; bone = bone->next) - { - float vec[3]; - short pval[2]; - int pdist; - - if ((bone->flag & BONE_CONNECTED) == 0) - { - copy_v3_v3(vec, bone->head); - mul_m4_v3(ob->obmat, vec); - if (ED_view3d_project_short_noclip(ar, vec, pval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - - pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]); - - if (pdist < *dist) - { - *dist = pdist; - pt = &boneSnap; - copy_v3_v3(pt->p, vec); - pt->type = PT_EXACT; - } - } - } - - - copy_v3_v3(vec, bone->tail); - mul_m4_v3(ob->obmat, vec); - if (ED_view3d_project_short_noclip(ar, vec, pval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - - pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]); - - if (pdist < *dist) - { - *dist = pdist; - pt = &boneSnap; - copy_v3_v3(pt->p, vec); - pt->type = PT_EXACT; - } - } - } - - return pt; -} -#endif - -void sk_resetOverdraw(SK_Sketch *sketch) -{ - sketch->over.target = NULL; - sketch->over.start = -1; - sketch->over.end = -1; - sketch->over.count = 0; -} - -int sk_hasOverdraw(SK_Sketch *sketch, SK_Stroke *stk) -{ - return sketch->over.target && - sketch->over.count >= SK_OVERDRAW_LIMIT && - (sketch->over.target == stk || stk == NULL) && - (sketch->over.start != -1 || sketch->over.end != -1); -} - -static void sk_updateOverdraw(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) -{ - if (sketch->over.target == NULL) { - SK_Stroke *target; - int closest_index = -1; - float dist_px = SNAP_MIN_DISTANCE * 2; - - for (target = sketch->strokes.first; target; target = target->next) { - if (target != stk) { - int index; - - SK_Point *spt = sk_snapPointStroke(C, target, dd->mval, &dist_px, &index, 1); - - if (spt != NULL) { - sketch->over.target = target; - closest_index = index; - } - } - } - - if (sketch->over.target != NULL) { - if (closest_index > -1) { - if (sk_lastStrokePoint(stk)->type == PT_EXACT) { - sketch->over.count = SK_OVERDRAW_LIMIT; - } - else { - sketch->over.count++; - } - } - - if (stk->nb_points == 1) { - sketch->over.start = closest_index; - } - else { - sketch->over.end = closest_index; - } - } - } - else if (sketch->over.target != NULL) { - SK_Point *closest_pt = NULL; - float dist_px = SNAP_MIN_DISTANCE * 2; - int index; - - closest_pt = sk_snapPointStroke(C, sketch->over.target, dd->mval, &dist_px, &index, 1); - - if (closest_pt != NULL) { - if (sk_lastStrokePoint(stk)->type == PT_EXACT) { - sketch->over.count = SK_OVERDRAW_LIMIT; - } - else { - sketch->over.count++; - } - - sketch->over.end = index; - } - else { - sketch->over.end = -1; - } - } -} - -/* return 1 on reverse needed */ -static int sk_adjustIndexes(SK_Sketch *sketch, int *start, int *end) -{ - int retval = 0; - - *start = sketch->over.start; - *end = sketch->over.end; - - if (*start == -1) { - *start = 0; - } - - if (*end == -1) { - *end = sketch->over.target->nb_points - 1; - } - - if (*end < *start) { - int tmp = *start; - *start = *end; - *end = tmp; - retval = 1; - } - - return retval; -} - -static void sk_endOverdraw(SK_Sketch *sketch) -{ - SK_Stroke *stk = sketch->active_stroke; - - if (sk_hasOverdraw(sketch, NULL)) { - int start; - int end; - - if (sk_adjustIndexes(sketch, &start, &end)) { - sk_reverseStroke(stk); - } - - if (stk->nb_points > 1) { - stk->points->type = sketch->over.target->points[start].type; - sk_lastStrokePoint(stk)->type = sketch->over.target->points[end].type; - } - - sk_insertStrokePoints(sketch->over.target, stk->points, stk->nb_points, start, end); - - sk_removeStroke(sketch, stk); - - sk_resetOverdraw(sketch); - } -} - - -static void sk_startStroke(SK_Sketch *sketch) -{ - SK_Stroke *stk = sk_createStroke(); - - BLI_addtail(&sketch->strokes, stk); - sketch->active_stroke = stk; - - sk_resetOverdraw(sketch); -} - -static void sk_endStroke(bContext *C, SK_Sketch *sketch) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - sk_shrinkStrokeBuffer(sketch->active_stroke); - - if (ts->bone_sketching & BONE_SKETCHING_ADJUST) { - sk_endOverdraw(sketch); - } - - sketch->active_stroke = NULL; -} - -static void sk_updateDrawData(SK_DrawData *dd) -{ - dd->type = PT_CONTINUOUS; - - dd->previous_mval[0] = dd->mval[0]; - dd->previous_mval[1] = dd->mval[1]; -} - -static float sk_distanceDepth(bContext *C, float p1[3], float p2[3]) -{ - ARegion *ar = CTX_wm_region(C); - RegionView3D *rv3d = ar->regiondata; - float vec[3]; - float distance; - - sub_v3_v3v3(vec, p1, p2); - - project_v3_v3v3(vec, vec, rv3d->viewinv[2]); - - distance = len_v3(vec); - - if (dot_v3v3(rv3d->viewinv[2], vec) > 0) { - distance *= -1; - } - - return distance; -} - -static void sk_interpolateDepth(bContext *C, SK_Stroke *stk, int start, int end, float length, float distance) -{ - ARegion *ar = CTX_wm_region(C); - ScrArea *sa = CTX_wm_area(C); - View3D *v3d = sa->spacedata.first; - - float progress = 0; - int i; - - progress = len_v3v3(stk->points[start].p, stk->points[start - 1].p); - - for (i = start; i <= end; i++) { - float ray_start[3], ray_normal[3]; - float delta = len_v3v3(stk->points[i].p, stk->points[i + 1].p); - float pval[2] = {0, 0}; - - ED_view3d_project_float_global(ar, stk->points[i].p, pval, V3D_PROJ_TEST_NOP); - ED_view3d_win_to_ray(CTX_data_depsgraph(C), ar, v3d, pval, ray_start, ray_normal, false); - - mul_v3_fl(ray_normal, distance * progress / length); - add_v3_v3(stk->points[i].p, ray_normal); - - progress += delta; - } -} - -static void sk_projectDrawPoint(bContext *C, float vec[3], SK_Stroke *stk, SK_DrawData *dd) -{ - ARegion *ar = CTX_wm_region(C); - /* copied from grease pencil, need fixing */ - SK_Point *last = sk_lastStrokePoint(stk); - short cval[2]; - float fp[3] = {0, 0, 0}; - float dvec[3]; - float mval_f[2]; - float zfac; - - if (last != NULL) { - copy_v3_v3(fp, last->p); - } - - zfac = ED_view3d_calc_zfac(ar->regiondata, fp, NULL); - - if (ED_view3d_project_short_global(ar, fp, cval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - VECSUB2D(mval_f, cval, dd->mval); - ED_view3d_win_to_delta(ar, mval_f, dvec, zfac); - sub_v3_v3v3(vec, fp, dvec); - } - else { - zero_v3(vec); - } -} - -static int sk_getStrokeDrawPoint(bContext *C, SK_Point *pt, SK_Sketch *UNUSED(sketch), SK_Stroke *stk, SK_DrawData *dd) -{ - pt->type = dd->type; - pt->mode = PT_PROJECT; - sk_projectDrawPoint(C, pt->p, stk, dd); - - return 1; -} - -static int sk_addStrokeDrawPoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) -{ - ARegion *ar = CTX_wm_region(C); - RegionView3D *rv3d = ar->regiondata; - SK_Point pt; - - sk_initPoint(&pt, dd, rv3d->viewinv[2]); - - sk_getStrokeDrawPoint(C, &pt, sketch, stk, dd); - - sk_appendStrokePoint(stk, &pt); - - return 1; -} - -static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - int point_added = 0; - - /* TODO: Since the function `ED_transform_snap_object_context_create_view3d` creates a cache, - * the ideal would be to call this function only at the beginning of the snap operation, - * or at the beginning of the operator itself */ - struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), CTX_data_scene(C), CTX_data_depsgraph(C), 0, - CTX_wm_region(C), CTX_wm_view3d(C)); - - float mvalf[2] = {UNPACK2(dd->mval)}; - float loc[3], dummy_no[3]; - - if (ts->snap_mode == SCE_SNAP_MODE_VOLUME) { - float size; - if (peelObjectsSnapContext( - snap_context, mvalf, - &(const struct SnapObjectParams){ - .snap_select = SNAP_NOT_SELECTED, - .use_object_edit_cage = false, - }, - (ts->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0, - loc, dummy_no, &size)) - { - pt->type = dd->type; - pt->mode = PT_SNAP; - pt->size = size / 2; - copy_v3_v3(pt->p, loc); - - point_added = 1; - } - } - else { - SK_Stroke *snap_stk; - float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here - - /* snap to strokes */ - // if (ts->snap_mode == SCE_SNAP_MODE_VERTEX) /* snap all the time to strokes */ - for (snap_stk = sketch->strokes.first; snap_stk; snap_stk = snap_stk->next) { - SK_Point *spt = NULL; - if (snap_stk == stk) { - spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist_px, NULL, 0); - } - else { - spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist_px, NULL, 1); - } - - if (spt != NULL) { - copy_v3_v3(pt->p, spt->p); - point_added = 1; - } - } - - /* try to snap to closer object */ - { - if (ED_transform_snap_object_project_view3d( - snap_context, - ts->snap_mode, - &(const struct SnapObjectParams){ - .snap_select = SNAP_NOT_SELECTED, - .use_object_edit_cage = false, - }, - mvalf, &dist_px, NULL, - loc, dummy_no)) - { - pt->type = dd->type; - pt->mode = PT_SNAP; - copy_v3_v3(pt->p, loc); - - point_added = 1; - } - } - } - - /* TODO: The ideal would be to call this function only once. - * At the end of the operator */ - ED_transform_snap_object_context_destroy(snap_context); - return point_added; -} - -static int sk_addStrokeSnapPoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) -{ - int point_added; - ARegion *ar = CTX_wm_region(C); - RegionView3D *rv3d = ar->regiondata; - SK_Point pt; - - sk_initPoint(&pt, dd, rv3d->viewinv[2]); - - point_added = sk_getStrokeSnapPoint(C, &pt, sketch, stk, dd); - - if (point_added) { - float final_p[3]; - float length, distance; - int total; - int i; - - copy_v3_v3(final_p, pt.p); - - sk_projectDrawPoint(C, pt.p, stk, dd); - sk_appendStrokePoint(stk, &pt); - - /* update all previous point to give smooth Z progresion */ - total = 0; - length = 0; - for (i = stk->nb_points - 2; i > 0; i--) { - length += len_v3v3(stk->points[i].p, stk->points[i + 1].p); - total++; - if (stk->points[i].mode == PT_SNAP || stk->points[i].type == PT_EXACT) { - break; - } - } - - if (total > 1) { - distance = sk_distanceDepth(C, final_p, stk->points[i].p); - - sk_interpolateDepth(C, stk, i + 1, stk->nb_points - 2, length, distance); - } - - copy_v3_v3(stk->points[stk->nb_points - 1].p, final_p); - - point_added = 1; - } - - return point_added; -} - -static void sk_addStrokePoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, const bool snap) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - int point_added = 0; - - if (snap) { - point_added = sk_addStrokeSnapPoint(C, sketch, stk, dd); - } - - if (point_added == 0) { - point_added = sk_addStrokeDrawPoint(C, sketch, stk, dd); - } - - if (stk == sketch->active_stroke && ts->bone_sketching & BONE_SKETCHING_ADJUST) { - sk_updateOverdraw(C, sketch, stk, dd); - } -} - -static void sk_getStrokePoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, const bool snap) -{ - int point_added = 0; - - if (snap) { - point_added = sk_getStrokeSnapPoint(C, pt, sketch, stk, dd); - LAST_SNAP_POINT_VALID = 1; - copy_v3_v3(LAST_SNAP_POINT, pt->p); - } - else { - LAST_SNAP_POINT_VALID = 0; - } - - if (point_added == 0) { - point_added = sk_getStrokeDrawPoint(C, pt, sketch, stk, dd); - } -} - -/********************************************/ - -static void *headPoint(void *arg); -static void *tailPoint(void *arg); -static void *nextPoint(void *arg); -static void *nextNPoint(void *arg, int n); -static void *peekPoint(void *arg, int n); -static void *previousPoint(void *arg); -static int iteratorStopped(void *arg); - -static void initIteratorFct(SK_StrokeIterator *iter) -{ - iter->head = headPoint; - iter->tail = tailPoint; - iter->peek = peekPoint; - iter->next = nextPoint; - iter->nextN = nextNPoint; - iter->previous = previousPoint; - iter->stopped = iteratorStopped; -} - -static SK_Point *setIteratorValues(SK_StrokeIterator *iter, int index) -{ - SK_Point *pt = NULL; - - if (index >= 0 && index < iter->length) { - pt = &(iter->stroke->points[iter->start + (iter->stride * index)]); - iter->p = pt->p; - iter->no = pt->no; - iter->size = pt->size; - } - else { - iter->p = NULL; - iter->no = NULL; - iter->size = 0; - } - - return pt; -} - -void initStrokeIterator(BArcIterator *arg, SK_Stroke *stk, int start, int end) -{ - SK_StrokeIterator *iter = (SK_StrokeIterator *)arg; - - initIteratorFct(iter); - iter->stroke = stk; - - if (start < end) { - iter->start = start + 1; - iter->end = end - 1; - iter->stride = 1; - } - else { - iter->start = start - 1; - iter->end = end + 1; - iter->stride = -1; - } - - iter->length = iter->stride * (iter->end - iter->start + 1); - - iter->index = -1; -} - - -static void *headPoint(void *arg) -{ - SK_StrokeIterator *iter = (SK_StrokeIterator *)arg; - SK_Point *result = NULL; - - result = &(iter->stroke->points[iter->start - iter->stride]); - iter->p = result->p; - iter->no = result->no; - iter->size = result->size; - - return result; -} - -static void *tailPoint(void *arg) -{ - SK_StrokeIterator *iter = (SK_StrokeIterator *)arg; - SK_Point *result = NULL; - - result = &(iter->stroke->points[iter->end + iter->stride]); - iter->p = result->p; - iter->no = result->no; - iter->size = result->size; - - return result; -} - -static void *nextPoint(void *arg) -{ - SK_StrokeIterator *iter = (SK_StrokeIterator *)arg; - SK_Point *result = NULL; - - iter->index++; - if (iter->index < iter->length) { - result = setIteratorValues(iter, iter->index); - } - - return result; -} - -static void *nextNPoint(void *arg, int n) -{ - SK_StrokeIterator *iter = (SK_StrokeIterator *)arg; - SK_Point *result = NULL; - - iter->index += n; - - /* check if passed end */ - if (iter->index < iter->length) { - result = setIteratorValues(iter, iter->index); - } - - return result; -} - -static void *peekPoint(void *arg, int n) -{ - SK_StrokeIterator *iter = (SK_StrokeIterator *)arg; - SK_Point *result = NULL; - int index = iter->index + n; - - /* check if passed end */ - if (index < iter->length) { - result = setIteratorValues(iter, index); - } - - return result; -} - -static void *previousPoint(void *arg) -{ - SK_StrokeIterator *iter = (SK_StrokeIterator *)arg; - SK_Point *result = NULL; - - if (iter->index > 0) { - iter->index--; - result = setIteratorValues(iter, iter->index); - } - - return result; -} - -static int iteratorStopped(void *arg) -{ - SK_StrokeIterator *iter = (SK_StrokeIterator *)arg; - - if (iter->index >= iter->length) { - return 1; - } - else { - return 0; - } -} - -static void sk_convertStroke(bContext *C, SK_Stroke *stk) -{ - Object *obedit = CTX_data_edit_object(C); - ToolSettings *ts = CTX_data_tool_settings(C); - bArmature *arm = obedit->data; - SK_Point *head; - EditBone *parent = NULL; - float invmat[4][4]; /* move in caller function */ - float tmat[3][3]; - int head_index = 0; - int i; - - head = NULL; - - invert_m4_m4(invmat, obedit->obmat); - transpose_m3_m4(tmat, obedit->obmat); - - for (i = 0; i < stk->nb_points; i++) { - SK_Point *pt = stk->points + i; - - if (pt->type == PT_EXACT) { - if (head == NULL) { - head_index = i; - head = pt; - } - else { - EditBone *bone = NULL; - EditBone *new_parent; - - if (i - head_index > 1) { - SK_StrokeIterator sk_iter; - BArcIterator *iter = (BArcIterator *)&sk_iter; - - initStrokeIterator(iter, stk, head_index, i); - - if (ts->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE) { - bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextAdaptativeSubdivision); - } - else if (ts->bone_sketching_convert == SK_CONVERT_CUT_LENGTH) { - bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextLengthSubdivision); - } - else if (ts->bone_sketching_convert == SK_CONVERT_CUT_FIXED) { - bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextFixedSubdivision); - } - } - - if (bone == NULL) { - bone = ED_armature_ebone_add(arm, "Bone"); - - copy_v3_v3(bone->head, head->p); - copy_v3_v3(bone->tail, pt->p); - - mul_m4_v3(invmat, bone->head); - mul_m4_v3(invmat, bone->tail); - setBoneRollFromNormal(bone, head->no, invmat, tmat); - } - - new_parent = bone; - bone->flag |= BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL; - - /* move to end of chain */ - while (bone->parent != NULL) { - bone = bone->parent; - bone->flag |= BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL; - } - - if (parent != NULL) { - bone->parent = parent; - bone->flag |= BONE_CONNECTED; - } - - parent = new_parent; - head_index = i; - head = pt; - } - } - } -} - -static void sk_convert(bContext *C, SK_Sketch *sketch) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - SK_Stroke *stk; - - for (stk = sketch->strokes.first; stk; stk = stk->next) { - if (stk->selected == 1) { - if (ts->bone_sketching_convert == SK_CONVERT_RETARGET) { - sk_retargetStroke(C, stk); - } - else { - sk_convertStroke(C, stk); - } -// XXX -// allqueue(REDRAWBUTSEDIT, 0); - } - } -} -/******************* GESTURE *************************/ - - -/* returns the number of self intersections */ -static int sk_getSelfIntersections(bContext *C, ListBase *list, SK_Stroke *gesture) -{ - ARegion *ar = CTX_wm_region(C); - int added = 0; - int s_i; - - for (s_i = 0; s_i < gesture->nb_points - 1; s_i++) { - float s_p1[3] = {0, 0, 0}; - float s_p2[3] = {0, 0, 0}; - int g_i; - - ED_view3d_project_float_global(ar, gesture->points[s_i].p, s_p1, V3D_PROJ_TEST_NOP); - ED_view3d_project_float_global(ar, gesture->points[s_i + 1].p, s_p2, V3D_PROJ_TEST_NOP); - - /* start checking from second next, because two consecutive cannot intersect */ - for (g_i = s_i + 2; g_i < gesture->nb_points - 1; g_i++) { - float g_p1[3] = {0, 0, 0}; - float g_p2[3] = {0, 0, 0}; - float vi[3]; - float lambda; - - ED_view3d_project_float_global(ar, gesture->points[g_i].p, g_p1, V3D_PROJ_TEST_NOP); - ED_view3d_project_float_global(ar, gesture->points[g_i + 1].p, g_p2, V3D_PROJ_TEST_NOP); - - if (isect_line_line_strict_v3(s_p1, s_p2, g_p1, g_p2, vi, &lambda)) { - SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection"); - - isect->gesture_index = g_i; - isect->before = s_i; - isect->after = s_i + 1; - isect->stroke = gesture; - - sub_v3_v3v3(isect->p, gesture->points[s_i + 1].p, gesture->points[s_i].p); - mul_v3_fl(isect->p, lambda); - add_v3_v3(isect->p, gesture->points[s_i].p); - - BLI_addtail(list, isect); - - added++; - } - } - } - - return added; -} - -static int cmpIntersections(const void *i1, const void *i2) -{ - const SK_Intersection *isect1 = i1, *isect2 = i2; - - if (isect1->stroke == isect2->stroke) { - if (isect1->before < isect2->before) { - return -1; - } - else if (isect1->before > isect2->before) { - return 1; - } - else { - if (isect1->lambda < isect2->lambda) { - return -1; - } - else if (isect1->lambda > isect2->lambda) { - return 1; - } - } - } - - return 0; -} - - -/* returns the maximum number of intersections per stroke */ -static int sk_getIntersections(bContext *C, ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture) -{ - Depsgraph *depsgraph = CTX_data_depsgraph(C); - ARegion *ar = CTX_wm_region(C); - ScrArea *sa = CTX_wm_area(C); - View3D *v3d = sa->spacedata.first; - SK_Stroke *stk; - int added = 0; - - for (stk = sketch->strokes.first; stk; stk = stk->next) { - int s_added = 0; - int s_i; - - for (s_i = 0; s_i < stk->nb_points - 1; s_i++) { - float s_p1[3] = {0, 0, 0}; - float s_p2[3] = {0, 0, 0}; - int g_i; - - ED_view3d_project_float_global(ar, stk->points[s_i].p, s_p1, V3D_PROJ_TEST_NOP); - ED_view3d_project_float_global(ar, stk->points[s_i + 1].p, s_p2, V3D_PROJ_TEST_NOP); - - for (g_i = 0; g_i < gesture->nb_points - 1; g_i++) { - float g_p1[3] = {0, 0, 0}; - float g_p2[3] = {0, 0, 0}; - float vi[3]; - float lambda; - - ED_view3d_project_float_global(ar, gesture->points[g_i].p, g_p1, V3D_PROJ_TEST_NOP); - ED_view3d_project_float_global(ar, gesture->points[g_i + 1].p, g_p2, V3D_PROJ_TEST_NOP); - - if (isect_line_line_strict_v3(s_p1, s_p2, g_p1, g_p2, vi, &lambda)) { - SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection"); - float ray_start[3], ray_end[3]; - float mval[2]; - - isect->gesture_index = g_i; - isect->before = s_i; - isect->after = s_i + 1; - isect->stroke = stk; - isect->lambda = lambda; - - mval[0] = vi[0]; - mval[1] = vi[1]; - ED_view3d_win_to_segment(depsgraph, ar, v3d, mval, ray_start, ray_end, true); - - isect_line_line_v3(stk->points[s_i].p, - stk->points[s_i + 1].p, - ray_start, - ray_end, - isect->p, - vi); - - BLI_addtail(list, isect); - - s_added++; - } - } - } - - added = MAX2(s_added, added); - } - - BLI_listbase_sort(list, cmpIntersections); - - return added; -} - -static int sk_getSegments(SK_Stroke *segments, SK_Stroke *gesture) -{ - SK_StrokeIterator sk_iter; - BArcIterator *iter = (BArcIterator *)&sk_iter; - - float CORRELATION_THRESHOLD = 0.99f; - float *vec; - int i, j; - - sk_appendStrokePoint(segments, &gesture->points[0]); - vec = segments->points[segments->nb_points - 1].p; - - initStrokeIterator(iter, gesture, 0, gesture->nb_points - 1); - - for (i = 1, j = 0; i < gesture->nb_points; i++) { - float n[3]; - - /* Calculate normal */ - sub_v3_v3v3(n, gesture->points[i].p, vec); - - if (calcArcCorrelation(iter, j, i, vec, n) < CORRELATION_THRESHOLD) { - j = i - 1; - sk_appendStrokePoint(segments, &gesture->points[j]); - vec = segments->points[segments->nb_points - 1].p; - segments->points[segments->nb_points - 1].type = PT_EXACT; - } - } - - sk_appendStrokePoint(segments, &gesture->points[gesture->nb_points - 1]); - - return segments->nb_points - 1; -} - -int sk_detectCutGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - if (gest->nb_segments == 1 && gest->nb_intersections == 1) { - return 1; - } - - return 0; -} - -void sk_applyCutGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - SK_Intersection *isect; - - for (isect = gest->intersections.first; isect; isect = isect->next) { - SK_Point pt; - - pt.type = PT_EXACT; - pt.mode = PT_PROJECT; /* take mode from neighboring points */ - copy_v3_v3(pt.p, isect->p); - copy_v3_v3(pt.no, isect->stroke->points[isect->before].no); - - sk_insertStrokePoint(isect->stroke, &pt, isect->after); - } -} - -int sk_detectTrimGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - if (gest->nb_segments == 2 && gest->nb_intersections == 1 && gest->nb_self_intersections == 0) { - float s1[3], s2[3]; - float angle; - - sub_v3_v3v3(s1, gest->segments->points[1].p, gest->segments->points[0].p); - sub_v3_v3v3(s2, gest->segments->points[2].p, gest->segments->points[1].p); - - angle = RAD2DEGF(angle_v2v2(s1, s2)); - - if (angle > 60 && angle < 120) { - return 1; - } - } - - return 0; -} - -void sk_applyTrimGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - SK_Intersection *isect; - float trim_dir[3]; - - sub_v3_v3v3(trim_dir, gest->segments->points[2].p, gest->segments->points[1].p); - - for (isect = gest->intersections.first; isect; isect = isect->next) { - SK_Point pt; - float stroke_dir[3]; - - pt.type = PT_EXACT; - pt.mode = PT_PROJECT; /* take mode from neighboring points */ - copy_v3_v3(pt.p, isect->p); - copy_v3_v3(pt.no, isect->stroke->points[isect->before].no); - - sub_v3_v3v3(stroke_dir, isect->stroke->points[isect->after].p, isect->stroke->points[isect->before].p); - - /* same direction, trim end */ - if (dot_v3v3(stroke_dir, trim_dir) > 0) { - sk_replaceStrokePoint(isect->stroke, &pt, isect->after); - sk_trimStroke(isect->stroke, 0, isect->after); - } - /* else, trim start */ - else { - sk_replaceStrokePoint(isect->stroke, &pt, isect->before); - sk_trimStroke(isect->stroke, isect->before, isect->stroke->nb_points - 1); - } - - } -} - -int sk_detectCommandGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - if (gest->nb_segments > 2 && gest->nb_intersections == 2 && gest->nb_self_intersections == 1) { - SK_Intersection *isect, *self_isect; - - /* get the last intersection of the first pair */ - for (isect = gest->intersections.first; isect; isect = isect->next) { - if (isect->stroke == isect->next->stroke) { - isect = isect->next; - break; - } - } - - self_isect = gest->self_intersections.first; - - if (isect && isect->gesture_index < self_isect->gesture_index) { - return 1; - } - } - - return 0; -} - -void sk_applyCommandGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - SK_Intersection *isect; - int command = 1; - -/* XXX */ -/* command = pupmenu("Action %t|Flatten %x1|Straighten %x2|Polygonize %x3"); */ - if (command < 1) return; - - for (isect = gest->intersections.first; isect; isect = isect->next) { - SK_Intersection *i2; - - i2 = isect->next; - - if (i2 && i2->stroke == isect->stroke) { - switch (command) { - case 1: - sk_flattenStroke(isect->stroke, isect->before, i2->after); - break; - case 2: - sk_straightenStroke(isect->stroke, isect->before, i2->after, isect->p, i2->p); - break; - case 3: - sk_polygonizeStroke(isect->stroke, isect->before, i2->after); - break; - } - - isect = i2; - } - } -} - -int sk_detectDeleteGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - if (gest->nb_segments == 2 && gest->nb_intersections == 2) { - float s1[3], s2[3]; - float angle; - - sub_v3_v3v3(s1, gest->segments->points[1].p, gest->segments->points[0].p); - sub_v3_v3v3(s2, gest->segments->points[2].p, gest->segments->points[1].p); - - angle = RAD2DEGF(angle_v2v2(s1, s2)); - - if (angle > 120) { - return 1; - } - } - - return 0; -} - -void sk_applyDeleteGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *sketch) -{ - SK_Intersection *isect; - - for (isect = gest->intersections.first; isect; isect = isect->next) { - /* only delete strokes that are crossed twice */ - if (isect->next && isect->next->stroke == isect->stroke) { - isect = isect->next; - - sk_removeStroke(sketch, isect->stroke); - } - } -} - -int sk_detectMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - ARegion *ar = CTX_wm_region(C); - if (gest->nb_segments > 2 && gest->nb_intersections == 2) { - int start_val[2], end_val[2]; - int dist; - - if ((ED_view3d_project_int_global(ar, gest->stk->points[0].p, start_val, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) && - (ED_view3d_project_int_global(ar, sk_lastStrokePoint(gest->stk)->p, end_val, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK)) - { - dist = len_manhattan_v2v2_int(start_val, end_val); - - /* if gesture is a circle */ - if (dist <= 20) { - SK_Intersection *isect; - - /* check if it circled around an exact point */ - for (isect = gest->intersections.first; isect; isect = isect->next) { - /* only delete strokes that are crossed twice */ - if (isect->next && isect->next->stroke == isect->stroke) { - int start_index, end_index; - int i; - - start_index = MIN2(isect->after, isect->next->after); - end_index = MAX2(isect->before, isect->next->before); - - for (i = start_index; i <= end_index; i++) { - if (isect->stroke->points[i].type == PT_EXACT) { - return 1; /* at least one exact point found, stop detect here */ - } - } - - /* skip next */ - isect = isect->next; - } - } - } - } - } - - return 0; -} - -void sk_applyMergeGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - SK_Intersection *isect; - - /* check if it circled around an exact point */ - for (isect = gest->intersections.first; isect; isect = isect->next) { - /* only merge strokes that are crossed twice */ - if (isect->next && isect->next->stroke == isect->stroke) { - int start_index, end_index; - int i; - - start_index = MIN2(isect->after, isect->next->after); - end_index = MAX2(isect->before, isect->next->before); - - for (i = start_index; i <= end_index; i++) { - /* if exact, switch to continuous */ - if (isect->stroke->points[i].type == PT_EXACT) { - isect->stroke->points[i].type = PT_CONTINUOUS; - } - } - - /* skip next */ - isect = isect->next; - } - } -} - -int sk_detectReverseGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - if (gest->nb_segments > 2 && gest->nb_intersections == 2 && gest->nb_self_intersections == 0) { - SK_Intersection *isect; - - /* check if it circled around an exact point */ - for (isect = gest->intersections.first; isect; isect = isect->next) { - /* only delete strokes that are crossed twice */ - if (isect->next && isect->next->stroke == isect->stroke) { - float start_v[3], end_v[3]; - float angle; - - if (isect->gesture_index < isect->next->gesture_index) { - sub_v3_v3v3(start_v, isect->p, gest->stk->points[0].p); - sub_v3_v3v3(end_v, sk_lastStrokePoint(gest->stk)->p, isect->next->p); - } - else { - sub_v3_v3v3(start_v, isect->next->p, gest->stk->points[0].p); - sub_v3_v3v3(end_v, sk_lastStrokePoint(gest->stk)->p, isect->p); - } - - angle = RAD2DEGF(angle_v2v2(start_v, end_v)); - - if (angle > 120) { - return 1; - } - - /* skip next */ - isect = isect->next; - } - } - } - - return 0; -} - -void sk_applyReverseGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - SK_Intersection *isect; - - for (isect = gest->intersections.first; isect; isect = isect->next) { - /* only reverse strokes that are crossed twice */ - if (isect->next && isect->next->stroke == isect->stroke) { - sk_reverseStroke(isect->stroke); - - /* skip next */ - isect = isect->next; - } - } -} - -int sk_detectConvertGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - if (gest->nb_segments == 3 && gest->nb_self_intersections == 1) { - return 1; - } - return 0; -} - -void sk_applyConvertGesture(bContext *C, SK_Gesture *UNUSED(gest), SK_Sketch *sketch) -{ - sk_convert(C, sketch); -} - -static void sk_initGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch) -{ - BLI_listbase_clear(&gest->intersections); - BLI_listbase_clear(&gest->self_intersections); - - gest->segments = sk_createStroke(); - gest->stk = sketch->gesture; - - gest->nb_self_intersections = sk_getSelfIntersections(C, &gest->self_intersections, gest->stk); - gest->nb_intersections = sk_getIntersections(C, &gest->intersections, sketch, gest->stk); - gest->nb_segments = sk_getSegments(gest->segments, gest->stk); -} - -static void sk_freeGesture(SK_Gesture *gest) -{ - sk_freeStroke(gest->segments); - BLI_freelistN(&gest->intersections); - BLI_freelistN(&gest->self_intersections); -} - -static void sk_applyGesture(bContext *C, SK_Sketch *sketch) -{ - SK_Gesture gest; - SK_GestureAction *act; - - sk_initGesture(C, &gest, sketch); - - /* detect and apply */ - for (act = GESTURE_ACTIONS; act->apply != NULL; act++) { - if (act->detect(C, &gest, sketch)) { - act->apply(C, &gest, sketch); - break; - } - } - - sk_freeGesture(&gest); -} - -/********************************************/ - - -static bool sk_selectStroke(bContext *C, SK_Sketch *sketch, const int mval[2], const bool extend) -{ - ViewContext vc; - rcti rect; - unsigned int buffer[MAXPICKBUF]; - short hits; - - ED_view3d_viewcontext_init(C, &vc); - - BLI_rcti_init_pt_radius(&rect, mval, 5); - - hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST); - - if (hits > 0) { - int besthitresult = -1; - - if (hits == 1) { - besthitresult = buffer[3]; - } - else { - besthitresult = buffer[3]; - /* loop and get best hit */ - } - - if (besthitresult > 0) { - SK_Stroke *selected_stk = BLI_findlink(&sketch->strokes, besthitresult - 1); - - if (extend == 0) { - sk_selectAllSketch(sketch, -1); - - selected_stk->selected = 1; - } - else { - selected_stk->selected ^= 1; - } - - - } - return 1; - } - - return 0; -} - -#if 0 /* UNUSED 2.5 */ -static void sk_queueRedrawSketch(SK_Sketch *sketch) -{ - if (sketch->active_stroke != NULL) - { - SK_Point *last = sk_lastStrokePoint(sketch->active_stroke); - - if (last != NULL) - { -// XXX -// allqueue(REDRAWVIEW3D, 0); - } - } -} -#endif - -static void sk_drawSketch(Scene *scene, View3D *UNUSED(v3d), SK_Sketch *sketch, int with_names) -{ - ToolSettings *ts = scene->toolsettings; - SK_Stroke *stk; - - glClear(GL_DEPTH_BUFFER_BIT); - glEnable(GL_DEPTH_TEST); - - if (with_names) { - int id; - for (id = 1, stk = sketch->strokes.first; stk; id++, stk = stk->next) { - sk_drawStroke(stk, id, NULL, -1, -1); - } - - GPU_select_load_id(-1); - } - else { - float selected_rgb[3] = { 1, 0, 0 }; - float unselected_rgb[3] = { 1, 0.5, 0 }; - float tmp_color[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; - for (stk = sketch->strokes.first; stk; stk = stk->next) { - int start = -1; - int end = -1; - - if (sk_hasOverdraw(sketch, stk)) { - sk_adjustIndexes(sketch, &start, &end); - } - - sk_drawStroke(stk, -1, (stk->selected == 1 ? selected_rgb : unselected_rgb), start, end); - - if (stk->selected == 1) { - sk_drawStrokeSubdivision(ts, stk); - } - } - - if (sketch->active_stroke != NULL) { - SK_Point *last = sk_lastStrokePoint(sketch->active_stroke); - - if (ts->bone_sketching & BONE_SKETCHING_QUICK) { - sk_drawStrokeSubdivision(ts, sketch->active_stroke); - } - - if (last != NULL) { - gpuPushMatrix(); - - glEnable(GL_BLEND); - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - - switch (sketch->next_point.mode) { - case PT_SNAP: - copy_v4_fl4(tmp_color, 0.0f, 1.0f, 0.0f, 1.0f); - break; - case PT_PROJECT: - copy_v4_fl4(tmp_color, 0.0f, 0.0f, 0.0f, 1.0f); - break; - } - - sk_drawPoint(&sketch->next_point, 0.1, tmp_color); - - copy_v4_fl4(tmp_color, selected_rgb[0], selected_rgb[1], selected_rgb[2], 0.3); - sk_drawEdge(last, &sketch->next_point, 0.1f, tmp_color); - - glDisable(GL_BLEND); - - gpuPopMatrix(); - } - } - } - - glDisable(GL_DEPTH_TEST); - - /* only draw gesture in active area */ - if (sketch->gesture != NULL /* && area_is_active_area(G.vd->area) */) { - float gesture_rgb[3] = { 0, 0.5, 1 }; - sk_drawStroke(sketch->gesture, -1, gesture_rgb, -1, -1); - } -} - -static int sk_finish_stroke(bContext *C, SK_Sketch *sketch) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - - if (sketch->active_stroke != NULL) { - SK_Stroke *stk = sketch->active_stroke; - - sk_endStroke(C, sketch); - - if (ts->bone_sketching & BONE_SKETCHING_QUICK) { - if (ts->bone_sketching_convert == SK_CONVERT_RETARGET) { - sk_retargetStroke(C, stk); - } - else { - sk_convertStroke(C, stk); - } -// XXX -// BIF_undo_push("Convert Sketch"); - sk_removeStroke(sketch, stk); -// XXX -// allqueue(REDRAWBUTSEDIT, 0); - } - -// XXX -// allqueue(REDRAWVIEW3D, 0); - return 1; - } - - return 0; -} - -static void sk_start_draw_stroke(SK_Sketch *sketch) -{ - if (sketch->active_stroke == NULL) { - sk_startStroke(sketch); - sk_selectAllSketch(sketch, -1); - - sketch->active_stroke->selected = 1; - } -} - -static void sk_start_draw_gesture(SK_Sketch *sketch) -{ - sketch->gesture = sk_createStroke(); -} - -static int sk_draw_stroke(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, bool snap) -{ - if (sk_stroke_filtermval(dd)) { - sk_addStrokePoint(C, sketch, stk, dd, snap); - sk_updateDrawData(dd); - sk_updateNextPoint(sketch, stk); - - return 1; - } - - return 0; -} - -static int ValidSketchViewContext(ViewContext *vc) -{ - Object *obedit = vc->obedit; - Scene *scene = vc->scene; - - if (obedit && - obedit->type == OB_ARMATURE && - scene->toolsettings->bone_sketching & BONE_SKETCHING) - { - return 1; - } - else { - return 0; - } -} - -int BDR_drawSketchNames(ViewContext *vc) -{ - if (ValidSketchViewContext(vc)) { - SK_Sketch *sketch = viewcontextSketch(vc, 0); - if (sketch) { - sk_drawSketch(vc->scene, vc->v3d, sketch, 1); - return 1; - } - } - - return 0; -} - -void BDR_drawSketch(const bContext *C) -{ - if (ED_operator_sketch_mode(C)) { - SK_Sketch *sketch = contextSketch(C, 0); - if (sketch) { - sk_drawSketch(CTX_data_scene(C), CTX_wm_view3d(C), sketch, 0); - } - } -} - -static int sketch_delete(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) -{ - SK_Sketch *sketch = contextSketch(C, 0); - if (sketch) { - sk_deleteSelectedStrokes(sketch); -// allqueue(REDRAWVIEW3D, 0); - } - WM_event_add_notifier(C, NC_SCREEN | ND_SKETCH | NA_REMOVED, NULL); - return OPERATOR_FINISHED; -} - -bool BIF_sk_selectStroke(bContext *C, const int mval[2], const bool extend) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - SK_Sketch *sketch = contextSketch(C, 0); - - if (sketch != NULL && ts->bone_sketching & BONE_SKETCHING) { - if (sk_selectStroke(C, sketch, mval, extend)) { - ED_area_tag_redraw(CTX_wm_area(C)); - return true; - } - } - - return false; -} - -void BIF_convertSketch(bContext *C) -{ - if (ED_operator_sketch_full_mode(C)) { - SK_Sketch *sketch = contextSketch(C, 0); - if (sketch) { - sk_convert(C, sketch); -// BIF_undo_push("Convert Sketch"); -// allqueue(REDRAWVIEW3D, 0); -// allqueue(REDRAWBUTSEDIT, 0); - } - } -} - -void BIF_deleteSketch(bContext *C) -{ - if (ED_operator_sketch_full_mode(C)) { - SK_Sketch *sketch = contextSketch(C, 0); - if (sketch) { - sk_deleteSelectedStrokes(sketch); -// BIF_undo_push("Convert Sketch"); -// allqueue(REDRAWVIEW3D, 0); - } - } -} - -#if 0 -void BIF_selectAllSketch(bContext *C, int mode) -{ - if (BIF_validSketchMode(C)) - { - SK_Sketch *sketch = contextSketch(C, 0); - if (sketch) - { - sk_selectAllSketch(sketch, mode); -// XXX -// allqueue(REDRAWVIEW3D, 0); - } - } -} -#endif - -SK_Sketch *contextSketch(const bContext *C, int create) -{ - Object *obedit = CTX_data_edit_object(C); - SK_Sketch *sketch = NULL; - - if (obedit && obedit->type == OB_ARMATURE) { - bArmature *arm = obedit->data; - - if (arm->sketch == NULL && create) { - arm->sketch = createSketch(); - } - sketch = arm->sketch; - } - - return sketch; -} - -SK_Sketch *viewcontextSketch(ViewContext *vc, int create) -{ - Object *obedit = vc->obedit; - SK_Sketch *sketch = NULL; - - if (obedit && obedit->type == OB_ARMATURE) { - bArmature *arm = obedit->data; - - if (arm->sketch == NULL && create) { - arm->sketch = createSketch(); - } - sketch = arm->sketch; - } - - return sketch; -} - -static int sketch_convert(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) -{ - SK_Sketch *sketch = contextSketch(C, 0); - if (sketch != NULL) { - sk_convert(C, sketch); - ED_area_tag_redraw(CTX_wm_area(C)); - } - return OPERATOR_FINISHED; -} - -static int sketch_cancel_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) -{ - SK_Sketch *sketch = contextSketch(C, 0); - if (sketch != NULL) { - sk_cancelStroke(sketch); - ED_area_tag_redraw(CTX_wm_area(C)); - return OPERATOR_FINISHED; - } - return OPERATOR_PASS_THROUGH; -} - -static int sketch_finish(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) -{ - SK_Sketch *sketch = contextSketch(C, 0); - if (sketch != NULL) { - if (sk_finish_stroke(C, sketch)) { - ED_area_tag_redraw(CTX_wm_area(C)); - return OPERATOR_FINISHED; - } - } - return OPERATOR_PASS_THROUGH; -} - -static int sketch_select(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) -{ - SK_Sketch *sketch = contextSketch(C, 0); - if (sketch) { - short extend = 0; - if (sk_selectStroke(C, sketch, event->mval, extend)) - ED_area_tag_redraw(CTX_wm_area(C)); - } - - return OPERATOR_FINISHED; -} - -static void sketch_draw_stroke_cancel(bContext *C, wmOperator *op) -{ - SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */ - sk_cancelStroke(sketch); - MEM_freeN(op->customdata); -} - -static int sketch_draw_stroke(bContext *C, wmOperator *op, const wmEvent *event) -{ - const bool snap = RNA_boolean_get(op->ptr, "snap"); - SK_DrawData *dd; - SK_Sketch *sketch = contextSketch(C, 1); - - op->customdata = dd = MEM_callocN(sizeof(SK_DrawData), "SketchDrawData"); - sk_initDrawData(dd, event->mval); - - sk_start_draw_stroke(sketch); - - sk_draw_stroke(C, sketch, sketch->active_stroke, dd, snap); - - WM_event_add_modal_handler(C, op); - - return OPERATOR_RUNNING_MODAL; -} - -static void sketch_draw_gesture_cancel(bContext *C, wmOperator *op) -{ - SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */ - sk_cancelStroke(sketch); - MEM_freeN(op->customdata); -} - -static int sketch_draw_gesture(bContext *C, wmOperator *op, const wmEvent *event) -{ - const bool snap = RNA_boolean_get(op->ptr, "snap"); - SK_DrawData *dd; - SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */ - sk_cancelStroke(sketch); - - op->customdata = dd = MEM_callocN(sizeof(SK_DrawData), "SketchDrawData"); - sk_initDrawData(dd, event->mval); - - sk_start_draw_gesture(sketch); - sk_draw_stroke(C, sketch, sketch->gesture, dd, snap); - - WM_event_add_modal_handler(C, op); - - return OPERATOR_RUNNING_MODAL; -} - -static int sketch_draw_modal(bContext *C, wmOperator *op, const wmEvent *event, short gesture, SK_Stroke *stk) -{ - bool snap = RNA_boolean_get(op->ptr, "snap"); - SK_DrawData *dd = op->customdata; - SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */ - int retval = OPERATOR_RUNNING_MODAL; - - switch (event->type) { - case LEFTCTRLKEY: - case RIGHTCTRLKEY: - snap = event->ctrl != 0; - RNA_boolean_set(op->ptr, "snap", snap); - break; - case MOUSEMOVE: - case INBETWEEN_MOUSEMOVE: - dd->mval[0] = event->mval[0]; - dd->mval[1] = event->mval[1]; - sk_draw_stroke(C, sketch, stk, dd, snap); - ED_area_tag_redraw(CTX_wm_area(C)); - break; - case ESCKEY: - op->type->cancel(C, op); - ED_area_tag_redraw(CTX_wm_area(C)); - retval = OPERATOR_CANCELLED; - break; - case LEFTMOUSE: - if (event->val == KM_RELEASE) { - if (gesture == 0) { - sk_endContinuousStroke(stk); - sk_filterLastContinuousStroke(stk); - sk_updateNextPoint(sketch, stk); - ED_area_tag_redraw(CTX_wm_area(C)); - MEM_freeN(op->customdata); - retval = OPERATOR_FINISHED; - } - else { - sk_endContinuousStroke(stk); - sk_filterLastContinuousStroke(stk); - - if (stk->nb_points > 1) { - /* apply gesture here */ - sk_applyGesture(C, sketch); - } - - sk_freeStroke(stk); - sketch->gesture = NULL; - - ED_area_tag_redraw(CTX_wm_area(C)); - MEM_freeN(op->customdata); - retval = OPERATOR_FINISHED; - } - } - break; - } - - return retval; -} - -static int sketch_draw_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) -{ - SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */ - return sketch_draw_modal(C, op, event, 0, sketch->active_stroke); -} - -static int sketch_draw_gesture_modal(bContext *C, wmOperator *op, const wmEvent *event) -{ - SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */ - return sketch_draw_modal(C, op, event, 1, sketch->gesture); -} - -static int sketch_draw_preview(bContext *C, wmOperator *op, const wmEvent *event) -{ - const bool snap = RNA_boolean_get(op->ptr, "snap"); - SK_Sketch *sketch = contextSketch(C, 0); - - if (sketch) { - SK_DrawData dd; - - sk_initDrawData(&dd, event->mval); - sk_getStrokePoint(C, &sketch->next_point, sketch, sketch->active_stroke, &dd, snap); - ED_area_tag_redraw(CTX_wm_area(C)); - } - - return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH; -} - -/* ============================================== Poll Functions ============================================= */ - -int ED_operator_sketch_mode_active_stroke(bContext *C) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - SK_Sketch *sketch = contextSketch(C, 0); - - if (ts->bone_sketching & BONE_SKETCHING && - sketch != NULL && - sketch->active_stroke != NULL) - { - return 1; - } - else { - return 0; - } -} - -static int ED_operator_sketch_mode_gesture(bContext *C) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - SK_Sketch *sketch = contextSketch(C, 0); - - if (ts->bone_sketching & BONE_SKETCHING && - (ts->bone_sketching & BONE_SKETCHING_QUICK) == 0 && - sketch != NULL && - sketch->active_stroke == NULL) - { - return 1; - } - else { - return 0; - } -} - -int ED_operator_sketch_full_mode(bContext *C) -{ - Object *obedit = CTX_data_edit_object(C); - ToolSettings *ts = CTX_data_tool_settings(C); - - if (obedit && - obedit->type == OB_ARMATURE && - ts->bone_sketching & BONE_SKETCHING && - (ts->bone_sketching & BONE_SKETCHING_QUICK) == 0) - { - return 1; - } - else { - return 0; - } -} - -int ED_operator_sketch_mode(const bContext *C) -{ - Object *obedit = CTX_data_edit_object(C); - ToolSettings *ts = CTX_data_tool_settings(C); - - if (obedit && - obedit->type == OB_ARMATURE && - ts->bone_sketching & BONE_SKETCHING) - { - return 1; - } - else { - return 0; - } -} - -/* ================================================ Operators ================================================ */ - -void SKETCH_OT_delete(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Delete"; - ot->idname = "SKETCH_OT_delete"; - ot->description = "Delete a sketch stroke"; - - /* api callbacks */ - ot->invoke = sketch_delete; - - ot->poll = ED_operator_sketch_full_mode; - - /* flags */ -// ot->flag = OPTYPE_UNDO; -} - -void SKETCH_OT_select(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select"; - ot->idname = "SKETCH_OT_select"; - ot->description = "Select a sketch stroke"; - - /* api callbacks */ - ot->invoke = sketch_select; - - ot->poll = ED_operator_sketch_full_mode; - - /* flags */ -// ot->flag = OPTYPE_UNDO; -} - -void SKETCH_OT_cancel_stroke(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Cancel Stroke"; - ot->idname = "SKETCH_OT_cancel_stroke"; - ot->description = "Cancel the current sketch stroke"; - - /* api callbacks */ - ot->invoke = sketch_cancel_invoke; - - ot->poll = ED_operator_sketch_mode_active_stroke; - - /* flags */ -// ot->flag = OPTYPE_UNDO; -} - -void SKETCH_OT_convert(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Convert"; - ot->idname = "SKETCH_OT_convert"; - ot->description = "Convert the selected sketch strokes to bone chains"; - - /* api callbacks */ - ot->invoke = sketch_convert; - - ot->poll = ED_operator_sketch_full_mode; - - /* flags */ - ot->flag = OPTYPE_UNDO; -} - -void SKETCH_OT_finish_stroke(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "End Stroke"; - ot->idname = "SKETCH_OT_finish_stroke"; - ot->description = "End and keep the current sketch stroke"; - - /* api callbacks */ - ot->invoke = sketch_finish; - - ot->poll = ED_operator_sketch_mode_active_stroke; - - /* flags */ -// ot->flag = OPTYPE_UNDO; -} - -void SKETCH_OT_draw_preview(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Draw Preview"; - ot->idname = "SKETCH_OT_draw_preview"; - ot->description = "Draw preview of current sketch stroke (internal use)"; - - /* api callbacks */ - ot->invoke = sketch_draw_preview; - - ot->poll = ED_operator_sketch_mode_active_stroke; - - RNA_def_boolean(ot->srna, "snap", 0, "Snap", ""); - - /* flags */ -// ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; -} - -void SKETCH_OT_draw_stroke(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Draw Stroke"; - ot->idname = "SKETCH_OT_draw_stroke"; - ot->description = "Start to draw a sketch stroke"; - - /* api callbacks */ - ot->invoke = sketch_draw_stroke; - ot->modal = sketch_draw_stroke_modal; - ot->cancel = sketch_draw_stroke_cancel; - - ot->poll = (int (*)(bContext *))ED_operator_sketch_mode; - - RNA_def_boolean(ot->srna, "snap", 0, "Snap", ""); - - /* flags */ - ot->flag = OPTYPE_BLOCKING; // OPTYPE_REGISTER|OPTYPE_UNDO -} - -void SKETCH_OT_gesture(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Gesture"; - ot->idname = "SKETCH_OT_gesture"; - ot->description = "Start to draw a gesture stroke"; - - /* api callbacks */ - ot->invoke = sketch_draw_gesture; - ot->modal = sketch_draw_gesture_modal; - ot->cancel = sketch_draw_gesture_cancel; - - ot->poll = ED_operator_sketch_mode_gesture; - - RNA_def_boolean(ot->srna, "snap", 0, "Snap", ""); - - /* flags */ - ot->flag = OPTYPE_BLOCKING; // OPTYPE_UNDO -} - diff --git a/source/blender/editors/armature/reeb.c b/source/blender/editors/armature/reeb.c deleted file mode 100644 index fda7012e955..00000000000 --- a/source/blender/editors/armature/reeb.c +++ /dev/null @@ -1,3201 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributor(s): Martin Poirier - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/editors/armature/reeb.c - * \ingroup edarmature - */ - -#include "MEM_guardedalloc.h" - -#include "BLI_blenlib.h" -#include "BLI_math.h" -#include "BLI_edgehash.h" -#include "BLI_ghash.h" - -#include "BKE_context.h" - -#include "reeb.h" - -#if 0 /* UNUSED 2.5 */ -static ReebGraph *GLOBAL_RG = NULL; -static ReebGraph *FILTERED_RG = NULL; -#endif - -/* - * Skeleton generation algorithm based on: - * "Harmonic Skeleton for Realistic Character Animation" - * Gregoire Aujay, Franck Hetroy, Francis Lazarus and Christine Depraz - * SIGGRAPH 2007 - * - * Reeb graph generation algorithm based on: - * "Robust On-line Computation of Reeb Graphs: Simplicity and Speed" - * Valerio Pascucci, Giorgio Scorzelli, Peer-Timo Bremer and Ajith Mascarenhas - * SIGGRAPH 2007 - * - * */ - -#if 0 -#define DEBUG_REEB -#define DEBUG_REEB_NODE -#endif - -/* place-holders! */ -typedef struct EditEdge { - void *fake; -} EditEdge; - -typedef struct EditFace { - void *fake; -} EditFace; -/* end place-holders! */ - -typedef struct VertexData { - float w; /* weight */ - int i; /* index */ - ReebNode *n; -} VertexData; - -typedef struct EdgeIndex { - EditEdge **edges; - int *offset; -} EdgeIndex; - -typedef enum { - MERGE_LOWER, - MERGE_HIGHER, - MERGE_APPEND -} MergeDirection; - -int mergeArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1); -void mergeArcEdges(ReebGraph *rg, ReebArc *aDst, ReebArc *aSrc, MergeDirection direction); -int mergeConnectedArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1); -EditEdge *NextEdgeForVert(EdgeIndex *indexed_edges, int index); -void mergeArcFaces(ReebGraph *rg, ReebArc *aDst, ReebArc *aSrc); -void addFacetoArc(ReebArc *arc, EditFace *efa); - -void REEB_RadialSymmetry(BNode *root_node, RadialArc *ring, int count); -void REEB_AxialSymmetry(BNode *root_node, BNode *node1, BNode *node2, struct BArc *barc1, BArc *barc2); - -void flipArcBuckets(ReebArc *arc); - - -/***************************************** UTILS **********************************************/ - -#if 0 /* UNUSED */ -static VertexData *allocVertexData(EditMesh *em) -{ - VertexData *data; - EditVert *eve; - int totvert, index; - - totvert = BLI_listbase_count(&em->verts); - - data = MEM_callocN(sizeof(VertexData) * totvert, "VertexData"); - - for (index = 0, eve = em->verts.first; eve; index++, eve = eve->next) - { - data[index].i = index; - data[index].w = 0; - eve->tmp.p = data + index; - } - - return data; -} - -static int indexData(EditVert *eve) -{ - return ((VertexData *)eve->tmp.p)->i; -} - -static float weightData(EditVert *eve) -{ - return ((VertexData *)eve->tmp.p)->w; -} - -static void weightSetData(EditVert *eve, float w) -{ - ((VertexData *)eve->tmp.p)->w = w; -} - -static ReebNode *nodeData(EditVert *eve) -{ - return ((VertexData *)eve->tmp.p)->n; -} - -static void nodeSetData(EditVert *eve, ReebNode *n) -{ - ((VertexData *)eve->tmp.p)->n = n; -} - -#endif - -void REEB_freeArc(BArc *barc) -{ - ReebArc *arc = (ReebArc *)barc; - BLI_freelistN(&arc->edges); - - if (arc->buckets) - MEM_freeN(arc->buckets); - - if (arc->faces) - BLI_ghash_free(arc->faces, NULL, NULL); - - MEM_freeN(arc); -} - -void REEB_freeGraph(ReebGraph *rg) -{ - ReebArc *arc; - ReebNode *node; - - // free nodes - for (node = rg->nodes.first; node; node = node->next) { - BLI_freeNode((BGraph *)rg, (BNode *)node); - } - BLI_freelistN(&rg->nodes); - - // free arcs - arc = rg->arcs.first; - while (arc) { - ReebArc *next = arc->next; - REEB_freeArc((BArc *)arc); - arc = next; - } - - // free edge map - BLI_edgehash_free(rg->emap, NULL); - - /* free linked graph */ - if (rg->link_up) { - REEB_freeGraph(rg->link_up); - } - - MEM_freeN(rg); -} - -ReebGraph *newReebGraph(void) -{ - ReebGraph *rg; - rg = MEM_callocN(sizeof(ReebGraph), "reeb graph"); - - rg->totnodes = 0; - rg->emap = BLI_edgehash_new(__func__); - - - rg->free_arc = REEB_freeArc; - rg->free_node = NULL; - rg->radial_symmetry = REEB_RadialSymmetry; - rg->axial_symmetry = REEB_AxialSymmetry; - - return rg; -} - -void BIF_flagMultiArcs(ReebGraph *rg, int flag) -{ - for (; rg; rg = rg->link_up) { - BLI_flagArcs((BGraph *)rg, flag); - } -} - -#if 0 /* UNUSED */ -static ReebNode *addNode(ReebGraph *rg, EditVert *eve) -{ - float weight; - ReebNode *node = NULL; - - weight = weightData(eve); - - node = MEM_callocN(sizeof(ReebNode), "reeb node"); - - node->flag = 0; // clear flag on init - node->symmetry_level = 0; - node->arcs = NULL; - node->degree = 0; - node->weight = weight; - node->index = rg->totnodes; - copy_v3_v3(node->p, eve->co); - - BLI_addtail(&rg->nodes, node); - rg->totnodes++; - - nodeSetData(eve, node); - - return node; -} - -static ReebNode *copyNode(ReebGraph *rg, ReebNode *node) -{ - ReebNode *cp_node = NULL; - - cp_node = MEM_callocN(sizeof(ReebNode), "reeb node copy"); - - memcpy(cp_node, node, sizeof(ReebNode)); - - cp_node->prev = NULL; - cp_node->next = NULL; - cp_node->arcs = NULL; - - cp_node->link_up = NULL; - cp_node->link_down = NULL; - - BLI_addtail(&rg->nodes, cp_node); - rg->totnodes++; - - return cp_node; -} - -static void relinkNodes(ReebGraph *low_rg, ReebGraph *high_rg) -{ - ReebNode *low_node, *high_node; - - if (low_rg == NULL || high_rg == NULL) - { - return; - } - - for (low_node = low_rg->nodes.first; low_node; low_node = low_node->next) - { - for (high_node = high_rg->nodes.first; high_node; high_node = high_node->next) - { - if (low_node->index == high_node->index) - { - high_node->link_down = low_node; - low_node->link_up = high_node; - break; - } - } - } -} -#endif - -ReebNode *BIF_otherNodeFromIndex(ReebArc *arc, ReebNode *node) -{ - return (arc->head->index == node->index) ? arc->tail : arc->head; -} - -ReebNode *BIF_NodeFromIndex(ReebArc *arc, ReebNode *node) -{ - return (arc->head->index == node->index) ? arc->head : arc->tail; -} - -ReebNode *BIF_lowestLevelNode(ReebNode *node) -{ - while (node->link_down) { - node = node->link_down; - } - - return node; -} - -#if 0 /* UNUSED */ -static ReebArc *copyArc(ReebGraph *rg, ReebArc *arc) -{ - ReebArc *cp_arc; - ReebNode *node; - - cp_arc = MEM_callocN(sizeof(ReebArc), "reeb arc copy"); - - memcpy(cp_arc, arc, sizeof(ReebArc)); - - cp_arc->link_up = arc; - - cp_arc->head = NULL; - cp_arc->tail = NULL; - - cp_arc->prev = NULL; - cp_arc->next = NULL; - - cp_arc->edges.first = NULL; - cp_arc->edges.last = NULL; - - /* copy buckets */ - cp_arc->buckets = MEM_callocN(sizeof(EmbedBucket) * cp_arc->bcount, "embed bucket"); - memcpy(cp_arc->buckets, arc->buckets, sizeof(EmbedBucket) * cp_arc->bcount); - - /* copy faces map */ - cp_arc->faces = BLI_ghash_ptr_new("copyArc gh"); - mergeArcFaces(rg, cp_arc, arc); - - /* find corresponding head and tail */ - for (node = rg->nodes.first; node && (cp_arc->head == NULL || cp_arc->tail == NULL); node = node->next) - { - if (node->index == arc->head->index) - { - cp_arc->head = node; - } - else if (node->index == arc->tail->index) - { - cp_arc->tail = node; - } - } - - BLI_addtail(&rg->arcs, cp_arc); - - return cp_arc; -} - -static ReebGraph *copyReebGraph(ReebGraph *rg, int level) -{ - ReebNode *node; - ReebArc *arc; - ReebGraph *cp_rg = newReebGraph(); - - cp_rg->resolution = rg->resolution; - cp_rg->length = rg->length; - cp_rg->link_up = rg; - cp_rg->multi_level = level; - - /* Copy nodes */ - for (node = rg->nodes.first; node; node = node->next) - { - ReebNode *cp_node = copyNode(cp_rg, node); - cp_node->multi_level = level; - } - - /* Copy arcs */ - for (arc = rg->arcs.first; arc; arc = arc->next) - { - copyArc(cp_rg, arc); - } - - BLI_buildAdjacencyList((BGraph *)cp_rg); - - return cp_rg; -} -#endif - -ReebGraph *BIF_graphForMultiNode(ReebGraph *rg, ReebNode *node) -{ - ReebGraph *multi_rg = rg; - - while (multi_rg && multi_rg->multi_level != node->multi_level) { - multi_rg = multi_rg->link_up; - } - - return multi_rg; -} - -#if 0 /* UNUSED */ -static ReebEdge *copyEdge(ReebEdge *edge) -{ - ReebEdge *newEdge = NULL; - - newEdge = MEM_callocN(sizeof(ReebEdge), "reeb edge"); - memcpy(newEdge, edge, sizeof(ReebEdge)); - - newEdge->next = NULL; - newEdge->prev = NULL; - - return newEdge; -} - -static void printArc(ReebArc *arc) -{ - ReebEdge *edge; - ReebNode *head = (ReebNode *)arc->head; - ReebNode *tail = (ReebNode *)arc->tail; - printf("arc: (%i) %f -> (%i) %f\n", head->index, head->weight, tail->index, tail->weight); - - for (edge = arc->edges.first; edge; edge = edge->next) - { - printf("\tedge (%i, %i)\n", edge->v1->index, edge->v2->index); - } -} - -static void flipArc(ReebArc *arc) -{ - ReebNode *tmp; - tmp = arc->head; - arc->head = arc->tail; - arc->tail = tmp; - - flipArcBuckets(arc); -} - -#ifdef DEBUG_REEB_NODE -static void NodeDegreeDecrement(ReebGraph *UNUSED(rg), ReebNode *node) -{ - node->degree--; - -// if (node->degree == 0) -// { -// printf("would remove node %i\n", node->index); -// } -} - -static void NodeDegreeIncrement(ReebGraph *UNUSED(rg), ReebNode *node) -{ -// if (node->degree == 0) -// { -// printf("first connect node %i\n", node->index); -// } - - node->degree++; -} - -#else -# define NodeDegreeDecrement(rg, node) {node->degree--; } (void)0 -# define NodeDegreeIncrement(rg, node) {node->degree++; } (void)0 -#endif - -void repositionNodes(ReebGraph *rg) -{ - BArc *arc = NULL; - BNode *node = NULL; - - // Reset node positions - for (node = rg->nodes.first; node; node = node->next) { - node->p[0] = node->p[1] = node->p[2] = 0; - } - - for (arc = rg->arcs.first; arc; arc = arc->next) { - if (((ReebArc *)arc)->bcount > 0) { - float p[3]; - - copy_v3_v3(p, ((ReebArc *)arc)->buckets[0].p); - mul_v3_fl(p, 1.0f / arc->head->degree); - add_v3_v3(arc->head->p, p); - - copy_v3_v3(p, ((ReebArc *)arc)->buckets[((ReebArc *)arc)->bcount - 1].p); - mul_v3_fl(p, 1.0f / arc->tail->degree); - add_v3_v3(arc->tail->p, p); - } - } -} - -void verifyNodeDegree(ReebGraph *rg) -{ -#ifdef DEBUG_REEB - ReebNode *node = NULL; - ReebArc *arc = NULL; - - for (node = rg->nodes.first; node; node = node->next) { - int count = 0; - for (arc = rg->arcs.first; arc; arc = arc->next) { - if (arc->head == node || arc->tail == node) { - count++; - } - } - if (count != node->degree) { - printf("degree error in node %i: expected %i got %i\n", node->index, count, node->degree); - } - if (node->degree == 0) { - printf("zero degree node %i with weight %f\n", node->index, node->weight); - } - } -#endif -} - -static void verifyBucketsArc(ReebGraph *UNUSED(rg), ReebArc *arc) -{ - ReebNode *head = (ReebNode *)arc->head; - ReebNode *tail = (ReebNode *)arc->tail; - - if (arc->bcount > 0) { - int i; - for (i = 0; i < arc->bcount; i++) { - if (arc->buckets[i].nv == 0) { - printArc(arc); - printf("count error in bucket %i/%i\n", i + 1, arc->bcount); - } - } - - if (ceilf(head->weight) != arc->buckets[0].val) { - printArc(arc); - printf("alloc error in first bucket: %f should be %f\n", arc->buckets[0].val, ceil(head->weight)); - } - if (floorf(tail->weight) != arc->buckets[arc->bcount - 1].val) { - printArc(arc); - printf("alloc error in last bucket: %f should be %f\n", arc->buckets[arc->bcount - 1].val, floor(tail->weight)); - } - } -} - -void verifyBuckets(ReebGraph *rg) -{ -#ifdef DEBUG_REEB - ReebArc *arc = NULL; - for (arc = rg->arcs.first; arc; arc = arc->next) { - verifyBucketsArc(rg, arc); - } -#endif -} - -void verifyFaces(ReebGraph *rg) -{ -#ifdef DEBUG_REEB - int total = 0; - ReebArc *arc = NULL; - for (arc = rg->arcs.first; arc; arc = arc->next) { - total += BLI_ghash_len(arc->faces); - } - -#endif -} - -void verifyArcs(ReebGraph *rg) -{ - ReebArc *arc; - - for (arc = rg->arcs.first; arc; arc = arc->next) { - if (arc->head->weight > arc->tail->weight) { - printf("FLIPPED ARC!\n"); - } - } -} - -static void verifyMultiResolutionLinks(ReebGraph *rg, int level) -{ -#ifdef DEBUG_REEB - ReebGraph *lower_rg = rg->link_up; - - if (lower_rg) { - ReebArc *arc; - - for (arc = rg->arcs.first; arc; arc = arc->next) { - if (BLI_findindex(&lower_rg->arcs, arc->link_up) == -1) { - printf("missing arc %p for level %i\n", (void *)arc->link_up, level); - printf("Source arc was ---\n"); - printArc(arc); - - arc->link_up = NULL; - } - } - - - verifyMultiResolutionLinks(lower_rg, level + 1); - } -#endif -} -/***************************************** BUCKET UTILS **********************************************/ - -static void addVertToBucket(EmbedBucket *b, float co[3]) -{ - b->nv++; - interp_v3_v3v3(b->p, b->p, co, 1.0f / b->nv); -} - -#if 0 /* UNUSED 2.5 */ -static void removeVertFromBucket(EmbedBucket *b, float co[3]) -{ - mul_v3_fl(b->p, (float)b->nv); - sub_v3_v3(b->p, co); - b->nv--; - mul_v3_fl(b->p, 1.0f / (float)b->nv); -} -#endif - -static void mergeBuckets(EmbedBucket *bDst, EmbedBucket *bSrc) -{ - if (bDst->nv > 0 && bSrc->nv > 0) { - bDst->nv += bSrc->nv; - interp_v3_v3v3(bDst->p, bDst->p, bSrc->p, (float)bSrc->nv / (float)(bDst->nv)); - } - else if (bSrc->nv > 0) { - bDst->nv = bSrc->nv; - copy_v3_v3(bDst->p, bSrc->p); - } -} - -static void mergeArcBuckets(ReebArc *aDst, ReebArc *aSrc, float start, float end) -{ - if (aDst->bcount > 0 && aSrc->bcount > 0) { - int indexDst = 0, indexSrc = 0; - - start = max_fff(start, aDst->buckets[0].val, aSrc->buckets[0].val); - - while (indexDst < aDst->bcount && aDst->buckets[indexDst].val < start) { - indexDst++; - } - - while (indexSrc < aSrc->bcount && aSrc->buckets[indexSrc].val < start) { - indexSrc++; - } - - for (; indexDst < aDst->bcount && - indexSrc < aSrc->bcount && - aDst->buckets[indexDst].val <= end && - aSrc->buckets[indexSrc].val <= end - - ; indexDst++, indexSrc++) - { - mergeBuckets(aDst->buckets + indexDst, aSrc->buckets + indexSrc); - } - } -} - -void flipArcBuckets(ReebArc *arc) -{ - int i, j; - - for (i = 0, j = arc->bcount - 1; i < j; i++, j--) { - EmbedBucket tmp; - - tmp = arc->buckets[i]; - arc->buckets[i] = arc->buckets[j]; - arc->buckets[j] = tmp; - } -} - -static int countArcBuckets(ReebArc *arc) -{ - return (int)(floor(arc->tail->weight) - ceil(arc->head->weight)) + 1; -} - -static void allocArcBuckets(ReebArc *arc) -{ - int i; - float start = ceil(arc->head->weight); - arc->bcount = countArcBuckets(arc); - - if (arc->bcount > 0) { - arc->buckets = MEM_callocN(sizeof(EmbedBucket) * arc->bcount, "embed bucket"); - - for (i = 0; i < arc->bcount; i++) { - arc->buckets[i].val = start + i; - } - } - else { - arc->buckets = NULL; - } -} - -static void resizeArcBuckets(ReebArc *arc) -{ - EmbedBucket *oldBuckets = arc->buckets; - int oldBCount = arc->bcount; - - if (countArcBuckets(arc) == oldBCount) { - return; - } - - allocArcBuckets(arc); - - if (oldBCount != 0 && arc->bcount != 0) { - int oldStart = (int)oldBuckets[0].val; - int oldEnd = (int)oldBuckets[oldBCount - 1].val; - int newStart = (int)arc->buckets[0].val; - int newEnd = (int)arc->buckets[arc->bcount - 1].val; - int oldOffset = 0; - int newOffset = 0; - int len; - - if (oldStart < newStart) { - oldOffset = newStart - oldStart; - } - else { - newOffset = oldStart - newStart; - } - - len = MIN2(oldEnd - (oldStart + oldOffset) + 1, newEnd - (newStart - newOffset) + 1); - - memcpy(arc->buckets + newOffset, oldBuckets + oldOffset, len * sizeof(EmbedBucket)); - } - - if (oldBuckets != NULL) { - MEM_freeN(oldBuckets); - } -} - -static void reweightBuckets(ReebArc *arc) -{ - int i; - float start = ceil((arc->head)->weight); - - if (arc->bcount > 0) { - for (i = 0; i < arc->bcount; i++) { - arc->buckets[i].val = start + i; - } - } -} - -static void interpolateBuckets(ReebArc *arc, float *start_p, float *end_p, int start_index, int end_index) -{ - int total; - int j; - - total = end_index - start_index + 2; - - for (j = start_index; j <= end_index; j++) { - EmbedBucket *empty = arc->buckets + j; - empty->nv = 1; - interp_v3_v3v3(empty->p, start_p, end_p, (float)(j - start_index + 1) / total); - } -} - -static void fillArcEmptyBuckets(ReebArc *arc) -{ - float *start_p, *end_p; - int start_index = 0, end_index = 0; - int missing = 0; - int i; - - start_p = arc->head->p; - - for (i = 0; i < arc->bcount; i++) { - EmbedBucket *bucket = arc->buckets + i; - - if (missing) { - if (bucket->nv > 0) { - missing = 0; - - end_p = bucket->p; - end_index = i - 1; - - interpolateBuckets(arc, start_p, end_p, start_index, end_index); - } - } - else { - if (bucket->nv == 0) { - missing = 1; - - if (i > 0) { - start_p = arc->buckets[i - 1].p; - } - start_index = i; - } - } - } - - if (missing) { - end_p = arc->tail->p; - end_index = arc->bcount - 1; - - interpolateBuckets(arc, start_p, end_p, start_index, end_index); - } -} - -static void ExtendArcBuckets(ReebArc *arc) -{ - ReebArcIterator arc_iter; - BArcIterator *iter = (BArcIterator *)&arc_iter; - EmbedBucket *last_bucket, *first_bucket; - float *previous = NULL; - float average_length = 0, length; - int padding_head = 0, padding_tail = 0; - - if (arc->bcount == 0) { - return; /* failsafe, shouldn't happen */ - } - - initArcIterator(iter, arc, arc->head); - IT_next(iter); - previous = iter->p; - - for (IT_next(iter); - IT_stopped(iter) == 0; - previous = iter->p, IT_next(iter) - ) - { - average_length += len_v3v3(previous, iter->p); - } - average_length /= (arc->bcount - 1); - - first_bucket = arc->buckets; - last_bucket = arc->buckets + (arc->bcount - 1); - - length = len_v3v3(first_bucket->p, arc->head->p); - if (length > 2 * average_length) { - padding_head = (int)floor(length / average_length); - } - - length = len_v3v3(last_bucket->p, arc->tail->p); - if (length > 2 * average_length) { - padding_tail = (int)floor(length / average_length); - } - - if (padding_head + padding_tail > 0) { - EmbedBucket *old_buckets = arc->buckets; - - arc->buckets = MEM_callocN(sizeof(EmbedBucket) * (padding_head + arc->bcount + padding_tail), "embed bucket"); - memcpy(arc->buckets + padding_head, old_buckets, arc->bcount * sizeof(EmbedBucket)); - - arc->bcount = padding_head + arc->bcount + padding_tail; - - MEM_freeN(old_buckets); - } - - if (padding_head > 0) { - interpolateBuckets(arc, arc->head->p, first_bucket->p, 0, padding_head); - } - - if (padding_tail > 0) { - interpolateBuckets(arc, last_bucket->p, arc->tail->p, arc->bcount - padding_tail, arc->bcount - 1); - } -} - -/* CALL THIS ONLY AFTER FILTERING, SINCE IT MESSES UP WEIGHT DISTRIBUTION */ -static void extendGraphBuckets(ReebGraph *rg) -{ - ReebArc *arc; - - for (arc = rg->arcs.first; arc; arc = arc->next) { - ExtendArcBuckets(arc); - } -} - -/**************************************** LENGTH CALCULATIONS ****************************************/ - -static void calculateArcLength(ReebArc *arc) -{ - ReebArcIterator arc_iter; - BArcIterator *iter = (BArcIterator *)&arc_iter; - float *vec0, *vec1; - - arc->length = 0; - - initArcIterator(iter, arc, arc->head); - - vec0 = arc->head->p; - vec1 = arc->head->p; /* in case there's no embedding */ - - while (IT_next(iter)) { - vec1 = iter->p; - - arc->length += len_v3v3(vec0, vec1); - - vec0 = vec1; - } - - arc->length += len_v3v3(arc->tail->p, vec1); -} - -static void calculateGraphLength(ReebGraph *rg) -{ - ReebArc *arc; - - for (arc = rg->arcs.first; arc; arc = arc->next) { - calculateArcLength(arc); - } -} -#endif - -/**************************************** SYMMETRY HANDLING ******************************************/ - -void REEB_RadialSymmetry(BNode *root_node, RadialArc *ring, int count) -{ - ReebNode *node = (ReebNode *)root_node; - float axis[3]; - int i; - - copy_v3_v3(axis, root_node->symmetry_axis); - - /* first pass, merge incrementally */ - for (i = 0; i < count - 1; i++) { - ReebNode *node1, *node2; - ReebArc *arc1, *arc2; - float tangent[3]; - float normal[3]; - int j = i + 1; - - add_v3_v3v3(tangent, ring[i].n, ring[j].n); - cross_v3_v3v3(normal, tangent, axis); - - node1 = (ReebNode *)BLI_otherNode(ring[i].arc, root_node); - node2 = (ReebNode *)BLI_otherNode(ring[j].arc, root_node); - - arc1 = (ReebArc *)ring[i].arc; - arc2 = (ReebArc *)ring[j].arc; - - /* mirror first node and mix with the second */ - BLI_mirrorAlongAxis(node1->p, root_node->p, normal); - interp_v3_v3v3(node2->p, node2->p, node1->p, 1.0f / (j + 1)); - - /* Merge buckets - * there shouldn't be any null arcs here, but just to be safe - * */ - if (arc1->bcount > 0 && arc2->bcount > 0) { - ReebArcIterator arc_iter1, arc_iter2; - BArcIterator *iter1 = (BArcIterator *)&arc_iter1; - BArcIterator *iter2 = (BArcIterator *)&arc_iter2; - EmbedBucket *bucket1 = NULL, *bucket2 = NULL; - - initArcIterator(iter1, arc1, (ReebNode *)root_node); - initArcIterator(iter2, arc2, (ReebNode *)root_node); - - bucket1 = IT_next(iter1); - bucket2 = IT_next(iter2); - - /* Make sure they both start at the same value */ - while (bucket1 && bucket2 && bucket1->val < bucket2->val) { - bucket1 = IT_next(iter1); - } - - while (bucket1 && bucket2 && bucket2->val < bucket1->val) { - bucket2 = IT_next(iter2); - } - - - for (; bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2)) { - bucket2->nv += bucket1->nv; /* add counts */ - - /* mirror on axis */ - BLI_mirrorAlongAxis(bucket1->p, root_node->p, normal); - /* add bucket2 in bucket1 */ - interp_v3_v3v3(bucket2->p, bucket2->p, bucket1->p, (float)bucket1->nv / (float)(bucket2->nv)); - } - } - } - - /* second pass, mirror back on previous arcs */ - for (i = count - 1; i > 0; i--) { - ReebNode *node1, *node2; - ReebArc *arc1, *arc2; - float tangent[3]; - float normal[3]; - int j = i - 1; - - add_v3_v3v3(tangent, ring[i].n, ring[j].n); - cross_v3_v3v3(normal, tangent, axis); - - node1 = (ReebNode *)BLI_otherNode(ring[i].arc, root_node); - node2 = (ReebNode *)BLI_otherNode(ring[j].arc, root_node); - - arc1 = (ReebArc *)ring[i].arc; - arc2 = (ReebArc *)ring[j].arc; - - /* copy first node than mirror */ - copy_v3_v3(node2->p, node1->p); - BLI_mirrorAlongAxis(node2->p, root_node->p, normal); - - /* Copy buckets - * there shouldn't be any null arcs here, but just to be safe - * */ - if (arc1->bcount > 0 && arc2->bcount > 0) { - ReebArcIterator arc_iter1, arc_iter2; - BArcIterator *iter1 = (BArcIterator *)&arc_iter1; - BArcIterator *iter2 = (BArcIterator *)&arc_iter2; - EmbedBucket *bucket1 = NULL, *bucket2 = NULL; - - initArcIterator(iter1, arc1, node); - initArcIterator(iter2, arc2, node); - - bucket1 = IT_next(iter1); - bucket2 = IT_next(iter2); - - /* Make sure they both start at the same value */ - while (bucket1 && bucket1->val < bucket2->val) { - bucket1 = IT_next(iter1); - } - - while (bucket2 && bucket2->val < bucket1->val) { - bucket2 = IT_next(iter2); - } - - - for (; bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2)) { - /* copy and mirror back to bucket2 */ - bucket2->nv = bucket1->nv; - copy_v3_v3(bucket2->p, bucket1->p); - BLI_mirrorAlongAxis(bucket2->p, node->p, normal); - } - } - } -} - -void REEB_AxialSymmetry(BNode *root_node, BNode *node1, BNode *node2, struct BArc *barc1, BArc *barc2) -{ - ReebArc *arc1, *arc2; - float nor[3], p[3]; - - arc1 = (ReebArc *)barc1; - arc2 = (ReebArc *)barc2; - - copy_v3_v3(nor, root_node->symmetry_axis); - - /* mirror node2 along axis */ - copy_v3_v3(p, node2->p); - BLI_mirrorAlongAxis(p, root_node->p, nor); - - /* average with node1 */ - add_v3_v3(node1->p, p); - mul_v3_fl(node1->p, 0.5f); - - /* mirror back on node2 */ - copy_v3_v3(node2->p, node1->p); - BLI_mirrorAlongAxis(node2->p, root_node->p, nor); - - /* Merge buckets - * there shouldn't be any null arcs here, but just to be safe - * */ - if (arc1->bcount > 0 && arc2->bcount > 0) { - ReebArcIterator arc_iter1, arc_iter2; - BArcIterator *iter1 = (BArcIterator *)&arc_iter1; - BArcIterator *iter2 = (BArcIterator *)&arc_iter2; - EmbedBucket *bucket1 = NULL, *bucket2 = NULL; - - initArcIterator(iter1, arc1, (ReebNode *)root_node); - initArcIterator(iter2, arc2, (ReebNode *)root_node); - - bucket1 = IT_next(iter1); - bucket2 = IT_next(iter2); - - /* Make sure they both start at the same value */ - while (bucket1 && bucket1->val < bucket2->val) { - bucket1 = IT_next(iter1); - } - - while (bucket2 && bucket2->val < bucket1->val) { - bucket2 = IT_next(iter2); - } - - - for (; bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2)) { - bucket1->nv += bucket2->nv; /* add counts */ - - /* mirror on axis */ - BLI_mirrorAlongAxis(bucket2->p, root_node->p, nor); - /* add bucket2 in bucket1 */ - interp_v3_v3v3(bucket1->p, bucket1->p, bucket2->p, (float)bucket2->nv / (float)(bucket1->nv)); - - /* copy and mirror back to bucket2 */ - bucket2->nv = bucket1->nv; - copy_v3_v3(bucket2->p, bucket1->p); - BLI_mirrorAlongAxis(bucket2->p, root_node->p, nor); - } - } -} - -/************************************** ADJACENCY LIST *************************************************/ - - -/****************************************** SMOOTHING **************************************************/ - -#if 0 /* UNUSED */ -void postprocessGraph(ReebGraph *rg, char mode) -{ - ReebArc *arc; - float fac1 = 0, fac2 = 1, fac3 = 0; - - switch (mode) - { - case SKGEN_AVERAGE: - fac1 = fac2 = fac3 = 1.0f / 3.0f; - break; - case SKGEN_SMOOTH: - fac1 = fac3 = 0.25f; - fac2 = 0.5f; - break; - case SKGEN_SHARPEN: - fac1 = fac3 = -0.25f; - fac2 = 1.5f; - break; - default: -// XXX -// error("Unknown post processing mode"); - return; - } - - for (arc = rg->arcs.first; arc; arc = arc->next) - { - EmbedBucket *buckets = arc->buckets; - int bcount = arc->bcount; - int index; - - for (index = 1; index < bcount - 1; index++) - { - interp_v3_v3v3(buckets[index].p, buckets[index].p, buckets[index - 1].p, fac1 / (fac1 + fac2)); - interp_v3_v3v3(buckets[index].p, buckets[index].p, buckets[index + 1].p, fac3 / (fac1 + fac2 + fac3)); - } - } -} - -/********************************************SORTING****************************************************/ - -static int compareNodesWeight(void *vnode1, void *vnode2) -{ - ReebNode *node1 = (ReebNode *)vnode1; - ReebNode *node2 = (ReebNode *)vnode2; - - if (node1->weight < node2->weight) - { - return -1; - } - if (node1->weight > node2->weight) - { - return 1; - } - else { - return 0; - } -} - -void sortNodes(ReebGraph *rg) -{ - BLI_listbase_sort(&rg->nodes, compareNodesWeight); -} - -static int compareArcsWeight(void *varc1, void *varc2) -{ - ReebArc *arc1 = (ReebArc *)varc1; - ReebArc *arc2 = (ReebArc *)varc2; - ReebNode *node1 = (ReebNode *)arc1->head; - ReebNode *node2 = (ReebNode *)arc2->head; - - if (node1->weight < node2->weight) - { - return -1; - } - if (node1->weight > node2->weight) - { - return 1; - } - else { - return 0; - } -} - -void sortArcs(ReebGraph *rg) -{ - BLI_listbase_sort(&rg->arcs, compareArcsWeight); -} -/******************************************* JOINING ***************************************************/ - -static void reweightArc(ReebGraph *rg, ReebArc *arc, ReebNode *start_node, float start_weight) -{ - ReebNode *node; - float old_weight; - float end_weight = start_weight + ABS(arc->tail->weight - arc->head->weight); - int i; - - node = (ReebNode *)BLI_otherNode((BArc *)arc, (BNode *)start_node); - - /* prevent backtracking */ - if (node->flag == 1) - { - return; - } - - if (arc->tail == start_node) - { - flipArc(arc); - } - - start_node->flag = 1; - - for (i = 0; i < node->degree; i++) - { - ReebArc *next_arc = node->arcs[i]; - - reweightArc(rg, next_arc, node, end_weight); - } - - /* update only if needed */ - if (arc->head->weight != start_weight || arc->tail->weight != end_weight) - { - old_weight = arc->head->weight; /* backup head weight, other arcs need it intact, it will be fixed by the source arc */ - - arc->head->weight = start_weight; - arc->tail->weight = end_weight; - - reweightBuckets(arc); - resizeArcBuckets(arc); - fillArcEmptyBuckets(arc); - - arc->head->weight = old_weight; - } -} - -static void reweightSubgraph(ReebGraph *rg, ReebNode *start_node, float start_weight) -{ - int i; - - BLI_flagNodes((BGraph *)rg, 0); - - for (i = 0; i < start_node->degree; i++) - { - ReebArc *next_arc = start_node->arcs[i]; - - reweightArc(rg, next_arc, start_node, start_weight); - } - start_node->weight = start_weight; -} - -static int joinSubgraphsEnds(ReebGraph *rg, float threshold, int nb_subgraphs) -{ - int joined = 0; - int subgraph; - - for (subgraph = 1; subgraph <= nb_subgraphs; subgraph++) - { - ReebNode *start_node, *end_node; - ReebNode *min_node_start = NULL, *min_node_end = NULL; - float min_distance = FLT_MAX; - - for (start_node = rg->nodes.first; start_node; start_node = start_node->next) - { - if (start_node->subgraph_index == subgraph && start_node->degree == 1) - { - - for (end_node = rg->nodes.first; end_node; end_node = end_node->next) - { - if (end_node->subgraph_index != subgraph) - { - float distance = len_v3v3(start_node->p, end_node->p); - - if (distance < threshold && distance < min_distance) - { - min_distance = distance; - min_node_end = end_node; - min_node_start = start_node; - } - } - } - } - } - - end_node = min_node_end; - start_node = min_node_start; - - if (end_node && start_node) - { - ReebArc *start_arc /* , *end_arc */ /* UNUSED */; - int merging = 0; - - start_arc = start_node->arcs[0]; - /* end_arc = end_node->arcs[0]; */ /* UNUSED */ - - if (start_arc->tail == start_node) - { - reweightSubgraph(rg, end_node, start_node->weight); - - start_arc->tail = end_node; - - merging = 1; - } - else if (start_arc->head == start_node) - { - reweightSubgraph(rg, start_node, end_node->weight); - - start_arc->head = end_node; - - merging = 2; - } - - if (merging) - { - BLI_ReflagSubgraph((BGraph *)rg, end_node->flag, subgraph); - - resizeArcBuckets(start_arc); - fillArcEmptyBuckets(start_arc); - - NodeDegreeIncrement(rg, end_node); - BLI_rebuildAdjacencyListForNode((BGraph *)rg, (BNode *)end_node); - - BLI_removeNode((BGraph *)rg, (BNode *)start_node); - } - - joined = 1; - } - } - - return joined; -} - -/* Reweight graph from smallest node, fix fliped arcs */ -static void fixSubgraphsOrientation(ReebGraph *rg, int nb_subgraphs) -{ - int subgraph; - - for (subgraph = 1; subgraph <= nb_subgraphs; subgraph++) - { - ReebNode *node; - ReebNode *start_node = NULL; - - for (node = rg->nodes.first; node; node = node->next) - { - if (node->subgraph_index == subgraph) - { - if (start_node == NULL || node->weight < start_node->weight) - { - start_node = node; - } - } - } - - if (start_node) - { - reweightSubgraph(rg, start_node, start_node->weight); - } - } -} - -static int joinSubgraphs(ReebGraph *rg, float threshold) -{ - int nb_subgraphs; - int joined = 0; - - BLI_buildAdjacencyList((BGraph *)rg); - - if (BLI_isGraphCyclic((BGraph *)rg)) { - /* don't deal with cyclic graphs YET */ - return 0; - } - - /* sort nodes before flagging subgraphs to make sure root node is subgraph 0 */ - sortNodes(rg); - - nb_subgraphs = BLI_FlagSubgraphs((BGraph *)rg); - - /* Harmonic function can create flipped arcs, take the occasion to fix them */ -// XXX -// if (G.scene->toolsettings->skgen_options & SKGEN_HARMONIC) -// { - fixSubgraphsOrientation(rg, nb_subgraphs); -// } - - if (nb_subgraphs > 1) - { - joined |= joinSubgraphsEnds(rg, threshold, nb_subgraphs); - - if (joined) - { - removeNormalNodes(rg); - BLI_buildAdjacencyList((BGraph *)rg); - } - } - - return joined; -} - -/****************************************** FILTERING **************************************************/ - -static float lengthArc(ReebArc *arc) -{ -#if 0 - ReebNode *head = (ReebNode *)arc->head; - ReebNode *tail = (ReebNode *)arc->tail; - - return tail->weight - head->weight; -#else - return arc->length; -#endif -} - -static int compareArcs(void *varc1, void *varc2) -{ - ReebArc *arc1 = (ReebArc *)varc1; - ReebArc *arc2 = (ReebArc *)varc2; - float len1 = lengthArc(arc1); - float len2 = lengthArc(arc2); - - if (len1 < len2) { - return -1; - } - if (len1 > len2) { - return 1; - } - else { - return 0; - } -} - -static void filterArc(ReebGraph *rg, ReebNode *newNode, ReebNode *removedNode, ReebArc *srcArc, int merging) -{ - ReebArc *arc = NULL, *nextArc = NULL; - - if (merging) { - /* first pass, merge buckets for arcs that spawned the two nodes into the source arc*/ - for (arc = rg->arcs.first; arc; arc = arc->next) { - if (arc->head == srcArc->head && arc->tail == srcArc->tail && arc != srcArc) { - ReebNode *head = srcArc->head; - ReebNode *tail = srcArc->tail; - mergeArcBuckets(srcArc, arc, head->weight, tail->weight); - } - } - } - - /* second pass, replace removedNode by newNode, remove arcs that are collapsed in a loop */ - arc = rg->arcs.first; - while (arc) { - nextArc = arc->next; - - if (arc->head == removedNode || arc->tail == removedNode) { - if (arc->head == removedNode) { - arc->head = newNode; - } - else { - arc->tail = newNode; - } - - // Remove looped arcs - if (arc->head == arc->tail) { - // v1 or v2 was already newNode, since we're removing an arc, decrement degree - NodeDegreeDecrement(rg, newNode); - - // If it's srcArc, it'll be removed later, so keep it for now - if (arc != srcArc) { - BLI_remlink(&rg->arcs, arc); - REEB_freeArc((BArc *)arc); - } - } - else { - /* flip arcs that flipped, can happen on diamond shapes, mostly on null arcs */ - if (arc->head->weight > arc->tail->weight) { - flipArc(arc); - } - //newNode->degree++; // incrementing degree since we're adding an arc - NodeDegreeIncrement(rg, newNode); - mergeArcFaces(rg, arc, srcArc); - - if (merging) { - ReebNode *head = arc->head; - ReebNode *tail = arc->tail; - - // resize bucket list - resizeArcBuckets(arc); - mergeArcBuckets(arc, srcArc, head->weight, tail->weight); - - /* update length */ - arc->length += srcArc->length; - } - } - } - - arc = nextArc; - } -} - -void filterNullReebGraph(ReebGraph *rg) -{ - ReebArc *arc = NULL, *nextArc = NULL; - - arc = rg->arcs.first; - while (arc) { - nextArc = arc->next; - // Only collapse arcs too short to have any embed bucket - if (arc->bcount == 0) { - ReebNode *newNode = (ReebNode *)arc->head; - ReebNode *removedNode = (ReebNode *)arc->tail; - float blend; - - blend = (float)newNode->degree / (float)(newNode->degree + removedNode->degree); // blending factors - - interp_v3_v3v3(newNode->p, removedNode->p, newNode->p, blend); - - filterArc(rg, newNode, removedNode, arc, 0); - - // Reset nextArc, it might have changed - nextArc = arc->next; - - BLI_remlink(&rg->arcs, arc); - REEB_freeArc((BArc *)arc); - - BLI_removeNode((BGraph *)rg, (BNode *)removedNode); - } - - arc = nextArc; - } -} - -static int filterInternalExternalReebGraph(ReebGraph *rg, float threshold_internal, float threshold_external) -{ - ReebArc *arc = NULL, *nextArc = NULL; - int value = 0; - - BLI_listbase_sort(&rg->arcs, compareArcs); - - for (arc = rg->arcs.first; arc; arc = nextArc) { - nextArc = arc->next; - - /* Only collapse non-terminal arcs that are shorter than threshold */ - if ((threshold_internal > 0) && - (arc->head->degree > 1) && - (arc->tail->degree > 1) && - (lengthArc(arc) < threshold_internal)) - { - ReebNode *newNode = NULL; - ReebNode *removedNode = NULL; - - /* Always remove lower node, so arcs don't flip */ - newNode = arc->head; - removedNode = arc->tail; - - filterArc(rg, newNode, removedNode, arc, 1); - - // Reset nextArc, it might have changed - nextArc = arc->next; - - BLI_remlink(&rg->arcs, arc); - REEB_freeArc((BArc *)arc); - - BLI_removeNode((BGraph *)rg, (BNode *)removedNode); - value = 1; - } - - // Only collapse terminal arcs that are shorter than threshold - else if ((threshold_external > 0) && - (arc->head->degree == 1 || arc->tail->degree == 1) && - (lengthArc(arc) < threshold_external)) - { - ReebNode *terminalNode = NULL; - ReebNode *middleNode = NULL; - ReebNode *removedNode = NULL; - - // Assign terminal and middle nodes - if (arc->head->degree == 1) { - terminalNode = arc->head; - middleNode = arc->tail; - } - else { - terminalNode = arc->tail; - middleNode = arc->head; - } - - if (middleNode->degree == 2 && middleNode != rg->nodes.first) { -#if 1 - // If middle node is a normal node, it will be removed later - // Only if middle node is not the root node - /* USE THIS IF YOU WANT TO PROLONG ARCS TO THEIR TERMINAL NODES - * FOR HANDS, THIS IS NOT THE BEST RESULT - * */ - continue; -#else - removedNode = terminalNode; - - // removing arc, so we need to decrease the degree of the remaining node - NodeDegreeDecrement(rg, middleNode); -#endif - } - // Otherwise, just plain remove of the arc - else { - removedNode = terminalNode; - - // removing arc, so we need to decrease the degree of the remaining node - NodeDegreeDecrement(rg, middleNode); - } - - // Reset nextArc, it might have changed - nextArc = arc->next; - - BLI_remlink(&rg->arcs, arc); - REEB_freeArc((BArc *)arc); - - BLI_removeNode((BGraph *)rg, (BNode *)removedNode); - value = 1; - } - } - - return value; -} - -static int filterCyclesReebGraph(ReebGraph *rg, float UNUSED(distance_threshold)) -{ - ReebArc *arc1, *arc2; - ReebArc *next2; - int filtered = 0; - - for (arc1 = rg->arcs.first; arc1; arc1 = arc1->next) { - for (arc2 = arc1->next; arc2; arc2 = next2) { - next2 = arc2->next; - if (arc1 != arc2 && arc1->head == arc2->head && arc1->tail == arc2->tail) { - mergeArcEdges(rg, arc1, arc2, MERGE_APPEND); - mergeArcFaces(rg, arc1, arc2); - mergeArcBuckets(arc1, arc2, arc1->head->weight, arc1->tail->weight); - - NodeDegreeDecrement(rg, arc1->head); - NodeDegreeDecrement(rg, arc1->tail); - - BLI_remlink(&rg->arcs, arc2); - REEB_freeArc((BArc *)arc2); - - filtered = 1; - } - } - } - - return filtered; -} - -int filterSmartReebGraph(ReebGraph *UNUSED(rg), float UNUSED(threshold)) -{ - int value = 0; -#if 0 //XXX - ReebArc *arc = NULL, *nextArc = NULL; - - BLI_listbase_sort(&rg->arcs, compareArcs); - -#ifdef DEBUG_REEB - { - EditFace *efa; - for (efa = G.editMesh->faces.first; efa; efa = efa->next) { - efa->tmp.fp = -1; - } - } -#endif - - arc = rg->arcs.first; - while (arc) - { - nextArc = arc->next; - - /* need correct normals and center */ - recalc_editnormals(); - - // Only test terminal arcs - if (arc->head->degree == 1 || arc->tail->degree == 1) - { - GHashIterator ghi; - int merging = 0; - int total = BLI_ghash_len(arc->faces); - float avg_angle = 0; - float avg_vec[3] = {0, 0, 0}; - - for (BLI_ghashIterator_init(&ghi, arc->faces); - BLI_ghashIterator_done(&ghi) == false; - BLI_ghashIterator_step(&ghi)) - { - EditFace *efa = BLI_ghashIterator_getValue(&ghi); - -#if 0 - ReebArcIterator arc_iter; - BArcIterator *iter = (BArcIterator *)&arc_iter; - EmbedBucket *bucket = NULL; - EmbedBucket *previous = NULL; - float min_distance = -1; - float angle = 0; - - initArcIterator(iter, arc, arc->head); - - bucket = nextBucket(iter); - - while (bucket != NULL) - { - float *vec0 = NULL; - float *vec1 = bucket->p; - float midpoint[3], tangent[3]; - float distance; - - /* first bucket. Previous is head */ - if (previous == NULL) - { - vec0 = arc->head->p; - } - /* Previous is a valid bucket */ - else { - vec0 = previous->p; - } - - copy_v3_v3(midpoint, vec1); - - distance = len_v3v3(midpoint, efa->cent); - - if (min_distance == -1 || distance < min_distance) - { - min_distance = distance; - - sub_v3_v3v3(tangent, vec1, vec0); - normalize_v3(tangent); - - angle = dot_v3v3(tangent, efa->n); - } - - previous = bucket; - bucket = nextBucket(iter); - } - - avg_angle += saacos(fabs(angle)); -#ifdef DEBUG_REEB - efa->tmp.fp = saacos(fabs(angle)); -#endif -#else - add_v3_v3(avg_vec, efa->n); -#endif - } - - -#if 0 - avg_angle /= total; -#else - mul_v3_fl(avg_vec, 1.0 / total); - avg_angle = dot_v3v3(avg_vec, avg_vec); -#endif - - arc->angle = avg_angle; - - if (avg_angle > threshold) - merging = 1; - - if (merging) { - ReebNode *terminalNode = NULL; - ReebNode *middleNode = NULL; - ReebNode *newNode = NULL; - ReebNode *removedNode = NULL; - int merging = 0; - - /* Assign terminal and middle nodes */ - if (arc->head->degree == 1) { - terminalNode = arc->head; - middleNode = arc->tail; - } - else { - terminalNode = arc->tail; - middleNode = arc->head; - } - - /* If middle node is a normal node, merge to terminal node */ - if (middleNode->degree == 2) { - merging = 1; - newNode = terminalNode; - removedNode = middleNode; - } - /* Otherwise, just plain remove of the arc */ - else { - merging = 0; - newNode = middleNode; - removedNode = terminalNode; - } - - /* Merging arc */ - if (merging) { - filterArc(rg, newNode, removedNode, arc, 1); - } - else { - /* removing arc, so we need to decrease the degree of the remaining node - *newNode->degree--; */ - NodeDegreeDecrement(rg, newNode); - } - - /* Reset nextArc, it might have changed */ - nextArc = arc->next; - - BLI_remlink(&rg->arcs, arc); - REEB_freeArc((BArc *)arc); - - BLI_freelinkN(&rg->nodes, removedNode); - value = 1; - } - } - - arc = nextArc; - } - -#endif - - return value; -} - -static void filterGraph(ReebGraph *rg, short options, float threshold_internal, float threshold_external) -{ - bool done = true; - - calculateGraphLength(rg); - - if ((options & SKGEN_FILTER_EXTERNAL) == 0) { - threshold_external = 0; - } - - if ((options & SKGEN_FILTER_INTERNAL) == 0) { - threshold_internal = 0; - } - - if (threshold_internal > 0 || threshold_external > 0) { - /* filter until there's nothing more to do */ - while (done == true) { - done = false; /* no work done yet */ - - done = filterInternalExternalReebGraph(rg, threshold_internal, threshold_external); - } - } - - if (options & SKGEN_FILTER_SMART) { - filterSmartReebGraph(rg, 0.5); - filterCyclesReebGraph(rg, 0.5); - } - - repositionNodes(rg); - - /* Filtering might have created degree 2 nodes, so remove them */ - removeNormalNodes(rg); -} - -static void finalizeGraph(ReebGraph *rg, char passes, char method) -{ - int i; - - BLI_buildAdjacencyList((BGraph *)rg); - - sortNodes(rg); - - sortArcs(rg); - - for (i = 0; i < passes; i++) { - postprocessGraph(rg, method); - } - - extendGraphBuckets(rg); -} - -/************************************** WEIGHT SPREADING ***********************************************/ - -static int compareVerts(const void *a, const void *b) -{ - EditVert *va = *(EditVert **)a; - EditVert *vb = *(EditVert **)b; - int value = 0; - - if (weightData(va) < weightData(vb)) { - value = -1; - } - else if (weightData(va) > weightData(vb)) { - value = 1; - } - - return value; -} - -static void spreadWeight(EditMesh *em) -{ - EditVert **verts, *eve; - float lastWeight = 0.0f; - int totvert = BLI_listbase_count(&em->verts); - int i; - int work_needed = 1; - - verts = MEM_callocN(sizeof(EditVert *) * totvert, "verts array"); - - for (eve = em->verts.first, i = 0; eve; eve = eve->next, i++) { - verts[i] = eve; - } - - while (work_needed == 1) { - work_needed = 0; - qsort(verts, totvert, sizeof(EditVert *), compareVerts); - - for (i = 0; i < totvert; i++) { - eve = verts[i]; - - if (i == 0 || (weightData(eve) - lastWeight) > FLT_EPSILON) { - lastWeight = weightData(eve); - } - else { - work_needed = 1; - weightSetData(eve, lastWeight + FLT_EPSILON * 2); - lastWeight = weightData(eve); - } - } - } - - MEM_freeN(verts); -} - -/******************************************** EXPORT ***************************************************/ - -static void exportNode(FILE *f, const char *text, ReebNode *node) -{ - fprintf(f, "%s i:%i w:%f d:%i %f %f %f\n", text, node->index, node->weight, node->degree, node->p[0], node->p[1], node->p[2]); -} - -void REEB_exportGraph(ReebGraph *rg, int count) -{ - ReebArc *arc; - char filename[128]; - FILE *f; - - if (count == -1) { - strcpy(filename, "test.txt"); - } - else { - sprintf(filename, "test%05i.txt", count); - } - f = BLI_fopen(filename, "w"); - - for (arc = rg->arcs.first; arc; arc = arc->next) { - int i; - float p[3]; - - exportNode(f, "v1", arc->head); - - for (i = 0; i < arc->bcount; i++) { - fprintf(f, "b nv:%i %f %f %f\n", arc->buckets[i].nv, arc->buckets[i].p[0], arc->buckets[i].p[1], arc->buckets[i].p[2]); - } - - add_v3_v3v3(p, arc->tail->p, arc->head->p); - mul_v3_fl(p, 0.5f); - - fprintf(f, "angle %0.3f %0.3f %0.3f %0.3f %i\n", p[0], p[1], p[2], arc->angle, BLI_ghash_len(arc->faces)); - exportNode(f, "v2", arc->tail); - } - - fclose(f); -} - -/***************************************** MAIN ALGORITHM **********************************************/ - -/* edges alone will create zero degree nodes, use this function to remove them */ -static void removeZeroNodes(ReebGraph *rg) -{ - ReebNode *node, *next_node; - - for (node = rg->nodes.first; node; node = next_node) { - next_node = node->next; - - if (node->degree == 0) { - BLI_removeNode((BGraph *)rg, (BNode *)node); - } - } -} - -void removeNormalNodes(ReebGraph *rg) -{ - ReebArc *arc, *nextArc; - - // Merge degree 2 nodes - for (arc = rg->arcs.first; arc; arc = nextArc) { - nextArc = arc->next; - - while (arc->head->degree == 2 || arc->tail->degree == 2) { - // merge at v1 - if (arc->head->degree == 2) { - ReebArc *connectedArc = (ReebArc *)BLI_findConnectedArc((BGraph *)rg, (BArc *)arc, (BNode *)arc->head); - - /* If arcs are one after the other */ - if (arc->head == connectedArc->tail) { - /* remove furthest arc */ - if (arc->tail->weight < connectedArc->head->weight) { - mergeConnectedArcs(rg, arc, connectedArc); - nextArc = arc->next; - } - else { - mergeConnectedArcs(rg, connectedArc, arc); - break; /* arc was removed, move to next */ - } - } - /* Otherwise, arcs are side by side */ - else { - /* Don't do anything, we need to keep the lowest node, even if degree 2 */ - break; - } - } - - /* merge at v2 */ - if (arc->tail->degree == 2) { - ReebArc *connectedArc = (ReebArc *)BLI_findConnectedArc((BGraph *)rg, (BArc *)arc, (BNode *)arc->tail); - - /* If arcs are one after the other */ - if (arc->tail == connectedArc->head) { - /* remove furthest arc */ - if (arc->head->weight < connectedArc->tail->weight) { - mergeConnectedArcs(rg, arc, connectedArc); - nextArc = arc->next; - } - else { - mergeConnectedArcs(rg, connectedArc, arc); - break; /* arc was removed, move to next */ - } - } - /* Otherwise, arcs are side by side */ - else { - /* Don't do anything, we need to keep the lowest node, even if degree 2 */ - break; - } - } - } - } - -} - -static int edgeEquals(ReebEdge *e1, ReebEdge *e2) -{ - return (e1->v1 == e2->v1 && e1->v2 == e2->v2); -} - -static ReebArc *nextArcMappedToEdge(ReebArc *arc, ReebEdge *e) -{ - ReebEdge *nextEdge = NULL; - ReebEdge *edge = NULL; - ReebArc *result = NULL; - - /* Find the ReebEdge in the edge list */ - for (edge = arc->edges.first; edge && !edgeEquals(edge, e); edge = edge->next) { } - - nextEdge = edge->nextEdge; - - if (nextEdge != NULL) { - result = nextEdge->arc; - } - - return result; -} - -void addFacetoArc(ReebArc *arc, EditFace *efa) -{ - BLI_ghash_insert(arc->faces, efa, efa); -} - -void mergeArcFaces(ReebGraph *UNUSED(rg), ReebArc *aDst, ReebArc *aSrc) -{ - GHashIterator ghi; - - for (BLI_ghashIterator_init(&ghi, aSrc->faces); - BLI_ghashIterator_done(&ghi) == false; - BLI_ghashIterator_step(&ghi)) - { - EditFace *efa = BLI_ghashIterator_getValue(&ghi); - BLI_ghash_insert(aDst->faces, efa, efa); - } -} - -void mergeArcEdges(ReebGraph *rg, ReebArc *aDst, ReebArc *aSrc, MergeDirection direction) -{ - ReebEdge *e = NULL; - - if (direction == MERGE_APPEND) { - for (e = aSrc->edges.first; e; e = e->next) { - e->arc = aDst; // Edge is stolen by new arc - } - - BLI_movelisttolist(&aDst->edges, &aSrc->edges); - } - else { - for (e = aSrc->edges.first; e; e = e->next) { - ReebEdge *newEdge = copyEdge(e); - - newEdge->arc = aDst; - - BLI_addtail(&aDst->edges, newEdge); - - if (direction == MERGE_LOWER) { - void **p = BLI_edgehash_lookup_p(rg->emap, e->v1->index, e->v2->index); - - newEdge->nextEdge = e; - - // if edge was the first in the list, point the edit edge to the new reeb edge instead. - if (*p == e) { - *p = (void *)newEdge; - } - // otherwise, advance in the list until the predecessor is found then insert it there - else { - ReebEdge *previous = (ReebEdge *)*p; - - while (previous->nextEdge != e) { - previous = previous->nextEdge; - } - - previous->nextEdge = newEdge; - } - } - else { - newEdge->nextEdge = e->nextEdge; - e->nextEdge = newEdge; - } - } - } -} - -// return 1 on full merge -int mergeConnectedArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1) -{ - int result = 0; - ReebNode *removedNode = NULL; - - a0->length += a1->length; - - mergeArcEdges(rg, a0, a1, MERGE_APPEND); - mergeArcFaces(rg, a0, a1); - - // Bring a0 to the combine length of both arcs - if (a0->tail == a1->head) { - removedNode = a0->tail; - a0->tail = a1->tail; - } - else if (a0->head == a1->tail) { - removedNode = a0->head; - a0->head = a1->head; - } - - resizeArcBuckets(a0); - // Merge a1 in a0 - mergeArcBuckets(a0, a1, a0->head->weight, a0->tail->weight); - - // remove a1 from graph - BLI_remlink(&rg->arcs, a1); - REEB_freeArc((BArc *)a1); - - BLI_removeNode((BGraph *)rg, (BNode *)removedNode); - result = 1; - - return result; -} -// return 1 on full merge -int mergeArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1) -{ - int result = 0; - /* TRIANGLE POINTS DOWN */ - if (a0->head->weight == a1->head->weight) { /* heads are the same */ - if (a0->tail->weight == a1->tail->weight) { /* tails also the same, arcs can be totally merge together */ - mergeArcEdges(rg, a0, a1, MERGE_APPEND); - mergeArcFaces(rg, a0, a1); - - mergeArcBuckets(a0, a1, a0->head->weight, a0->tail->weight); - - // Adjust node degree - //a1->head->degree--; - NodeDegreeDecrement(rg, a1->head); - //a1->tail->degree--; - NodeDegreeDecrement(rg, a1->tail); - - // remove a1 from graph - BLI_remlink(&rg->arcs, a1); - - REEB_freeArc((BArc *)a1); - result = 1; - } - else if (a0->tail->weight > a1->tail->weight) { /* a1->tail->weight is in the middle */ - mergeArcEdges(rg, a1, a0, MERGE_LOWER); - mergeArcFaces(rg, a1, a0); - - // Adjust node degree - //a0->head->degree--; - NodeDegreeDecrement(rg, a0->head); - //a1->tail->degree++; - NodeDegreeIncrement(rg, a1->tail); - - mergeArcBuckets(a1, a0, a1->head->weight, a1->tail->weight); - a0->head = a1->tail; - resizeArcBuckets(a0); - } - else { /* a0>n2 is in the middle */ - mergeArcEdges(rg, a0, a1, MERGE_LOWER); - mergeArcFaces(rg, a0, a1); - - // Adjust node degree - //a1->head->degree--; - NodeDegreeDecrement(rg, a1->head); - //a0->tail->degree++; - NodeDegreeIncrement(rg, a0->tail); - - mergeArcBuckets(a0, a1, a0->head->weight, a0->tail->weight); - a1->head = a0->tail; - resizeArcBuckets(a1); - } - } - /* TRIANGLE POINTS UP */ - else if (a0->tail->weight == a1->tail->weight) { /* tails are the same */ - if (a0->head->weight > a1->head->weight) { /* a0->head->weight is in the middle */ - mergeArcEdges(rg, a0, a1, MERGE_HIGHER); - mergeArcFaces(rg, a0, a1); - - // Adjust node degree - //a1->tail->degree--; - NodeDegreeDecrement(rg, a1->tail); - //a0->head->degree++; - NodeDegreeIncrement(rg, a0->head); - - mergeArcBuckets(a0, a1, a0->head->weight, a0->tail->weight); - a1->tail = a0->head; - resizeArcBuckets(a1); - } - else { /* a1->head->weight is in the middle */ - mergeArcEdges(rg, a1, a0, MERGE_HIGHER); - mergeArcFaces(rg, a1, a0); - - // Adjust node degree - //a0->tail->degree--; - NodeDegreeDecrement(rg, a0->tail); - //a1->head->degree++; - NodeDegreeIncrement(rg, a1->head); - - mergeArcBuckets(a1, a0, a1->head->weight, a1->tail->weight); - a0->tail = a1->head; - resizeArcBuckets(a0); - } - } - else { - /* Need something here (OR NOT) */ - } - - return result; -} - -static void glueByMergeSort(ReebGraph *rg, ReebArc *a0, ReebArc *a1, ReebEdge *e0, ReebEdge *e1) -{ - int total = 0; - while (total == 0 && a0 != a1 && a0 != NULL && a1 != NULL) { - total = mergeArcs(rg, a0, a1); - - if (total == 0) // if it wasn't a total merge, go forward { - if (a0->tail->weight < a1->tail->weight) { - a0 = nextArcMappedToEdge(a0, e0); - } - else { - a1 = nextArcMappedToEdge(a1, e1); - } - } - } -} - -static void mergePaths(ReebGraph *rg, ReebEdge *e0, ReebEdge *e1, ReebEdge *e2) -{ - ReebArc *a0, *a1, *a2; - a0 = e0->arc; - a1 = e1->arc; - a2 = e2->arc; - - glueByMergeSort(rg, a0, a1, e0, e1); - glueByMergeSort(rg, a0, a2, e0, e2); -} - -static ReebEdge *createArc(ReebGraph *rg, ReebNode *node1, ReebNode *node2) -{ - ReebEdge *edge; - - edge = BLI_edgehash_lookup(rg->emap, node1->index, node2->index); - - // Only add existing edges that haven't been added yet - if (edge == NULL) { - ReebArc *arc; - ReebNode *v1, *v2; - float len, offset; - int i; - - arc = MEM_callocN(sizeof(ReebArc), "reeb arc"); - edge = MEM_callocN(sizeof(ReebEdge), "reeb edge"); - - arc->flag = 0; // clear flag on init - arc->symmetry_level = 0; - arc->faces = BLI_ghash_ptr_new("createArc gh"); - - if (node1->weight <= node2->weight) { - v1 = node1; - v2 = node2; - } - else { - v1 = node2; - v2 = node1; - } - - arc->head = v1; - arc->tail = v2; - - // increase node degree - //v1->degree++; - NodeDegreeIncrement(rg, v1); - //v2->degree++; - NodeDegreeIncrement(rg, v2); - - BLI_edgehash_insert(rg->emap, node1->index, node2->index, edge); - - edge->arc = arc; - edge->nextEdge = NULL; - edge->v1 = v1; - edge->v2 = v2; - - BLI_addtail(&rg->arcs, arc); - BLI_addtail(&arc->edges, edge); - - /* adding buckets for embedding */ - allocArcBuckets(arc); - - offset = arc->head->weight; - len = arc->tail->weight - arc->head->weight; - -#if 0 - /* This is the actual embedding filling described in the paper - * the problem is that it only works with really dense meshes - */ - if (arc->bcount > 0) - { - addVertToBucket(&(arc->buckets[0]), arc->head->co); - addVertToBucket(&(arc->buckets[arc->bcount - 1]), arc->tail->co); - } -#else - for (i = 0; i < arc->bcount; i++) { - float co[3]; - float f = (arc->buckets[i].val - offset) / len; - - interp_v3_v3v3(co, v1->p, v2->p, f); - addVertToBucket(&(arc->buckets[i]), co); - } -#endif - - } - - return edge; -} - -static void addTriangleToGraph(ReebGraph *rg, ReebNode *n1, ReebNode *n2, ReebNode *n3, EditFace *efa) -{ - ReebEdge *re1, *re2, *re3; - ReebEdge *e1, *e2, *e3; - float len1, len2, len3; - - re1 = createArc(rg, n1, n2); - re2 = createArc(rg, n2, n3); - re3 = createArc(rg, n3, n1); - - addFacetoArc(re1->arc, efa); - addFacetoArc(re2->arc, efa); - addFacetoArc(re3->arc, efa); - - len1 = (float)fabs(n1->weight - n2->weight); - len2 = (float)fabs(n2->weight - n3->weight); - len3 = (float)fabs(n3->weight - n1->weight); - - /* The rest of the algorithm assumes that e1 is the longest edge */ - - if (len1 >= len2 && len1 >= len3) { - e1 = re1; - e2 = re2; - e3 = re3; - } - else if (len2 >= len1 && len2 >= len3) { - e1 = re2; - e2 = re1; - e3 = re3; - } - else { - e1 = re3; - e2 = re2; - e3 = re1; - } - - /* And e2 is the lowest edge - * If e3 is lower than e2, swap them - */ - if (e3->v1->weight < e2->v1->weight) { - ReebEdge *etmp = e2; - e2 = e3; - e3 = etmp; - } - - - mergePaths(rg, e1, e2, e3); -} - -ReebGraph *generateReebGraph(EditMesh *em, int subdivisions) -{ - ReebGraph *rg; - EditVert *eve; - EditFace *efa; - int index; - /*int totvert;*/ - -#ifdef DEBUG_REEB - int totfaces; - int countfaces = 0; -#endif - - rg = newReebGraph(); - - rg->resolution = subdivisions; - - /*totvert = BLI_listbase_count(&em->verts);*/ /*UNUSED*/ -#ifdef DEBUG_REEB - totfaces = BLI_listbase_count(&em->faces); -#endif - - renormalizeWeight(em, 1.0f); - - /* Spread weight to minimize errors */ - spreadWeight(em); - - renormalizeWeight(em, (float)rg->resolution); - - /* Adding vertice */ - for (index = 0, eve = em->verts.first; eve; eve = eve->next) { - if (eve->h == 0) { - addNode(rg, eve); - eve->f2 = 0; - index++; - } - } - - /* Adding face, edge per edge */ - for (efa = em->faces.first; efa; efa = efa->next) { - if (efa->h == 0) { - ReebNode *n1, *n2, *n3; - - n1 = nodeData(efa->v1); - n2 = nodeData(efa->v2); - n3 = nodeData(efa->v3); - - addTriangleToGraph(rg, n1, n2, n3, efa); - - if (efa->v4) { - ReebNode *n4 = nodeData(efa->v4); - addTriangleToGraph(rg, n1, n3, n4, efa); - } -#ifdef DEBUG_REEB - countfaces++; - if (countfaces % 100 == 0) { - printf("\rface %i of %i", countfaces, totfaces); - } -#endif - } - } - - printf("\n"); - - removeZeroNodes(rg); - - removeNormalNodes(rg); - - return rg; -} - -/***************************************** WEIGHT UTILS **********************************************/ - -void renormalizeWeight(EditMesh *em, float newmax) -{ - EditVert *eve; - float minimum, maximum, range; - - if (em == NULL || BLI_listbase_is_empty(&em->verts)) - return; - - /* First pass, determine maximum and minimum */ - eve = em->verts.first; - minimum = weightData(eve); - maximum = minimum; - for (; eve; eve = eve->next) { - maximum = MAX2(maximum, weightData(eve)); - minimum = MIN2(minimum, weightData(eve)); - } - - range = maximum - minimum; - - /* Normalize weights */ - for (eve = em->verts.first; eve; eve = eve->next) { - float weight = (weightData(eve) - minimum) / range * newmax; - weightSetData(eve, weight); - } -} - - -int weightFromLoc(EditMesh *em, int axis) -{ - EditVert *eve; - - if (em == NULL || BLI_listbase_is_empty(&em->verts) || axis < 0 || axis > 2) - return 0; - - /* Copy coordinate in weight */ - for (eve = em->verts.first; eve; eve = eve->next) { - weightSetData(eve, eve->co[axis]); - } - - return 1; -} - -static void addTriangle(LinearSolver *context, EditVert *v1, EditVert *v2, EditVert *v3, int e1, int e2, int e3) -{ - /* Angle opposite e1 */ - float t1 = cotangent_tri_weight_v3(v1->co, v2->co, v3->co) / e2; - - /* Angle opposite e2 */ - float t2 = cotangent_tri_weight_v3(v2->co, v3->co, v1->co) / e3; - - /* Angle opposite e3 */ - float t3 = cotangent_tri_weight_v3(v3->co, v1->co, v2->co) / e1; - - int i1 = indexData(v1); - int i2 = indexData(v2); - int i3 = indexData(v3); - - EIG_linear_solver_matrix_add(context, i1, i1, t2 + t3); - EIG_linear_solver_matrix_add(context, i2, i2, t1 + t3); - EIG_linear_solver_matrix_add(context, i3, i3, t1 + t2); - - EIG_linear_solver_matrix_add(context, i1, i2, -t3); - EIG_linear_solver_matrix_add(context, i2, i1, -t3); - - EIG_linear_solver_matrix_add(context, i2, i3, -t1); - EIG_linear_solver_matrix_add(context, i3, i2, -t1); - - EIG_linear_solver_matrix_add(context, i3, i1, -t2); - EIG_linear_solver_matrix_add(context, i1, i3, -t2); -} - -int weightToHarmonic(EditMesh *em, EdgeIndex *indexed_edges) -{ - LinearSolver *context; - NLboolean success; - EditVert *eve; - EditEdge *eed; - EditFace *efa; - int totvert = 0; - int index; - int rval; - - /* Find local extrema */ - for (eve = em->verts.first; eve; eve = eve->next) { - totvert++; - } - - /* Solve */ - - context = EIG_linear_solver_new(, 0, totvert, 1); - - /* Find local extrema */ - for (index = 0, eve = em->verts.first; eve; index++, eve = eve->next) { - if (eve->h == 0) { - EditEdge *eed; - int maximum = 1; - int minimum = 1; - - NextEdgeForVert(indexed_edges, -1); /* Reset next edge */ - for (eed = NextEdgeForVert(indexed_edges, index); eed && (maximum || minimum); eed = NextEdgeForVert(indexed_edges, index)) { - EditVert *eve2; - - if (eed->v1 == eve) { - eve2 = eed->v2; - } - else { - eve2 = eed->v1; - } - - if (eve2->h == 0) { - /* Adjacent vertex is bigger, not a local maximum */ - if (weightData(eve2) > weightData(eve)) { - maximum = 0; - } - /* Adjacent vertex is smaller, not a local minimum */ - else if (weightData(eve2) < weightData(eve)) { - minimum = 0; - } - } - } - - if (maximum || minimum) { - float w = weightData(eve); - eve->f1 = 0; - EIG_linear_solver_variable_set(context, 0, index, w); - EIG_linear_solver_variable_lock(context, index); - } - else { - eve->f1 = 1; - } - } - } - - /* Zero edge weight */ - for (eed = em->edges.first; eed; eed = eed->next) { - eed->tmp.l = 0; - } - - /* Add faces count to the edge weight */ - for (efa = em->faces.first; efa; efa = efa->next) { - if (efa->h == 0) { - efa->e1->tmp.l++; - efa->e2->tmp.l++; - efa->e3->tmp.l++; - - if (efa->e4) { - efa->e4->tmp.l++; - } - } - } - - /* Add faces angle to the edge weight */ - for (efa = em->faces.first; efa; efa = efa->next) { - if (efa->h == 0) { - if (efa->v4 == NULL) { - addTriangle(context, efa->v1, efa->v2, efa->v3, efa->e1->tmp.l, efa->e2->tmp.l, efa->e3->tmp.l); - } - else { - addTriangle(context, efa->v1, efa->v2, efa->v3, efa->e1->tmp.l, efa->e2->tmp.l, 2); - addTriangle(context, efa->v3, efa->v4, efa->v1, efa->e3->tmp.l, efa->e4->tmp.l, 2); - } - } - } - - success = EIG_linear_solver_solve(context); - - if (success) { - rval = 1; - for (index = 0, eve = em->verts.first; eve; index++, eve = eve->next) { - weightSetData(eve, EIG_linear_solver_variable_get(context, 0, index)); - } - } - else { - rval = 0; - } - - EIG_linear_solver_delete(context); - - return rval; -} - - -EditEdge *NextEdgeForVert(EdgeIndex *indexed_edges, int index) -{ - static int offset = -1; - - /* Reset method, call with NULL mesh pointer */ - if (index == -1) { - offset = -1; - return NULL; - } - - /* first pass, start at the head of the list */ - if (offset == -1) { - offset = indexed_edges->offset[index]; - } - /* subsequent passes, start on the next edge */ - else { - offset++; - } - - return indexed_edges->edges[offset]; -} - -static void shortestPathsFromVert(EditMesh *em, EditVert *starting_vert, EdgeIndex *indexed_edges) -{ - Heap *edge_heap; - EditVert *current_eve = NULL; - EditEdge *eed = NULL; - EditEdge *select_eed = NULL; - - edge_heap = BLI_heap_new(); - - current_eve = starting_vert; - - /* insert guard in heap, when that is returned, no more edges */ - BLI_heap_insert(edge_heap, FLT_MAX, NULL); - - /* Initialize edge flag */ - for (eed = em->edges.first; eed; eed = eed->next) { - eed->f1 = 0; - } - - while (BLI_heap_len(edge_heap) > 0) { - float current_weight; - - current_eve->f1 = 1; /* mark vertex as selected */ - - /* Add all new edges connected to current_eve to the list */ - NextEdgeForVert(indexed_edges, -1); // Reset next edge - for (eed = NextEdgeForVert(indexed_edges, indexData(current_eve)); eed; eed = NextEdgeForVert(indexed_edges, indexData(current_eve))) { - if (eed->f1 == 0) { - BLI_heap_insert(edge_heap, weightData(current_eve) + eed->tmp.fp, eed); - eed->f1 = 1; - } - } - - /* Find next shortest edge with unselected verts */ - do { - current_weight = BLI_heap_node_value(BLI_heap_top(edge_heap)); - select_eed = BLI_heap_pop_min(edge_heap); - } while (select_eed != NULL && select_eed->v1->f1 != 0 && select_eed->v2->f1); - - if (select_eed != NULL) { - select_eed->f1 = 2; - - if (select_eed->v1->f1 == 0) /* v1 is the new vertex */ { - current_eve = select_eed->v1; - } - else { /* otherwise, it's v2 */ - current_eve = select_eed->v2; - } - - weightSetData(current_eve, current_weight); - } - } - - BLI_heap_free(edge_heap, NULL); -} - -static void freeEdgeIndex(EdgeIndex *indexed_edges) -{ - MEM_freeN(indexed_edges->offset); - MEM_freeN(indexed_edges->edges); -} - -static void buildIndexedEdges(EditMesh *em, EdgeIndex *indexed_edges) -{ - EditVert *eve; - EditEdge *eed; - int totvert = 0; - int tot_indexed = 0; - int offset = 0; - - totvert = BLI_listbase_count(&em->verts); - - indexed_edges->offset = MEM_callocN(totvert * sizeof(int), "EdgeIndex offset"); - - for (eed = em->edges.first; eed; eed = eed->next) { - if (eed->v1->h == 0 && eed->v2->h == 0) { - tot_indexed += 2; - indexed_edges->offset[indexData(eed->v1)]++; - indexed_edges->offset[indexData(eed->v2)]++; - } - } - - tot_indexed += totvert; - - indexed_edges->edges = MEM_callocN(tot_indexed * sizeof(EditEdge *), "EdgeIndex edges"); - - /* setting vert offsets */ - for (eve = em->verts.first; eve; eve = eve->next) { - if (eve->h == 0) { - int d = indexed_edges->offset[indexData(eve)]; - indexed_edges->offset[indexData(eve)] = offset; - offset += d + 1; - } - } - - /* adding edges in array */ - for (eed = em->edges.first; eed; eed = eed->next) { - if (eed->v1->h == 0 && eed->v2->h == 0) { - int i; - for (i = indexed_edges->offset[indexData(eed->v1)]; i < tot_indexed; i++) { - if (indexed_edges->edges[i] == NULL) { - indexed_edges->edges[i] = eed; - break; - } - } - - for (i = indexed_edges->offset[indexData(eed->v2)]; i < tot_indexed; i++) { - if (indexed_edges->edges[i] == NULL) { - indexed_edges->edges[i] = eed; - break; - } - } - } - } -} - -int weightFromDistance(EditMesh *em, EdgeIndex *indexed_edges) -{ - EditVert *eve; - int totedge = 0; - int totvert = 0; - int vCount = 0; - - totvert = BLI_listbase_count(&em->verts); - - if (em == NULL || totvert == 0) { - return 0; - } - - totedge = BLI_listbase_count(&em->edges); - - if (totedge == 0) { - return 0; - } - - /* Initialize vertice flag and find at least one selected vertex */ - for (eve = em->verts.first; eve; eve = eve->next) { - eve->f1 = 0; - if (eve->f & SELECT) { - vCount = 1; - } - } - - if (vCount == 0) { - return 0; /* no selected vert, failure */ - } - else { - EditEdge *eed; - int allDone = 0; - - /* Calculate edge weight */ - for (eed = em->edges.first; eed; eed = eed->next) { - if (eed->v1->h == 0 && eed->v2->h == 0) { - eed->tmp.fp = len_v3v3(eed->v1->co, eed->v2->co); - } - } - - /* Apply dijkstra spf for each selected vert */ - for (eve = em->verts.first; eve; eve = eve->next) { - if (eve->f & SELECT) { - shortestPathsFromVert(em, eve, indexed_edges); - } - } - - /* connect unselected islands */ - while (allDone == 0) { - EditVert *selected_eve = NULL; - float selected_weight = 0; - float min_distance = FLT_MAX; - - allDone = 1; - - for (eve = em->verts.first; eve; eve = eve->next) { - /* for every vertex visible that hasn't been processed yet */ - if (eve->h == 0 && eve->f1 != 1) { - EditVert *closest_eve; - - /* find the closest processed vertex */ - for (closest_eve = em->verts.first; closest_eve; closest_eve = closest_eve->next) { - /* vertex is already processed and distance is smaller than current minimum */ - if (closest_eve->f1 == 1) { - float distance = len_v3v3(closest_eve->co, eve->co); - if (distance < min_distance) { - min_distance = distance; - selected_eve = eve; - selected_weight = weightData(closest_eve); - } - } - } - } - } - - if (selected_eve) { - allDone = 0; - - weightSetData(selected_eve, selected_weight + min_distance); - shortestPathsFromVert(em, selected_eve, indexed_edges); - } - } - } - - for (eve = em->verts.first; eve && vCount == 0; eve = eve->next) { - if (eve->f1 == 0) { - printf("vertex not reached\n"); - break; - } - } - - return 1; -} -#endif - -/****************************************** BUCKET ITERATOR **************************************************/ - -static void *headNode(void *arg); -static void *tailNode(void *arg); -static void *nextBucket(void *arg); -static void *nextNBucket(void *arg, int n); -static void *peekBucket(void *arg, int n); -static void *previousBucket(void *arg); -static int iteratorStopped(void *arg); - -static void initIteratorFct(ReebArcIterator *iter) -{ - iter->head = headNode; - iter->tail = tailNode; - iter->peek = peekBucket; - iter->next = nextBucket; - iter->nextN = nextNBucket; - iter->previous = previousBucket; - iter->stopped = iteratorStopped; -} - -static void setIteratorValues(ReebArcIterator *iter, EmbedBucket *bucket) -{ - if (bucket) { - iter->p = bucket->p; - iter->no = bucket->no; - } - else { - iter->p = NULL; - iter->no = NULL; - } - iter->size = 0; -} - -void initArcIterator(BArcIterator *arg, ReebArc *arc, ReebNode *head) -{ - ReebArcIterator *iter = (ReebArcIterator *)arg; - - initIteratorFct(iter); - iter->arc = arc; - - if (head == arc->head) { - iter->start = 0; - iter->end = arc->bcount - 1; - iter->stride = 1; - } - else { - iter->start = arc->bcount - 1; - iter->end = 0; - iter->stride = -1; - } - - iter->length = arc->bcount; - - iter->index = -1; -} - -void initArcIteratorStart(BArcIterator *arg, struct ReebArc *arc, struct ReebNode *head, int start) -{ - ReebArcIterator *iter = (ReebArcIterator *)arg; - - initIteratorFct(iter); - iter->arc = arc; - - if (head == arc->head) { - iter->start = start; - iter->end = arc->bcount - 1; - iter->stride = 1; - } - else { - iter->start = arc->bcount - 1 - start; - iter->end = 0; - iter->stride = -1; - } - - iter->index = -1; - - iter->length = arc->bcount - start; - - if (start >= arc->bcount) { - iter->start = iter->end; /* stop iterator since it's past its end */ - } -} - -void initArcIterator2(BArcIterator *arg, ReebArc *arc, int start, int end) -{ - ReebArcIterator *iter = (ReebArcIterator *)arg; - - initIteratorFct(iter); - iter->arc = arc; - - iter->start = start; - iter->end = end; - - if (end > start) { - iter->stride = 1; - } - else { - iter->stride = -1; - } - - iter->index = -1; - - iter->length = abs(iter->end - iter->start) + 1; -} - -static void *headNode(void *arg) -{ - ReebArcIterator *iter = (ReebArcIterator *)arg; - ReebNode *node; - - if (iter->start < iter->end) { - node = iter->arc->head; - } - else { - node = iter->arc->tail; - } - - iter->p = node->p; - iter->no = node->no; - iter->size = 0; - - return node; -} - -static void *tailNode(void *arg) -{ - ReebArcIterator *iter = (ReebArcIterator *)arg; - ReebNode *node; - - if (iter->start < iter->end) { - node = iter->arc->tail; - } - else { - node = iter->arc->head; - } - - iter->p = node->p; - iter->no = node->no; - iter->size = 0; - - return node; -} - -static void *nextBucket(void *arg) -{ - ReebArcIterator *iter = (ReebArcIterator *)arg; - EmbedBucket *result = NULL; - - iter->index++; - - if (iter->index < iter->length) { - result = &(iter->arc->buckets[iter->start + (iter->stride * iter->index)]); - } - - setIteratorValues(iter, result); - return result; -} - -static void *nextNBucket(void *arg, int n) -{ - ReebArcIterator *iter = (ReebArcIterator *)arg; - EmbedBucket *result = NULL; - - iter->index += n; - - /* check if passed end */ - if (iter->index < iter->length) { - result = &(iter->arc->buckets[iter->start + (iter->stride * iter->index)]); - } - - setIteratorValues(iter, result); - return result; -} - -static void *peekBucket(void *arg, int n) -{ - ReebArcIterator *iter = (ReebArcIterator *)arg; - EmbedBucket *result = NULL; - int index = iter->index + n; - - /* check if passed end */ - if (index < iter->length) { - result = &(iter->arc->buckets[iter->start + (iter->stride * index)]); - } - - setIteratorValues(iter, result); - return result; -} - -static void *previousBucket(void *arg) -{ - ReebArcIterator *iter = (ReebArcIterator *)arg; - EmbedBucket *result = NULL; - - if (iter->index > 0) { - iter->index--; - result = &(iter->arc->buckets[iter->start + (iter->stride * iter->index)]); - } - - setIteratorValues(iter, result); - return result; -} - -static int iteratorStopped(void *arg) -{ - ReebArcIterator *iter = (ReebArcIterator *)arg; - - if (iter->index >= iter->length) { - return 1; - } - else { - return 0; - } -} - -/************************ PUBLIC FUNCTIONS *********************************************/ - -ReebGraph *BIF_ReebGraphMultiFromEditMesh(bContext *C) -{ - (void)C; - return NULL; -#if 0 - Scene *scene = CTX_data_scene(C); - Object *obedit = CTX_data_edit_object(C); - EditMesh *em = BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - EdgeIndex indexed_edges; - VertexData *data; - ReebGraph *rg = NULL; - ReebGraph *rgi, *previous; - int i, nb_levels = REEB_MAX_MULTI_LEVEL; - - if (em == NULL) - return NULL; - - data = allocVertexData(em); - - buildIndexedEdges(em, &indexed_edges); - - if (weightFromDistance(em, &indexed_edges) == 0) - { - // XXX error("No selected vertex\n"); - freeEdgeIndex(&indexed_edges); - return NULL; - } - - renormalizeWeight(em, 1.0f); - - if (scene->toolsettings->skgen_options & SKGEN_HARMONIC) - { - weightToHarmonic(em, &indexed_edges); - } - - freeEdgeIndex(&indexed_edges); - - rg = generateReebGraph(em, scene->toolsettings->skgen_resolution); - - /* Remove arcs without embedding */ - filterNullReebGraph(rg); - - /* smart filter and loop filter on basic level */ - filterGraph(rg, SKGEN_FILTER_SMART, 0, 0); - - repositionNodes(rg); - - /* Filtering might have created degree 2 nodes, so remove them */ - removeNormalNodes(rg); - - joinSubgraphs(rg, 1.0); - - BLI_buildAdjacencyList((BGraph *)rg); - - /* calc length before copy, so we have same length on all levels */ - BLI_calcGraphLength((BGraph *)rg); - - previous = NULL; - for (i = 0; i <= nb_levels; i++) - { - rgi = rg; - - /* don't filter last level */ - if (i > 0) - { - float internal_threshold; - float external_threshold; - - /* filter internal progressively in second half only*/ - if (i > nb_levels / 2) - { - internal_threshold = rg->length * scene->toolsettings->skgen_threshold_internal; - } - else { - internal_threshold = rg->length * scene->toolsettings->skgen_threshold_internal * (2 * i / (float)nb_levels); - } - - external_threshold = rg->length * scene->toolsettings->skgen_threshold_external * (i / (float)nb_levels); - - filterGraph(rgi, scene->toolsettings->skgen_options, internal_threshold, external_threshold); - } - - if (i < nb_levels) - { - rg = copyReebGraph(rgi, i + 1); - } - - finalizeGraph(rgi, scene->toolsettings->skgen_postpro_passes, scene->toolsettings->skgen_postpro); - - BLI_markdownSymmetry((BGraph *)rgi, rgi->nodes.first, scene->toolsettings->skgen_symmetry_limit); - - if (previous != NULL) - { - relinkNodes(rgi, previous); - } - previous = rgi; - } - - verifyMultiResolutionLinks(rg, 0); - - MEM_freeN(data); - - /* no need to load the editmesh back into the object, just - * free it (avoids ngon conversion issues too going back the other way) */ - free_editMesh(em); - MEM_freeN(em); - - return rg; -#endif -} diff --git a/source/blender/editors/armature/reeb.h b/source/blender/editors/armature/reeb.h deleted file mode 100644 index a6ef16fed67..00000000000 --- a/source/blender/editors/armature/reeb.h +++ /dev/null @@ -1,207 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributor(s): Martin Poirier - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/editors/armature/reeb.h - * \ingroup edarmature - */ - - -#ifndef __REEB_H__ -#define __REEB_H__ - -#define WITH_BF_REEB - -#include "DNA_listBase.h" - -#include "BLI_graph.h" - -struct GHash; -struct EdgeHash; -struct ReebArc; -struct ReebEdge; -struct ReebNode; - -typedef struct ReebGraph { - ListBase arcs; - ListBase nodes; - - float length; - - FreeArc free_arc; - FreeNode free_node; - RadialSymmetry radial_symmetry; - AxialSymmetry axial_symmetry; - /*********************************/ - - int resolution; - int totnodes; - struct EdgeHash *emap; - int multi_level; - struct ReebGraph *link_up; /* for multi resolution filtering, points to higher levels */ -} ReebGraph; - -typedef struct EmbedBucket { - float val; - int nv; - float p[3]; - float no[3]; /* if non-null, normal of the bucket */ -} EmbedBucket; - -typedef struct ReebNode { - void *next, *prev; - float p[3]; - int flag; - - int degree; - struct ReebArc **arcs; - - int subgraph_index; - - int symmetry_level; - int symmetry_flag; - float symmetry_axis[3]; - /*********************************/ - - float no[3]; - - int index; - float weight; - int multi_level; - struct ReebNode *link_down; /* for multi resolution filtering, points to lower levels, if present */ - struct ReebNode *link_up; -} ReebNode; - -typedef struct ReebEdge { - struct ReebEdge *next, *prev; - struct ReebArc *arc; - struct ReebNode *v1, *v2; - struct ReebEdge *nextEdge; - int flag; -} ReebEdge; - -typedef struct ReebArc { - void *next, *prev; - struct ReebNode *head, *tail; - int flag; - - float length; - - int symmetry_level; - int symmetry_group; - int symmetry_flag; - /*********************************/ - - ListBase edges; - int bcount; - struct EmbedBucket *buckets; - - struct GHash *faces; - float angle; - struct ReebArc *link_up; /* for multi resolution filtering, points to higher levels */ -} ReebArc; - -typedef struct ReebArcIterator { - HeadFct head; - TailFct tail; - PeekFct peek; - NextFct next; - NextNFct nextN; - PreviousFct previous; - StoppedFct stopped; - - float *p, *no; - float size; - - int length; - int index; - /*********************************/ - struct ReebArc *arc; - int start; - int end; - int stride; -} ReebArcIterator; - -#if 0 -struct EditMesh; -struct EdgeIndex; - -int weightToHarmonic(struct EditMesh *em, struct EdgeIndex *indexed_edges); -int weightFromDistance(struct EditMesh *em, struct EdgeIndex *indexed_edges); -int weightFromLoc(struct EditMesh *me, int axis); -//void weightToVCol(struct EditMesh *em, int index); -void arcToVCol(struct ReebGraph *rg, struct EditMesh *em, int index); -//void angleToVCol(struct EditMesh *em, int index); -void renormalizeWeight(struct EditMesh *em, float newmax); - -ReebGraph *generateReebGraph(struct EditMesh *me, int subdivisions); -#endif - -ReebGraph *newReebGraph(void); - -void initArcIterator(BArcIterator *iter, struct ReebArc *arc, struct ReebNode *head); -void initArcIterator2(BArcIterator *iter, struct ReebArc *arc, int start, int end); -void initArcIteratorStart(BArcIterator *iter, struct ReebArc *arc, struct ReebNode *head, int start); - -/* Filtering */ -void filterNullReebGraph(ReebGraph *rg); -int filterSmartReebGraph(ReebGraph *rg, float threshold); - -/* Post-Build processing */ -void repositionNodes(ReebGraph *rg); -void postprocessGraph(ReebGraph *rg, char mode); -void removeNormalNodes(ReebGraph *rg); - -void sortNodes(ReebGraph *rg); -void sortArcs(ReebGraph *rg); - -/*------------ Sanity check ------------*/ -void verifyBuckets(ReebGraph *rg); -void verifyFaces(ReebGraph *rg); -void verifyArcs(ReebGraph *rg); -void verifyNodeDegree(ReebGraph *rg); - -/*********************** PUBLIC *********************************/ - -#define REEB_MAX_MULTI_LEVEL 10 - -struct bContext; - -ReebGraph *BIF_ReebGraphFromEditMesh(void); -ReebGraph *BIF_ReebGraphMultiFromEditMesh(struct bContext *C); -void BIF_flagMultiArcs(ReebGraph *rg, int flag); - -void BIF_GlobalReebGraphFromEditMesh(void); -void BIF_GlobalReebFree(void); - -ReebNode *BIF_otherNodeFromIndex(ReebArc *arc, ReebNode *node); -ReebNode *BIF_NodeFromIndex(ReebArc *arc, ReebNode *node); -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(void); - - -#endif /*__REEB_H__*/ diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index b74d6ed8d69..ccd47463a9c 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -679,7 +679,7 @@ static short gp_stroke_addpoint( /* simplify a stroke (in buffer) before storing it * - applies a reverse Chaikin filter - * - code adapted from etch-a-ton branch (editarmature_sketch.c) + * - code adapted from etch-a-ton branch */ static void gp_stroke_simplify(tGPsdata *p) { diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index 69f71f3df44..8b5886d65f1 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -226,26 +226,6 @@ void ED_pose_bone_select(struct Object *ob, struct bPoseChannel *pchan, bool sel void ED_pose_recalculate_paths(struct bContext *C, struct Scene *scene, struct Object *ob); struct Object *ED_pose_object_from_context(struct bContext *C); -/* sketch */ - -int ED_operator_sketch_mode_active_stroke(struct bContext *C); -int ED_operator_sketch_full_mode(struct bContext *C); -int ED_operator_sketch_mode(const struct bContext *C); - -void BIF_convertSketch(struct bContext *C); -void BIF_deleteSketch(struct bContext *C); -void BIF_selectAllSketch(struct bContext *C, int mode); /* -1: deselect, 0: select, 1: toggle */ - -void BIF_makeListTemplates(const struct bContext *C); -int BIF_currentTemplate(const struct bContext *C); -void BIF_freeTemplates(struct bContext *C); -void BIF_setTemplate(struct bContext *C, int index); -int BIF_nbJointsTemplate(const struct bContext *C); -const char *BIF_nameBoneTemplate(const struct bContext *C); - -void BDR_drawSketch(const struct bContext *vc); -int BDR_drawSketchNames(struct ViewContext *vc); - /* meshlaplacian.c */ void ED_mesh_deform_bind_callback( struct Scene *scene, |