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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2018-04-20 11:18:25 +0300
committerCampbell Barton <ideasman42@gmail.com>2018-04-20 11:34:48 +0300
commit36773e35f6009693562330137435271922758b95 (patch)
tree955bdbe2382e28a9ff0cf10efc498c1780ef8f43
parent98422c36abe0792ec44d3e0378faef4b2249940f (diff)
Remove Armature Sketching & Retarget
While the feature is interesting, it's not much from what we can tell. Retargeting is an important feature but needs to fit in better with typical animation work-flows. See: T52809
-rw-r--r--release/scripts/presets/keyconfig/3dsmax.py11
-rw-r--r--release/scripts/presets/keyconfig/maya.py11
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py58
-rw-r--r--source/blender/blenkernel/BKE_sketch.h149
-rw-r--r--source/blender/blenkernel/CMakeLists.txt2
-rw-r--r--source/blender/blenkernel/intern/armature.c8
-rw-r--r--source/blender/blenkernel/intern/library_query.c2
-rw-r--r--source/blender/blenkernel/intern/scene.c15
-rw-r--r--source/blender/blenkernel/intern/sketch.c555
-rw-r--r--source/blender/blenlib/BLI_graph.h185
-rw-r--r--source/blender/blenlib/CMakeLists.txt2
-rw-r--r--source/blender/blenlib/intern/graph.c1016
-rw-r--r--source/blender/blenloader/intern/readfile.c3
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c41
-rw-r--r--source/blender/editors/armature/BIF_generate.h49
-rw-r--r--source/blender/editors/armature/BIF_retarget.h171
-rw-r--r--source/blender/editors/armature/CMakeLists.txt7
-rw-r--r--source/blender/editors/armature/armature_intern.h13
-rw-r--r--source/blender/editors/armature/armature_ops.c27
-rw-r--r--source/blender/editors/armature/armature_select.c4
-rw-r--r--source/blender/editors/armature/armature_skinning.c4
-rw-r--r--source/blender/editors/armature/armature_utils.c2
-rw-r--r--source/blender/editors/armature/editarmature_generate.c305
-rw-r--r--source/blender/editors/armature/editarmature_retarget.c2641
-rw-r--r--source/blender/editors/armature/editarmature_sketch.c2651
-rw-r--r--source/blender/editors/armature/reeb.c3201
-rw-r--r--source/blender/editors/armature/reeb.h207
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c2
-rw-r--r--source/blender/editors/include/ED_armature.h20
-rw-r--r--source/blender/makesdna/DNA_armature_types.h2
-rw-r--r--source/blender/makesdna/DNA_scene_types.h47
-rw-r--r--source/blender/makesrna/intern/rna_scene.c91
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c5
33 files changed, 7 insertions, 11500 deletions
diff --git a/release/scripts/presets/keyconfig/3dsmax.py b/release/scripts/presets/keyconfig/3dsmax.py
index c77ad6cfece..d65ecaa9204 100644
--- a/release/scripts/presets/keyconfig/3dsmax.py
+++ b/release/scripts/presets/keyconfig/3dsmax.py
@@ -2278,17 +2278,6 @@ kmi.properties.value_2 = 'CONNECTED'
# Map Armature
km = kc.keymaps.new('Armature', space_type='EMPTY', region_type='WINDOW', modal=False)
-kmi = km.keymap_items.new('sketch.delete', 'X', 'PRESS')
-kmi = km.keymap_items.new('sketch.delete', 'DEL', 'PRESS')
-kmi = km.keymap_items.new('sketch.finish_stroke', 'RIGHTMOUSE', 'PRESS')
-kmi = km.keymap_items.new('sketch.cancel_stroke', 'ESC', 'PRESS')
-kmi = km.keymap_items.new('sketch.gesture', 'LEFTMOUSE', 'PRESS', shift=True)
-kmi = km.keymap_items.new('sketch.draw_stroke', 'LEFTMOUSE', 'PRESS')
-kmi = km.keymap_items.new('sketch.draw_stroke', 'LEFTMOUSE', 'PRESS', ctrl=True)
-kmi.properties.snap = True
-kmi = km.keymap_items.new('sketch.draw_preview', 'MOUSEMOVE', 'ANY')
-kmi = km.keymap_items.new('sketch.draw_preview', 'MOUSEMOVE', 'ANY', ctrl=True)
-kmi.properties.snap = True
kmi = km.keymap_items.new('armature.hide', 'H', 'PRESS')
kmi.properties.unselected = False
kmi = km.keymap_items.new('armature.hide', 'H', 'PRESS', shift=True)
diff --git a/release/scripts/presets/keyconfig/maya.py b/release/scripts/presets/keyconfig/maya.py
index 7c8844444f1..09371e75950 100644
--- a/release/scripts/presets/keyconfig/maya.py
+++ b/release/scripts/presets/keyconfig/maya.py
@@ -770,17 +770,6 @@ kmi.properties.value_2 = 'CONNECTED'
# Map Armature
km = kc.keymaps.new('Armature', space_type='EMPTY', region_type='WINDOW', modal=False)
-kmi = km.keymap_items.new('sketch.delete', 'BACK_SPACE', 'PRESS')
-kmi = km.keymap_items.new('sketch.delete', 'DEL', 'PRESS')
-kmi = km.keymap_items.new('sketch.finish_stroke', 'RIGHTMOUSE', 'PRESS')
-kmi = km.keymap_items.new('sketch.cancel_stroke', 'ESC', 'PRESS')
-kmi = km.keymap_items.new('sketch.gesture', 'LEFTMOUSE', 'PRESS', shift=True)
-kmi = km.keymap_items.new('sketch.draw_stroke', 'LEFTMOUSE', 'PRESS')
-kmi = km.keymap_items.new('sketch.draw_stroke', 'LEFTMOUSE', 'PRESS', ctrl=True)
-kmi.properties.snap = True
-kmi = km.keymap_items.new('sketch.draw_preview', 'MOUSEMOVE', 'ANY')
-kmi = km.keymap_items.new('sketch.draw_preview', 'MOUSEMOVE', 'ANY', ctrl=True)
-kmi.properties.snap = True
kmi = km.keymap_items.new('armature.hide', 'H', 'PRESS', ctrl=True)
kmi.properties.unselected = False
kmi = km.keymap_items.new('armature.hide', 'H', 'PRESS', alt=True)
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index d211d8bb6fe..ce439049a0a 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -3716,63 +3716,6 @@ class VIEW3D_PT_transform_orientations(Panel):
row.operator("transform.delete_orientation", text="", icon='X')
-class VIEW3D_PT_etch_a_ton(Panel):
- bl_space_type = 'VIEW_3D'
- bl_region_type = 'UI'
- bl_label = "Skeleton Sketching"
- bl_options = {'DEFAULT_CLOSED'}
-
- @classmethod
- def poll(cls, context):
- scene = context.space_data
- ob = context.active_object
- return scene and ob and ob.type == 'ARMATURE' and ob.mode == 'EDIT'
-
- def draw_header(self, context):
- layout = self.layout
- toolsettings = context.scene.tool_settings
-
- layout.prop(toolsettings, "use_bone_sketching", text="")
-
- def draw(self, context):
- layout = self.layout
-
- toolsettings = context.scene.tool_settings
-
- col = layout.column()
-
- col.prop(toolsettings, "use_etch_quick")
- col.prop(toolsettings, "use_etch_overdraw")
-
- col.separator()
-
- col.prop(toolsettings, "etch_convert_mode")
-
- if toolsettings.etch_convert_mode == 'LENGTH':
- col.prop(toolsettings, "etch_length_limit")
- elif toolsettings.etch_convert_mode == 'ADAPTIVE':
- col.prop(toolsettings, "etch_adaptive_limit")
- elif toolsettings.etch_convert_mode == 'FIXED':
- col.prop(toolsettings, "etch_subdivision_number")
- elif toolsettings.etch_convert_mode == 'RETARGET':
- col.prop(toolsettings, "etch_template")
- col.prop(toolsettings, "etch_roll_mode")
-
- col.separator()
-
- colsub = col.column(align=True)
- colsub.prop(toolsettings, "use_etch_autoname")
- sub = colsub.column(align=True)
- sub.enabled = not toolsettings.use_etch_autoname
- sub.prop(toolsettings, "etch_number")
- sub.prop(toolsettings, "etch_side")
-
- col.separator()
-
- col.operator("sketch.convert", text="Convert to Bones")
- col.operator("sketch.delete", text="Delete Strokes")
-
-
class VIEW3D_PT_context_properties(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
@@ -3948,7 +3891,6 @@ classes = (
VIEW3D_PT_view3d_meshstatvis,
VIEW3D_PT_view3d_curvedisplay,
VIEW3D_PT_transform_orientations,
- VIEW3D_PT_etch_a_ton,
VIEW3D_PT_context_properties,
)
diff --git a/source/blender/blenkernel/BKE_sketch.h b/source/blender/blenkernel/BKE_sketch.h
deleted file mode 100644
index 9b9c125fbe6..00000000000
--- a/source/blender/blenkernel/BKE_sketch.h
+++ /dev/null
@@ -1,149 +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): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-#ifndef __BKE_SKETCH_H__
-#define __BKE_SKETCH_H__
-
-/** \file BKE_sketch.h
- * \ingroup bke
- */
-
-typedef enum SK_PType {
- PT_CONTINUOUS,
- PT_EXACT,
-} SK_PType;
-
-typedef enum SK_PMode {
- PT_SNAP,
- PT_PROJECT,
-} SK_PMode;
-
-typedef struct SK_Point {
- float p[3];
- short p2d[2];
- float no[3];
- float size;
- SK_PType type;
- SK_PMode mode;
-} SK_Point;
-
-typedef struct SK_Stroke {
- struct SK_Stroke *next, *prev;
-
- SK_Point *points;
- int nb_points;
- int buf_size;
- int selected;
-} SK_Stroke;
-
-#define SK_OVERDRAW_LIMIT 5
-
-typedef struct SK_Overdraw {
- SK_Stroke *target;
- int start, end;
- int count;
-} SK_Overdraw;
-
-#define SK_Stroke_BUFFER_INIT_SIZE 20
-
-typedef struct SK_DrawData {
- int mval[2];
- int previous_mval[2];
- SK_PType type;
-} SK_DrawData;
-
-typedef struct SK_Intersection {
- struct SK_Intersection *next, *prev;
- SK_Stroke *stroke;
- int before;
- int after;
- int gesture_index;
- float p[3];
- float lambda; /* used for sorting intersection points */
-} SK_Intersection;
-
-typedef struct SK_Sketch {
- ListBase strokes;
- SK_Stroke *active_stroke;
- SK_Stroke *gesture;
- SK_Point next_point;
- SK_Overdraw over;
-} SK_Sketch;
-
-
-typedef struct SK_Gesture {
- SK_Stroke *stk;
- SK_Stroke *segments;
-
- ListBase intersections;
- ListBase self_intersections;
-
- int nb_self_intersections;
- int nb_intersections;
- int nb_segments;
-} SK_Gesture;
-
-
-/************************************************/
-
-void freeSketch(SK_Sketch *sketch);
-SK_Sketch *createSketch(void);
-
-void sk_removeStroke(SK_Sketch *sketch, SK_Stroke *stk);
-
-void sk_freeStroke(SK_Stroke *stk);
-SK_Stroke *sk_createStroke(void);
-
-SK_Point *sk_lastStrokePoint(SK_Stroke *stk);
-
-void sk_allocStrokeBuffer(SK_Stroke *stk);
-void sk_shrinkStrokeBuffer(SK_Stroke *stk);
-void sk_growStrokeBuffer(SK_Stroke *stk);
-void sk_growStrokeBufferN(SK_Stroke *stk, int n);
-
-void sk_replaceStrokePoint(SK_Stroke *stk, SK_Point *pt, int n);
-void sk_insertStrokePoint(SK_Stroke *stk, SK_Point *pt, int n);
-void sk_appendStrokePoint(SK_Stroke *stk, SK_Point *pt);
-void sk_insertStrokePoints(SK_Stroke *stk, SK_Point *pts, int len, int start, int end);
-
-void sk_trimStroke(SK_Stroke *stk, int start, int end);
-void sk_straightenStroke(SK_Stroke *stk, int start, int end, float p_start[3], float p_end[3]);
-void sk_polygonizeStroke(SK_Stroke *stk, int start, int end);
-void sk_flattenStroke(SK_Stroke *stk, int start, int end);
-void sk_reverseStroke(SK_Stroke *stk);
-
-void sk_filterLastContinuousStroke(SK_Stroke *stk);
-void sk_filterStroke(SK_Stroke *stk, int start, int end);
-
-void sk_initPoint(SK_Point *pt, SK_DrawData *dd, const float no[3]);
-void sk_copyPoint(SK_Point *dst, SK_Point *src);
-
-int sk_stroke_filtermval(SK_DrawData *dd);
-void sk_endContinuousStroke(SK_Stroke *stk);
-
-void sk_updateNextPoint(SK_Sketch *sketch, SK_Stroke *stk);
-
-void sk_initDrawData(SK_DrawData *dd, const int mval[2]);
-
-void sk_deleteSelectedStrokes(SK_Sketch *sketch);
-void sk_selectAllSketch(SK_Sketch *sketch, int mode);
-
-#endif
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 4191580b0fa..d90831605b5 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -176,7 +176,6 @@ set(SRC
intern/seqmodifier.c
intern/sequencer.c
intern/shrinkwrap.c
- intern/sketch.c
intern/smoke.c
intern/softbody.c
intern/sound.c
@@ -296,7 +295,6 @@ set(SRC
BKE_screen.h
BKE_sequencer.h
BKE_shrinkwrap.h
- BKE_sketch.h
BKE_smoke.h
BKE_softbody.h
BKE_sound.h
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 6daaa10f227..d1b02695c35 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -73,7 +73,6 @@
#include "BKE_scene.h"
#include "BIK_api.h"
-#include "BKE_sketch.h"
/* **************** Generic Functions, data level *************** */
@@ -135,12 +134,6 @@ void BKE_armature_free(bArmature *arm)
MEM_freeN(arm->edbo);
arm->edbo = NULL;
}
-
- /* free sketch */
- if (arm->sketch) {
- freeSketch(arm->sketch);
- arm->sketch = NULL;
- }
}
void BKE_armature_make_local(Main *bmain, bArmature *arm, const bool lib_local)
@@ -204,7 +197,6 @@ void BKE_armature_copy_data(Main *UNUSED(bmain), bArmature *arm_dst, const bArma
arm_dst->edbo = NULL;
arm_dst->act_edbone = NULL;
- arm_dst->sketch = NULL;
}
bArmature *BKE_armature_copy(Main *bmain, const bArmature *arm)
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index 9c015cea225..ebf286c29ca 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -445,8 +445,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
}
if (toolsett) {
- CALLBACK_INVOKE(toolsett->skgen_template, IDWALK_CB_NOP);
-
CALLBACK_INVOKE(toolsett->particle.scene, IDWALK_CB_NOP);
CALLBACK_INVOKE(toolsett->particle.object, IDWALK_CB_NOP);
CALLBACK_INVOKE(toolsett->particle.shape_object, IDWALK_CB_NOP);
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 27ebbad6660..91ff3c15502 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -659,21 +659,6 @@ void BKE_scene_init(Scene *sce)
sce->toolsettings->snap_node_mode = SCE_SNAP_MODE_GRID;
- sce->toolsettings->skgen_resolution = 100;
- sce->toolsettings->skgen_threshold_internal = 0.01f;
- sce->toolsettings->skgen_threshold_external = 0.01f;
- sce->toolsettings->skgen_angle_limit = 45.0f;
- sce->toolsettings->skgen_length_ratio = 1.3f;
- sce->toolsettings->skgen_length_limit = 1.5f;
- sce->toolsettings->skgen_correlation_limit = 0.98f;
- sce->toolsettings->skgen_symmetry_limit = 0.1f;
- sce->toolsettings->skgen_postpro = SKGEN_SMOOTH;
- sce->toolsettings->skgen_postpro_passes = 1;
- sce->toolsettings->skgen_options = SKGEN_FILTER_INTERNAL | SKGEN_FILTER_EXTERNAL | SKGEN_FILTER_SMART | SKGEN_HARMONIC | SKGEN_SUB_CORRELATION | SKGEN_STICK_TO_EMBEDDING;
- sce->toolsettings->skgen_subdivisions[0] = SKGEN_SUB_CORRELATION;
- sce->toolsettings->skgen_subdivisions[1] = SKGEN_SUB_LENGTH;
- sce->toolsettings->skgen_subdivisions[2] = SKGEN_SUB_ANGLE;
-
sce->toolsettings->curve_paint_settings.curve_type = CU_BEZIER;
sce->toolsettings->curve_paint_settings.flag |= CURVE_PAINT_FLAG_CORNERS_DETECT;
sce->toolsettings->curve_paint_settings.error_threshold = 8;
diff --git a/source/blender/blenkernel/intern/sketch.c b/source/blender/blenkernel/intern/sketch.c
deleted file mode 100644
index 6f5c264f658..00000000000
--- a/source/blender/blenkernel/intern/sketch.c
+++ /dev/null
@@ -1,555 +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): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/blenkernel/intern/sketch.c
- * \ingroup bke
- */
-
-
-#include <string.h>
-#include <math.h>
-#include <float.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
-#include "BLI_utildefines.h"
-
-#include "BKE_sketch.h"
-
-
-#include "DNA_userdef_types.h"
-
-void freeSketch(SK_Sketch *sketch)
-{
- SK_Stroke *stk, *next;
-
- for (stk = sketch->strokes.first; stk; stk = next) {
- next = stk->next;
-
- sk_freeStroke(stk);
- }
-
- MEM_freeN(sketch);
-}
-
-SK_Sketch *createSketch(void)
-{
- SK_Sketch *sketch;
-
- sketch = MEM_callocN(sizeof(SK_Sketch), "SK_Sketch");
-
- sketch->active_stroke = NULL;
- sketch->gesture = NULL;
-
- BLI_listbase_clear(&sketch->strokes);
-
- return sketch;
-}
-
-void sk_initPoint(SK_Point *pt, SK_DrawData *dd, const float no[3])
-{
- if (no) {
- normalize_v3_v3(pt->no, no);
- }
- else {
- pt->no[0] = 0.0f;
- pt->no[1] = 0.0f;
- pt->no[2] = 1.0f;
- }
- pt->p2d[0] = dd->mval[0];
- pt->p2d[1] = dd->mval[1];
-
- pt->size = 0.0f;
- pt->type = PT_CONTINUOUS;
- pt->mode = PT_SNAP;
- /* more init code here */
-}
-
-void sk_copyPoint(SK_Point *dst, SK_Point *src)
-{
- memcpy(dst, src, sizeof(SK_Point));
-}
-
-void sk_allocStrokeBuffer(SK_Stroke *stk)
-{
- stk->points = MEM_callocN(sizeof(SK_Point) * stk->buf_size, "SK_Point buffer");
-}
-
-void sk_freeStroke(SK_Stroke *stk)
-{
- MEM_freeN(stk->points);
- MEM_freeN(stk);
-}
-
-SK_Stroke *sk_createStroke(void)
-{
- SK_Stroke *stk;
-
- stk = MEM_callocN(sizeof(SK_Stroke), "SK_Stroke");
-
- stk->selected = 0;
- stk->nb_points = 0;
- stk->buf_size = SK_Stroke_BUFFER_INIT_SIZE;
-
- sk_allocStrokeBuffer(stk);
-
- return stk;
-}
-
-void sk_shrinkStrokeBuffer(SK_Stroke *stk)
-{
- if (stk->nb_points < stk->buf_size) {
- SK_Point *old_points = stk->points;
-
- stk->buf_size = stk->nb_points;
-
- sk_allocStrokeBuffer(stk);
-
- memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points);
-
- MEM_freeN(old_points);
- }
-}
-
-void sk_growStrokeBuffer(SK_Stroke *stk)
-{
- if (stk->nb_points == stk->buf_size) {
- SK_Point *old_points = stk->points;
-
- stk->buf_size *= 2;
-
- sk_allocStrokeBuffer(stk);
-
- memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points);
-
- MEM_freeN(old_points);
- }
-}
-
-void sk_growStrokeBufferN(SK_Stroke *stk, int n)
-{
- if (stk->nb_points + n > stk->buf_size) {
- SK_Point *old_points = stk->points;
-
- while (stk->nb_points + n > stk->buf_size) {
- stk->buf_size *= 2;
- }
-
- sk_allocStrokeBuffer(stk);
-
- memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points);
-
- MEM_freeN(old_points);
- }
-}
-
-
-void sk_replaceStrokePoint(SK_Stroke *stk, SK_Point *pt, int n)
-{
- memcpy(stk->points + n, pt, sizeof(SK_Point));
-}
-
-void sk_insertStrokePoint(SK_Stroke *stk, SK_Point *pt, int n)
-{
- int size = stk->nb_points - n;
-
- sk_growStrokeBuffer(stk);
-
- memmove(stk->points + n + 1, stk->points + n, size * sizeof(SK_Point));
-
- memcpy(stk->points + n, pt, sizeof(SK_Point));
-
- stk->nb_points++;
-}
-
-void sk_appendStrokePoint(SK_Stroke *stk, SK_Point *pt)
-{
- sk_growStrokeBuffer(stk);
-
- memcpy(stk->points + stk->nb_points, pt, sizeof(SK_Point));
-
- stk->nb_points++;
-}
-
-void sk_insertStrokePoints(SK_Stroke *stk, SK_Point *pts, int len, int start, int end)
-{
- int size = end - start;
-
- sk_growStrokeBufferN(stk, len - size);
-
- if (len != size) {
- int tail_size = stk->nb_points - end;
-
- memmove(stk->points + start + len, stk->points + end, tail_size * sizeof(SK_Point));
- }
-
- memcpy(stk->points + start, pts, len * sizeof(SK_Point));
-
- stk->nb_points += len - size;
-}
-
-void sk_trimStroke(SK_Stroke *stk, int start, int end)
-{
- int size = end - start + 1;
-
- if (start > 0) {
- memmove(stk->points, stk->points + start, size * sizeof(SK_Point));
- }
-
- stk->nb_points = size;
-}
-
-void sk_straightenStroke(SK_Stroke *stk, int start, int end, float p_start[3], float p_end[3])
-{
- SK_Point pt1, pt2;
- SK_Point *prev, *next;
- float delta_p[3];
- int i, total;
-
- total = end - start;
-
- sub_v3_v3v3(delta_p, p_end, p_start);
-
- prev = stk->points + start;
- next = stk->points + end;
-
- copy_v3_v3(pt1.p, p_start);
- copy_v3_v3(pt1.no, prev->no);
- pt1.mode = prev->mode;
- pt1.type = prev->type;
-
- copy_v3_v3(pt2.p, p_end);
- copy_v3_v3(pt2.no, next->no);
- pt2.mode = next->mode;
- pt2.type = next->type;
-
- sk_insertStrokePoint(stk, &pt1, start + 1); /* insert after start */
- sk_insertStrokePoint(stk, &pt2, end + 1); /* insert before end (since end was pushed back already) */
-
- for (i = 1; i < total; i++) {
- float delta = (float)i / (float)total;
- float *p = stk->points[start + 1 + i].p;
-
- mul_v3_v3fl(p, delta_p, delta);
- add_v3_v3(p, p_start);
- }
-}
-
-void sk_polygonizeStroke(SK_Stroke *stk, int start, int end)
-{
- int offset;
- int i;
-
- /* find first exact points outside of range */
- for (; start > 0; start--) {
- if (stk->points[start].type == PT_EXACT) {
- break;
- }
- }
-
- for (; end < stk->nb_points - 1; end++) {
- if (stk->points[end].type == PT_EXACT) {
- break;
- }
- }
-
- offset = start + 1;
-
- for (i = start + 1; i < end; i++) {
- if (stk->points[i].type == PT_EXACT) {
- if (offset != i) {
- memcpy(stk->points + offset, stk->points + i, sizeof(SK_Point));
- }
-
- offset++;
- }
- }
-
- /* some points were removes, move end of array */
- if (offset < end) {
- int size = stk->nb_points - end;
- memmove(stk->points + offset, stk->points + end, size * sizeof(SK_Point));
- stk->nb_points = offset + size;
- }
-}
-
-void sk_flattenStroke(SK_Stroke *stk, int start, int end)
-{
- float normal[3], distance[3];
- float limit;
- int i, total;
-
- total = end - start + 1;
-
- copy_v3_v3(normal, stk->points[start].no);
-
- sub_v3_v3v3(distance, stk->points[end].p, stk->points[start].p);
- project_v3_v3v3(normal, distance, normal);
- limit = normalize_v3(normal);
-
- for (i = 1; i < total - 1; i++) {
- float d = limit * i / total;
- float offset[3];
- float *p = stk->points[start + i].p;
-
- sub_v3_v3v3(distance, p, stk->points[start].p);
- project_v3_v3v3(distance, distance, normal);
-
- copy_v3_v3(offset, normal);
- mul_v3_fl(offset, d);
-
- sub_v3_v3(p, distance);
- add_v3_v3(p, offset);
- }
-}
-
-void sk_removeStroke(SK_Sketch *sketch, SK_Stroke *stk)
-{
- if (sketch->active_stroke == stk) {
- sketch->active_stroke = NULL;
- }
-
- BLI_remlink(&sketch->strokes, stk);
- sk_freeStroke(stk);
-}
-
-void sk_reverseStroke(SK_Stroke *stk)
-{
- SK_Point *old_points = stk->points;
- int i = 0;
-
- sk_allocStrokeBuffer(stk);
-
- for (i = 0; i < stk->nb_points; i++) {
- sk_copyPoint(stk->points + i, old_points + stk->nb_points - 1 - i);
- }
-
- MEM_freeN(old_points);
-}
-
-
-/* Ramer-Douglas-Peucker algorithm for line simplification */
-void sk_filterStroke(SK_Stroke *stk, int start, int end)
-{
- SK_Point *old_points = stk->points;
- int nb_points = stk->nb_points;
- char *marked = NULL;
- char work;
- int i;
-
- if (start == -1) {
- start = 0;
- end = stk->nb_points - 1;
- }
-
- sk_allocStrokeBuffer(stk);
- stk->nb_points = 0;
-
- /* adding points before range */
- for (i = 0; i < start; i++) {
- sk_appendStrokePoint(stk, old_points + i);
- }
-
- marked = MEM_callocN(nb_points, "marked array");
- marked[start] = 1;
- marked[end] = 1;
-
- work = 1;
-
- /* while still reducing */
- while (work) {
- int ls, le;
- work = 0;
-
- ls = start;
- le = start + 1;
-
- /* while not over interval */
- while (ls < end) {
- int max_i = 0;
- short v1[2];
- float max_dist = 16; /* more than 4 pixels */
-
- /* find the next marked point */
- while (marked[le] == 0) {
- le++;
- }
-
- /* perpendicular vector to ls-le */
- v1[1] = old_points[le].p2d[0] - old_points[ls].p2d[0];
- v1[0] = old_points[ls].p2d[1] - old_points[le].p2d[1];
-
-
- for (i = ls + 1; i < le; i++) {
- float mul;
- float dist;
- short v2[2];
-
- v2[0] = old_points[i].p2d[0] - old_points[ls].p2d[0];
- v2[1] = old_points[i].p2d[1] - old_points[ls].p2d[1];
-
- if (v2[0] == 0 && v2[1] == 0) {
- continue;
- }
-
- mul = (float)(v1[0] * v2[0] + v1[1] * v2[1]) / (float)(v2[0] * v2[0] + v2[1] * v2[1]);
-
- dist = mul * mul * (v2[0] * v2[0] + v2[1] * v2[1]);
-
- if (dist > max_dist) {
- max_dist = dist;
- max_i = i;
- }
- }
-
- if (max_i != 0) {
- work = 1;
- marked[max_i] = 1;
- }
-
- ls = le;
- le = ls + 1;
- }
- }
-
-
- /* adding points after range */
- for (i = start; i <= end; i++) {
- if (marked[i]) {
- sk_appendStrokePoint(stk, old_points + i);
- }
- }
-
- MEM_freeN(marked);
-
- /* adding points after range */
- for (i = end + 1; i < nb_points; i++) {
- sk_appendStrokePoint(stk, old_points + i);
- }
-
- MEM_freeN(old_points);
-
- sk_shrinkStrokeBuffer(stk);
-}
-
-
-void sk_filterLastContinuousStroke(SK_Stroke *stk)
-{
- int start, end;
-
- end = stk->nb_points - 1;
-
- for (start = end - 1; start > 0 && stk->points[start].type == PT_CONTINUOUS; start--) {
- /* nothing to do here*/
- }
-
- if (end - start > 1) {
- sk_filterStroke(stk, start, end);
- }
-}
-
-SK_Point *sk_lastStrokePoint(SK_Stroke *stk)
-{
- SK_Point *pt = NULL;
-
- if (stk->nb_points > 0) {
- pt = stk->points + (stk->nb_points - 1);
- }
-
- return pt;
-}
-
-void sk_endContinuousStroke(SK_Stroke *stk)
-{
- stk->points[stk->nb_points - 1].type = PT_EXACT;
-}
-
-void sk_updateNextPoint(SK_Sketch *sketch, SK_Stroke *stk)
-{
- if (stk) {
- memcpy(&(sketch->next_point), &(stk->points[stk->nb_points - 1]), sizeof(SK_Point));
- }
-}
-
-int sk_stroke_filtermval(SK_DrawData *dd)
-{
- int retval = 0;
- if (ABS(dd->mval[0] - dd->previous_mval[0]) + ABS(dd->mval[1] - dd->previous_mval[1]) > U.gp_manhattendist) {
- retval = 1;
- }
-
- return retval;
-}
-
-void sk_initDrawData(SK_DrawData *dd, const int mval[2])
-{
- dd->mval[0] = mval[0];
- dd->mval[1] = mval[1];
- dd->previous_mval[0] = -1;
- dd->previous_mval[1] = -1;
- dd->type = PT_EXACT;
-}
-
-
-void sk_deleteSelectedStrokes(SK_Sketch *sketch)
-{
- SK_Stroke *stk, *next;
-
- for (stk = sketch->strokes.first; stk; stk = next) {
- next = stk->next;
-
- if (stk->selected == 1) {
- sk_removeStroke(sketch, stk);
- }
- }
-}
-
-void sk_selectAllSketch(SK_Sketch *sketch, int mode)
-{
- SK_Stroke *stk = NULL;
-
- if (mode == -1) {
- for (stk = sketch->strokes.first; stk; stk = stk->next) {
- stk->selected = 0;
- }
- }
- else if (mode == 0) {
- for (stk = sketch->strokes.first; stk; stk = stk->next) {
- stk->selected = 1;
- }
- }
- else if (mode == 1) {
- int selected = 1;
-
- for (stk = sketch->strokes.first; stk; stk = stk->next) {
- selected &= stk->selected;
- }
-
- selected ^= 1;
-
- for (stk = sketch->strokes.first; stk; stk = stk->next) {
- stk->selected = selected;
- }
- }
-}
diff --git a/source/blender/blenlib/BLI_graph.h b/source/blender/blenlib/BLI_graph.h
deleted file mode 100644
index 7936f5a6fab..00000000000
--- a/source/blender/blenlib/BLI_graph.h
+++ /dev/null
@@ -1,185 +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.
- *
- * The Original Code is Copyright (C) 2008 Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): Joshua Leung
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-#ifndef __BLI_GRAPH_H__
-#define __BLI_GRAPH_H__
-
-/** \file BLI_graph.h
- * \ingroup bli
- */
-
-#include "DNA_listBase.h"
-
-struct BGraph;
-struct BNode;
-struct BArc;
-
-struct RadialArc;
-
-typedef void (*FreeArc)(struct BArc *);
-typedef void (*FreeNode)(struct BNode *);
-typedef void (*RadialSymmetry)(struct BNode *root_node, struct RadialArc *ring, int total);
-typedef void (*AxialSymmetry)(struct BNode *root_node, struct BNode *node1, struct BNode *node2, struct BArc *arc1, struct BArc *arc2);
-
-/* IF YOU MODIFY THOSE TYPES, YOU NEED TO UPDATE ALL THOSE THAT "INHERIT" FROM THEM
- *
- * RigGraph, ReebGraph
- *
- * */
-
-typedef struct BGraph {
- ListBase arcs;
- ListBase nodes;
-
- float length;
-
- /* function pointer to deal with custom fonctionnality */
- FreeArc free_arc;
- FreeNode free_node;
- RadialSymmetry radial_symmetry;
- AxialSymmetry axial_symmetry;
-} BGraph;
-
-typedef struct BNode {
- 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];
-} BNode;
-
-typedef struct BArc {
- void *next, *prev;
- struct BNode *head, *tail;
- int flag;
-
- float length;
-
- int symmetry_level;
- int symmetry_group;
- int symmetry_flag;
-} BArc;
-
-struct BArcIterator;
-
-void *IT_head(void *iter);
-void *IT_tail(void *iter);
-void *IT_peek(void *iter, int n);
-void *IT_next(void *iter);
-void *IT_nextN(void *iter, int n);
-void *IT_previous(void *iter);
-int IT_stopped(void *iter);
-
-typedef void * (*HeadFct)(void *iter);
-typedef void * (*TailFct)(void *iter);
-typedef void * (*PeekFct)(void *iter, int n);
-typedef void * (*NextFct)(void *iter);
-typedef void * (*NextNFct)(void *iter, int n);
-typedef void * (*PreviousFct)(void *iter);
-typedef int (*StoppedFct)(void *iter);
-
-typedef struct BArcIterator {
- HeadFct head;
- TailFct tail;
- PeekFct peek;
- NextFct next;
- NextNFct nextN;
- PreviousFct previous;
- StoppedFct stopped;
-
- float *p, *no;
- float size;
-
- int length;
- int index;
-} BArcIterator;
-
-/* Helper structure for radial symmetry */
-typedef struct RadialArc {
- struct BArc *arc;
- float n[3]; /* normalized vector joining the nodes of the arc */
-} RadialArc;
-
-BNode *BLI_otherNode(BArc *arc, BNode *node);
-
-void BLI_freeNode(BGraph *graph, BNode *node);
-void BLI_removeNode(BGraph *graph, BNode *node);
-
-void BLI_removeArc(BGraph *graph, BArc *arc);
-
-void BLI_flagNodes(BGraph *graph, int flag);
-void BLI_flagArcs(BGraph *graph, int flag);
-
-bool BLI_hasAdjacencyList(BGraph *rg);
-void BLI_buildAdjacencyList(BGraph *rg);
-void BLI_rebuildAdjacencyListForNode(BGraph *rg, BNode *node);
-void BLI_freeAdjacencyList(BGraph *rg);
-
-int BLI_FlagSubgraphs(BGraph *graph);
-void BLI_ReflagSubgraph(BGraph *graph, int old_subgraph, int new_subgraph);
-
-#define SHAPE_RADIX 10 /* each shape level is encoded this base */
-
-int BLI_subtreeShape(BGraph *graph, BNode *node, BArc *rootArc, int include_root);
-float BLI_subtreeLength(BNode *node);
-void BLI_calcGraphLength(BGraph *graph);
-
-void BLI_replaceNode(BGraph *graph, BNode *node_src, BNode *node_replaced);
-void BLI_replaceNodeInArc(BGraph *graph, BArc *arc, BNode *node_src, BNode *node_replaced);
-void BLI_removeDoubleNodes(BGraph *graph, float limit);
-BNode *BLI_FindNodeByPosition(BGraph *graph, const float p[3], const float limit);
-
-BArc *BLI_findConnectedArc(BGraph *graph, BArc *arc, BNode *v);
-
-bool BLI_isGraphCyclic(BGraph *graph);
-
-/*------------ Symmetry handling ------------*/
-void BLI_markdownSymmetry(BGraph *graph, BNode *root_node, float limit);
-
-void BLI_mirrorAlongAxis(float v[3], float center[3], float axis[3]);
-
-/* BNode symmetry flags */
-#define SYM_TOPOLOGICAL 1
-#define SYM_PHYSICAL 2
-
-/* the following two are exclusive */
-#define SYM_AXIAL 4
-#define SYM_RADIAL 8
-
-/* BArc symmetry flags
- *
- * axial symmetry sides */
-#define SYM_SIDE_POSITIVE 1
-#define SYM_SIDE_NEGATIVE 2
-/* Anything higher is the order in radial symmetry */
-#define SYM_SIDE_RADIAL 3
-
-#endif /*__BLI_GRAPH_H__*/
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 80a8ef96eb3..31abf258d0f 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -71,7 +71,6 @@ set(SRC
intern/fileops.c
intern/fnmatch.c
intern/freetypefont.c
- intern/graph.c
intern/gsqueue.c
intern/hash_md5.c
intern/hash_mm2a.c
@@ -154,7 +153,6 @@ set(SRC
BLI_fileops_types.h
BLI_fnmatch.h
BLI_ghash.h
- BLI_graph.h
BLI_gsqueue.h
BLI_hash.h
BLI_hash_md5.h
diff --git a/source/blender/blenlib/intern/graph.c b/source/blender/blenlib/intern/graph.c
deleted file mode 100644
index 911e8aae340..00000000000
--- a/source/blender/blenlib/intern/graph.c
+++ /dev/null
@@ -1,1016 +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 *****
- * graph.c: Common graph interface and methods
- */
-
-/** \file blender/blenlib/intern/graph.c
- * \ingroup bli
- */
-
-#include <float.h>
-#include <math.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_utildefines.h"
-#include "BLI_listbase.h"
-#include "BLI_graph.h"
-#include "BLI_math.h"
-
-
-static void testRadialSymmetry(BGraph *graph, BNode *root_node, RadialArc *ring, int total, float axis[3], float limit, int group);
-
-static void handleAxialSymmetry(BGraph *graph, BNode *root_node, int depth, float axis[3], float limit);
-static void testAxialSymmetry(BGraph *graph, BNode *root_node, BNode *node1, BNode *node2, BArc *arc1, BArc *arc2, float axis[3], float limit, int group);
-static void flagAxialSymmetry(BNode *root_node, BNode *end_node, BArc *arc, int group);
-
-void BLI_freeNode(BGraph *graph, BNode *node)
-{
- if (node->arcs) {
- MEM_freeN(node->arcs);
- }
-
- if (graph->free_node) {
- graph->free_node(node);
- }
-}
-
-void BLI_removeNode(BGraph *graph, BNode *node)
-{
- BLI_freeNode(graph, node);
- BLI_freelinkN(&graph->nodes, node);
-}
-
-BNode *BLI_otherNode(BArc *arc, BNode *node)
-{
- return (arc->head == node) ? arc->tail : arc->head;
-}
-
-void BLI_removeArc(BGraph *graph, BArc *arc)
-{
- if (graph->free_arc) {
- graph->free_arc(arc);
- }
-
- BLI_freelinkN(&graph->arcs, arc);
-}
-
-void BLI_flagNodes(BGraph *graph, int flag)
-{
- BNode *node;
-
- for (node = graph->nodes.first; node; node = node->next) {
- node->flag = flag;
- }
-}
-
-void BLI_flagArcs(BGraph *graph, int flag)
-{
- BArc *arc;
-
- for (arc = graph->arcs.first; arc; arc = arc->next) {
- arc->flag = flag;
- }
-}
-
-static void addArcToNodeAdjacencyList(BNode *node, BArc *arc)
-{
- node->arcs[node->flag] = arc;
- node->flag++;
-}
-
-void BLI_buildAdjacencyList(BGraph *graph)
-{
- BNode *node;
- BArc *arc;
-
- for (node = graph->nodes.first; node; node = node->next) {
- if (node->arcs != NULL) {
- MEM_freeN(node->arcs);
- }
-
- node->arcs = MEM_callocN((node->degree) * sizeof(BArc *), "adjacency list");
-
- /* temporary use to indicate the first index available in the lists */
- node->flag = 0;
- }
-
- for (arc = graph->arcs.first; arc; arc = arc->next) {
- addArcToNodeAdjacencyList(arc->head, arc);
- addArcToNodeAdjacencyList(arc->tail, arc);
- }
-
- for (node = graph->nodes.first; node; node = node->next) {
- if (node->degree != node->flag) {
- printf("error in node [%p]. Added only %i arcs out of %i\n", (void *)node, node->flag, node->degree);
- }
- }
-}
-
-void BLI_rebuildAdjacencyListForNode(BGraph *graph, BNode *node)
-{
- BArc *arc;
-
- if (node->arcs != NULL) {
- MEM_freeN(node->arcs);
- }
-
- node->arcs = MEM_callocN((node->degree) * sizeof(BArc *), "adjacency list");
-
- /* temporary use to indicate the first index available in the lists */
- node->flag = 0;
-
- for (arc = graph->arcs.first; arc; arc = arc->next) {
- if (arc->head == node) {
- addArcToNodeAdjacencyList(arc->head, arc);
- }
- else if (arc->tail == node) {
- addArcToNodeAdjacencyList(arc->tail, arc);
- }
- }
-
- if (node->degree != node->flag) {
- printf("error in node [%p]. Added only %i arcs out of %i\n", (void *)node, node->flag, node->degree);
- }
-}
-
-void BLI_freeAdjacencyList(BGraph *graph)
-{
- BNode *node;
-
- for (node = graph->nodes.first; node; node = node->next) {
- if (node->arcs != NULL) {
- MEM_freeN(node->arcs);
- node->arcs = NULL;
- }
- }
-}
-
-bool BLI_hasAdjacencyList(BGraph *graph)
-{
- BNode *node;
-
- for (node = graph->nodes.first; node; node = node->next) {
- if (node->arcs == NULL) {
- return false;
- }
- }
-
- return true;
-}
-
-void BLI_replaceNodeInArc(BGraph *graph, BArc *arc, BNode *node_src, BNode *node_replaced)
-{
- if (arc->head == node_replaced) {
- arc->head = node_src;
- node_src->degree++;
- }
-
- if (arc->tail == node_replaced) {
- arc->tail = node_src;
- node_src->degree++;
- }
-
- if (arc->head == arc->tail) {
- node_src->degree -= 2;
-
- graph->free_arc(arc);
- BLI_freelinkN(&graph->arcs, arc);
- }
-
- if (node_replaced->degree == 0) {
- BLI_removeNode(graph, node_replaced);
- }
-}
-
-void BLI_replaceNode(BGraph *graph, BNode *node_src, BNode *node_replaced)
-{
- BArc *arc, *next_arc;
-
- for (arc = graph->arcs.first; arc; arc = next_arc) {
- next_arc = arc->next;
-
- if (arc->head == node_replaced) {
- arc->head = node_src;
- node_replaced->degree--;
- node_src->degree++;
- }
-
- if (arc->tail == node_replaced) {
- arc->tail = node_src;
- node_replaced->degree--;
- node_src->degree++;
- }
-
- if (arc->head == arc->tail) {
- node_src->degree -= 2;
-
- graph->free_arc(arc);
- BLI_freelinkN(&graph->arcs, arc);
- }
- }
-
- if (node_replaced->degree == 0) {
- BLI_removeNode(graph, node_replaced);
- }
-}
-
-void BLI_removeDoubleNodes(BGraph *graph, float limit)
-{
- const float limit_sq = limit * limit;
- BNode *node_src, *node_replaced;
-
- for (node_src = graph->nodes.first; node_src; node_src = node_src->next) {
- for (node_replaced = graph->nodes.first; node_replaced; node_replaced = node_replaced->next) {
- if (node_replaced != node_src && len_squared_v3v3(node_replaced->p, node_src->p) <= limit_sq) {
- BLI_replaceNode(graph, node_src, node_replaced);
- }
- }
- }
-
-}
-
-BNode *BLI_FindNodeByPosition(BGraph *graph, const float p[3], const float limit)
-{
- const float limit_sq = limit * limit;
- BNode *closest_node = NULL, *node;
- float min_distance = 0.0f;
-
- for (node = graph->nodes.first; node; node = node->next) {
- float distance = len_squared_v3v3(p, node->p);
- if (distance <= limit_sq && (closest_node == NULL || distance < min_distance)) {
- closest_node = node;
- min_distance = distance;
- }
- }
-
- return closest_node;
-}
-/************************************* SUBGRAPH DETECTION **********************************************/
-
-static void flagSubgraph(BNode *node, int subgraph)
-{
- if (node->subgraph_index == 0) {
- BArc *arc;
- int i;
-
- node->subgraph_index = subgraph;
-
- for (i = 0; i < node->degree; i++) {
- arc = node->arcs[i];
- flagSubgraph(BLI_otherNode(arc, node), subgraph);
- }
- }
-}
-
-int BLI_FlagSubgraphs(BGraph *graph)
-{
- BNode *node;
- int subgraph = 0;
-
- if (BLI_hasAdjacencyList(graph) == 0) {
- BLI_buildAdjacencyList(graph);
- }
-
- for (node = graph->nodes.first; node; node = node->next) {
- node->subgraph_index = 0;
- }
-
- for (node = graph->nodes.first; node; node = node->next) {
- if (node->subgraph_index == 0) {
- subgraph++;
- flagSubgraph(node, subgraph);
- }
- }
-
- return subgraph;
-}
-
-void BLI_ReflagSubgraph(BGraph *graph, int old_subgraph, int new_subgraph)
-{
- BNode *node;
-
- for (node = graph->nodes.first; node; node = node->next) {
- if (node->flag == old_subgraph) {
- node->flag = new_subgraph;
- }
- }
-}
-
-/*************************************** CYCLE DETECTION ***********************************************/
-
-static bool detectCycle(BNode *node, BArc *src_arc)
-{
- bool value = false;
-
- if (node->flag == 0) {
- int i;
-
- /* mark node as visited */
- node->flag = 1;
-
- for (i = 0; i < node->degree && value == 0; i++) {
- BArc *arc = node->arcs[i];
-
- /* don't go back on the source arc */
- if (arc != src_arc) {
- value = detectCycle(BLI_otherNode(arc, node), arc);
- }
- }
- }
- else {
- value = true;
- }
-
- return value;
-}
-
-bool BLI_isGraphCyclic(BGraph *graph)
-{
- BNode *node;
- bool value = false;
-
- /* NEED TO CHECK IF ADJACENCY LIST EXIST */
-
- /* Mark all nodes as not visited */
- BLI_flagNodes(graph, 0);
-
- /* detectCycles in subgraphs */
- for (node = graph->nodes.first; node && value == false; node = node->next) {
- /* only for nodes in subgraphs that haven't been visited yet */
- if (node->flag == 0) {
- value = value || detectCycle(node, NULL);
- }
- }
-
- return value;
-}
-
-BArc *BLI_findConnectedArc(BGraph *graph, BArc *arc, BNode *v)
-{
- BArc *nextArc;
-
- for (nextArc = graph->arcs.first; nextArc; nextArc = nextArc->next) {
- if (arc != nextArc && (nextArc->head == v || nextArc->tail == v)) {
- break;
- }
- }
-
- return nextArc;
-}
-
-/*********************************** GRAPH AS TREE FUNCTIONS *******************************************/
-
-static int subtreeShape(BNode *node, BArc *rootArc, int include_root)
-{
- int depth = 0;
-
- node->flag = 1;
-
- if (include_root) {
- BNode *newNode = BLI_otherNode(rootArc, node);
- return subtreeShape(newNode, rootArc, 0);
- }
- else {
- /* Base case, no arcs leading away */
- if (node->arcs == NULL || *(node->arcs) == NULL) {
- return 0;
- }
- else {
- int i;
-
- for (i = 0; i < node->degree; i++) {
- BArc *arc = node->arcs[i];
- BNode *newNode = BLI_otherNode(arc, node);
-
- /* stop immediate and cyclic backtracking */
- if (arc != rootArc && newNode->flag == 0) {
- depth += subtreeShape(newNode, arc, 0);
- }
- }
- }
-
- return SHAPE_RADIX * depth + 1;
- }
-}
-
-int BLI_subtreeShape(BGraph *graph, BNode *node, BArc *rootArc, int include_root)
-{
- BLI_flagNodes(graph, 0);
- return subtreeShape(node, rootArc, include_root);
-}
-
-float BLI_subtreeLength(BNode *node)
-{
- float length = 0;
- int i;
-
- node->flag = 0; /* flag node as visited */
-
- for (i = 0; i < node->degree; i++) {
- BArc *arc = node->arcs[i];
- BNode *other_node = BLI_otherNode(arc, node);
-
- if (other_node->flag != 0) {
- float subgraph_length = arc->length + BLI_subtreeLength(other_node);
- length = MAX2(length, subgraph_length);
- }
- }
-
- return length;
-}
-
-void BLI_calcGraphLength(BGraph *graph)
-{
- float length = 0;
- int nb_subgraphs;
- int i;
-
- nb_subgraphs = BLI_FlagSubgraphs(graph);
-
- for (i = 1; i <= nb_subgraphs; i++) {
- BNode *node;
-
- for (node = graph->nodes.first; node; node = node->next) {
- /* start on an external node of the subgraph */
- if (node->subgraph_index == i && node->degree == 1) {
- float subgraph_length = BLI_subtreeLength(node);
- length = MAX2(length, subgraph_length);
- break;
- }
- }
- }
-
- graph->length = length;
-}
-
-/********************************* SYMMETRY DETECTION **************************************************/
-
-static void markdownSymmetryArc(BGraph *graph, BArc *arc, BNode *node, int level, float limit);
-
-void BLI_mirrorAlongAxis(float v[3], float center[3], float axis[3])
-{
- float dv[3], pv[3];
-
- sub_v3_v3v3(dv, v, center);
- project_v3_v3v3(pv, dv, axis);
- mul_v3_fl(pv, -2);
- add_v3_v3(v, pv);
-}
-
-static void testRadialSymmetry(BGraph *graph, BNode *root_node, RadialArc *ring, int total, float axis[3], float limit, int group)
-{
- const float limit_sq = limit * limit;
- int symmetric = 1;
- int i;
-
- /* sort ring by angle */
- for (i = 0; i < total - 1; i++) {
- float minAngle = FLT_MAX;
- int minIndex = -1;
- int j;
-
- for (j = i + 1; j < total; j++) {
- float angle = dot_v3v3(ring[i].n, ring[j].n);
-
- /* map negative values to 1..2 */
- if (angle < 0) {
- angle = 1 - angle;
- }
-
- if (angle < minAngle) {
- minIndex = j;
- minAngle = angle;
- }
- }
-
- /* swap if needed */
- if (minIndex != i + 1) {
- RadialArc tmp;
- tmp = ring[i + 1];
- ring[i + 1] = ring[minIndex];
- ring[minIndex] = tmp;
- }
- }
-
- for (i = 0; i < total && symmetric; i++) {
- BNode *node1, *node2;
- float tangent[3];
- float normal[3];
- float p[3];
- int j = (i + 1) % total; /* next arc in the circular list */
-
- add_v3_v3v3(tangent, ring[i].n, ring[j].n);
- cross_v3_v3v3(normal, tangent, axis);
-
- node1 = BLI_otherNode(ring[i].arc, root_node);
- node2 = BLI_otherNode(ring[j].arc, root_node);
-
- copy_v3_v3(p, node2->p);
- BLI_mirrorAlongAxis(p, root_node->p, normal);
-
- /* check if it's within limit before continuing */
- if (len_squared_v3v3(node1->p, p) > limit_sq) {
- symmetric = 0;
- }
-
- }
-
- if (symmetric) {
- /* mark node as symmetric physically */
- copy_v3_v3(root_node->symmetry_axis, axis);
- root_node->symmetry_flag |= SYM_PHYSICAL;
- root_node->symmetry_flag |= SYM_RADIAL;
-
- /* FLAG SYMMETRY GROUP */
- for (i = 0; i < total; i++) {
- ring[i].arc->symmetry_group = group;
- ring[i].arc->symmetry_flag = SYM_SIDE_RADIAL + i;
- }
-
- if (graph->radial_symmetry) {
- graph->radial_symmetry(root_node, ring, total);
- }
- }
-}
-
-static void handleRadialSymmetry(BGraph *graph, BNode *root_node, int depth, float axis[3], float limit)
-{
- RadialArc *ring = NULL;
- RadialArc *unit;
- int total = 0;
- int group;
- int first;
- int i;
-
- /* mark topological symmetry */
- root_node->symmetry_flag |= SYM_TOPOLOGICAL;
-
- /* total the number of arcs in the symmetry ring */
- for (i = 0; i < root_node->degree; i++) {
- BArc *connectedArc = root_node->arcs[i];
-
- /* depth is store as a negative in flag. symmetry level is positive */
- if (connectedArc->symmetry_level == -depth) {
- total++;
- }
- }
-
- ring = MEM_callocN(sizeof(RadialArc) * total, "radial symmetry ring");
- unit = ring;
-
- /* fill in the ring */
- for (i = 0; i < root_node->degree; i++) {
- BArc *connectedArc = root_node->arcs[i];
-
- /* depth is store as a negative in flag. symmetry level is positive */
- if (connectedArc->symmetry_level == -depth) {
- BNode *otherNode = BLI_otherNode(connectedArc, root_node);
- float vec[3];
-
- unit->arc = connectedArc;
-
- /* project the node to node vector on the symmetry plane */
- sub_v3_v3v3(unit->n, otherNode->p, root_node->p);
- project_v3_v3v3(vec, unit->n, axis);
- sub_v3_v3v3(unit->n, unit->n, vec);
-
- normalize_v3(unit->n);
-
- unit++;
- }
- }
-
- /* sort ring by arc length
- * using a rather bogus insertion sort
- * but rings will never get too big to matter
- * */
- for (i = 0; i < total; i++) {
- int j;
-
- for (j = i - 1; j >= 0; j--) {
- BArc *arc1, *arc2;
-
- arc1 = ring[j].arc;
- arc2 = ring[j + 1].arc;
-
- if (arc1->length > arc2->length) {
- /* swap with smaller */
- RadialArc tmp;
-
- tmp = ring[j + 1];
- ring[j + 1] = ring[j];
- ring[j] = tmp;
- }
- else {
- break;
- }
- }
- }
-
- /* Dispatch to specific symmetry tests */
- first = 0;
- group = 0;
-
- for (i = 1; i < total; i++) {
- int dispatch = 0;
- int last = i - 1;
-
- if (fabsf(ring[first].arc->length - ring[i].arc->length) > limit) {
- dispatch = 1;
- }
-
- /* if not dispatching already and on last arc
- * Dispatch using current arc as last
- */
- if (dispatch == 0 && i == total - 1) {
- last = i;
- dispatch = 1;
- }
-
- if (dispatch) {
- int sub_total = last - first + 1;
-
- group += 1;
-
- if (sub_total == 1) {
- group -= 1; /* not really a group so decrement */
- /* NOTHING TO DO */
- }
- else if (sub_total == 2) {
- BArc *arc1, *arc2;
- BNode *node1, *node2;
-
- arc1 = ring[first].arc;
- arc2 = ring[last].arc;
-
- node1 = BLI_otherNode(arc1, root_node);
- node2 = BLI_otherNode(arc2, root_node);
-
- testAxialSymmetry(graph, root_node, node1, node2, arc1, arc2, axis, limit, group);
- }
- else if (sub_total != total) /* allocate a new sub ring if needed */ {
- RadialArc *sub_ring = MEM_callocN(sizeof(RadialArc) * sub_total, "radial symmetry ring");
- int sub_i;
-
- /* fill in the sub ring */
- for (sub_i = 0; sub_i < sub_total; sub_i++) {
- sub_ring[sub_i] = ring[first + sub_i];
- }
-
- testRadialSymmetry(graph, root_node, sub_ring, sub_total, axis, limit, group);
-
- MEM_freeN(sub_ring);
- }
- else if (sub_total == total) {
- testRadialSymmetry(graph, root_node, ring, total, axis, limit, group);
- }
-
- first = i;
- }
- }
-
-
- MEM_freeN(ring);
-}
-
-static void flagAxialSymmetry(BNode *root_node, BNode *end_node, BArc *arc, int group)
-{
- float vec[3];
-
- arc->symmetry_group = group;
-
- sub_v3_v3v3(vec, end_node->p, root_node->p);
-
- if (dot_v3v3(vec, root_node->symmetry_axis) < 0) {
- arc->symmetry_flag |= SYM_SIDE_NEGATIVE;
- }
- else {
- arc->symmetry_flag |= SYM_SIDE_POSITIVE;
- }
-}
-
-static void testAxialSymmetry(BGraph *graph, BNode *root_node, BNode *node1, BNode *node2, BArc *arc1, BArc *arc2, float axis[3], float limit, int group)
-{
- const float limit_sq = limit * limit;
- float nor[3], vec[3], p[3];
-
- sub_v3_v3v3(p, node1->p, root_node->p);
- cross_v3_v3v3(nor, p, axis);
-
- sub_v3_v3v3(p, root_node->p, node2->p);
- cross_v3_v3v3(vec, p, axis);
- add_v3_v3(vec, nor);
-
- cross_v3_v3v3(nor, vec, axis);
-
- if (fabsf(nor[0]) > fabsf(nor[1]) && fabsf(nor[0]) > fabsf(nor[2]) && nor[0] < 0) {
- negate_v3(nor);
- }
- else if (fabsf(nor[1]) > fabsf(nor[0]) && fabsf(nor[1]) > fabsf(nor[2]) && nor[1] < 0) {
- negate_v3(nor);
- }
- else if (fabsf(nor[2]) > fabsf(nor[1]) && fabsf(nor[2]) > fabsf(nor[0]) && nor[2] < 0) {
- negate_v3(nor);
- }
-
- /* mirror node2 along axis */
- copy_v3_v3(p, node2->p);
- BLI_mirrorAlongAxis(p, root_node->p, nor);
-
- /* check if it's within limit before continuing */
- if (len_squared_v3v3(node1->p, p) <= limit_sq) {
- /* mark node as symmetric physically */
- copy_v3_v3(root_node->symmetry_axis, nor);
- root_node->symmetry_flag |= SYM_PHYSICAL;
- root_node->symmetry_flag |= SYM_AXIAL;
-
- /* flag side on arcs */
- flagAxialSymmetry(root_node, node1, arc1, group);
- flagAxialSymmetry(root_node, node2, arc2, group);
-
- if (graph->axial_symmetry) {
- graph->axial_symmetry(root_node, node1, node2, arc1, arc2);
- }
- }
- else {
- /* NOT SYMMETRIC */
- }
-}
-
-static void handleAxialSymmetry(BGraph *graph, BNode *root_node, int depth, float axis[3], float limit)
-{
- BArc *arc1 = NULL, *arc2 = NULL;
- BNode *node1 = NULL, *node2 = NULL;
- int i;
-
- /* mark topological symmetry */
- root_node->symmetry_flag |= SYM_TOPOLOGICAL;
-
- for (i = 0; i < root_node->degree; i++) {
- BArc *connectedArc = root_node->arcs[i];
-
- /* depth is store as a negative in flag. symmetry level is positive */
- if (connectedArc->symmetry_level == -depth) {
- if (arc1 == NULL) {
- arc1 = connectedArc;
- node1 = BLI_otherNode(arc1, root_node);
- }
- else {
- arc2 = connectedArc;
- node2 = BLI_otherNode(arc2, root_node);
- break; /* Can stop now, the two arcs have been found */
- }
- }
- }
-
- /* shouldn't happen, but just to be sure */
- if (node1 == NULL || node2 == NULL) {
- return;
- }
-
- testAxialSymmetry(graph, root_node, node1, node2, arc1, arc2, axis, limit, 1);
-}
-
-static void markdownSecondarySymmetry(BGraph *graph, BNode *node, int depth, int level, float limit)
-{
- float axis[3] = {0, 0, 0};
- int count = 0;
- int i;
-
- /* count the number of branches in this symmetry group
- * and determinate the axis of symmetry
- */
- for (i = 0; i < node->degree; i++) {
- BArc *connectedArc = node->arcs[i];
-
- /* depth is store as a negative in flag. symmetry level is positive */
- if (connectedArc->symmetry_level == -depth) {
- count++;
- }
- /* If arc is on the axis */
- else if (connectedArc->symmetry_level == level) {
- add_v3_v3(axis, connectedArc->head->p);
- sub_v3_v3v3(axis, axis, connectedArc->tail->p);
- }
- }
-
- normalize_v3(axis);
-
- /* Split between axial and radial symmetry */
- if (count == 2) {
- handleAxialSymmetry(graph, node, depth, axis, limit);
- }
- else {
- handleRadialSymmetry(graph, node, depth, axis, limit);
- }
-
- /* markdown secondary symetries */
- for (i = 0; i < node->degree; i++) {
- BArc *connectedArc = node->arcs[i];
-
- if (connectedArc->symmetry_level == -depth) {
- /* markdown symmetry for branches corresponding to the depth */
- markdownSymmetryArc(graph, connectedArc, node, level + 1, limit);
- }
- }
-}
-
-static void markdownSymmetryArc(BGraph *graph, BArc *arc, BNode *node, int level, float limit)
-{
- int i;
-
- /* if arc is null, we start straight from a node */
- if (arc) {
- arc->symmetry_level = level;
-
- node = BLI_otherNode(arc, node);
- }
-
- for (i = 0; i < node->degree; i++) {
- BArc *connectedArc = node->arcs[i];
-
- if (connectedArc != arc) {
- BNode *connectedNode = BLI_otherNode(connectedArc, node);
-
- /* symmetry level is positive value, negative values is subtree depth */
- connectedArc->symmetry_level = -BLI_subtreeShape(graph, connectedNode, connectedArc, 0);
- }
- }
-
- arc = NULL;
-
- for (i = 0; i < node->degree; i++) {
- int issymmetryAxis = 0;
- BArc *connectedArc = node->arcs[i];
-
- /* only arcs not already marked as symetric */
- if (connectedArc->symmetry_level < 0) {
- int j;
-
- /* true by default */
- issymmetryAxis = 1;
-
- for (j = 0; j < node->degree; j++) {
- BArc *otherArc = node->arcs[j];
-
- /* different arc, same depth */
- if (otherArc != connectedArc && otherArc->symmetry_level == connectedArc->symmetry_level) {
- /* not on the symmetry axis */
- issymmetryAxis = 0;
- break;
- }
- }
- }
-
- /* arc could be on the symmetry axis */
- if (issymmetryAxis == 1) {
- /* no arc as been marked previously, keep this one */
- if (arc == NULL) {
- arc = connectedArc;
- }
- else if (connectedArc->symmetry_level < arc->symmetry_level) {
- /* go with more complex subtree as symmetry arc */
- arc = connectedArc;
- }
- }
- }
-
- /* go down the arc continuing the symmetry axis */
- if (arc) {
- markdownSymmetryArc(graph, arc, node, level, limit);
- }
-
-
- /* secondary symmetry */
- for (i = 0; i < node->degree; i++) {
- BArc *connectedArc = node->arcs[i];
-
- /* only arcs not already marked as symetric and is not the next arc on the symmetry axis */
- if (connectedArc->symmetry_level < 0) {
- /* subtree depth is store as a negative value in the symmetry */
- markdownSecondarySymmetry(graph, node, -connectedArc->symmetry_level, level, limit);
- }
- }
-}
-
-void BLI_markdownSymmetry(BGraph *graph, BNode *root_node, float limit)
-{
- BNode *node;
- BArc *arc;
-
- if (root_node == NULL) {
- return;
- }
-
- if (BLI_isGraphCyclic(graph)) {
- return;
- }
-
- /* mark down all arcs as non-symetric */
- BLI_flagArcs(graph, 0);
-
- /* mark down all nodes as not on the symmetry axis */
- BLI_flagNodes(graph, 0);
-
- node = root_node;
-
- /* sanity check REMOVE ME */
- if (node->degree > 0) {
- arc = node->arcs[0];
-
- if (node->degree == 1) {
- markdownSymmetryArc(graph, arc, node, 1, limit);
- }
- else {
- markdownSymmetryArc(graph, NULL, node, 1, limit);
- }
-
-
-
- /* mark down non-symetric arcs */
- for (arc = graph->arcs.first; arc; arc = arc->next) {
- if (arc->symmetry_level < 0) {
- arc->symmetry_level = 0;
- }
- else {
- /* mark down nodes with the lowest level symmetry axis */
- if (arc->head->symmetry_level == 0 || arc->head->symmetry_level > arc->symmetry_level) {
- arc->head->symmetry_level = arc->symmetry_level;
- }
- if (arc->tail->symmetry_level == 0 || arc->tail->symmetry_level > arc->symmetry_level) {
- arc->tail->symmetry_level = arc->symmetry_level;
- }
- }
- }
- }
-}
-
-void *IT_head(void *arg)
-{
- BArcIterator *iter = (BArcIterator *)arg;
- return iter->head(iter);
-}
-
-void *IT_tail(void *arg)
-{
- BArcIterator *iter = (BArcIterator *)arg;
- return iter->tail(iter);
-}
-
-void *IT_peek(void *arg, int n)
-{
- BArcIterator *iter = (BArcIterator *)arg;
-
- if (iter->index + n < 0) {
- return iter->head(iter);
- }
- else if (iter->index + n >= iter->length) {
- return iter->tail(iter);
- }
- else {
- return iter->peek(iter, n);
- }
-}
-
-void *IT_next(void *arg)
-{
- BArcIterator *iter = (BArcIterator *)arg;
- return iter->next(iter);
-}
-
-void *IT_nextN(void *arg, int n)
-{
- BArcIterator *iter = (BArcIterator *)arg;
- return iter->nextN(iter, n);
-}
-
-void *IT_previous(void *arg)
-{
- BArcIterator *iter = (BArcIterator *)arg;
- return iter->previous(iter);
-}
-
-int IT_stopped(void *arg)
-{
- BArcIterator *iter = (BArcIterator *)arg;
- return iter->stopped(iter);
-}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 82994eb0bc4..ba91dac67c4 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -3556,7 +3556,6 @@ static void direct_link_armature(FileData *fd, bArmature *arm)
link_list(fd, &arm->bonebase);
arm->edbo = NULL;
- arm->sketch = NULL;
arm->adt = newdataadr(fd, arm->adt);
direct_link_animdata(fd, arm->adt);
@@ -5680,8 +5679,6 @@ static void lib_link_scene(FileData *fd, Main *main)
sce->toolsettings->imapaint.canvas =
newlibadr_us(fd, sce->id.lib, sce->toolsettings->imapaint.canvas);
- sce->toolsettings->skgen_template = newlibadr(fd, sce->id.lib, sce->toolsettings->skgen_template);
-
sce->toolsettings->particle.shape_object = newlibadr(fd, sce->id.lib, sce->toolsettings->particle.shape_object);
for (Base *base_legacy_next, *base_legacy = sce->base.first; base_legacy; base_legacy = base_legacy_next) {
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index 9ac2f926da6..b31aa7047b0 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -2176,22 +2176,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
}
}
- /* sanity check for skgen */
- {
- Scene *sce;
- for (sce = main->scene.first; sce; sce = sce->id.next) {
- if (sce->toolsettings->skgen_subdivisions[0] == sce->toolsettings->skgen_subdivisions[1] ||
- sce->toolsettings->skgen_subdivisions[0] == sce->toolsettings->skgen_subdivisions[2] ||
- sce->toolsettings->skgen_subdivisions[1] == sce->toolsettings->skgen_subdivisions[2])
- {
- sce->toolsettings->skgen_subdivisions[0] = SKGEN_SUB_CORRELATION;
- sce->toolsettings->skgen_subdivisions[1] = SKGEN_SUB_LENGTH;
- sce->toolsettings->skgen_subdivisions[2] = SKGEN_SUB_ANGLE;
- }
- }
- }
-
-
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 2)) {
Image *ima;
@@ -2569,31 +2553,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
for (sce = main->scene.first; sce; sce = sce->id.next) {
sce->toolsettings->imapaint.seam_bleed = 2;
sce->toolsettings->imapaint.normal_angle = 80;
-
- /* initialize skeleton generation toolsettings */
- sce->toolsettings->skgen_resolution = 250;
- sce->toolsettings->skgen_threshold_internal = 0.1f;
- sce->toolsettings->skgen_threshold_external = 0.1f;
- sce->toolsettings->skgen_angle_limit = 30.0f;
- sce->toolsettings->skgen_length_ratio = 1.3f;
- sce->toolsettings->skgen_length_limit = 1.5f;
- sce->toolsettings->skgen_correlation_limit = 0.98f;
- sce->toolsettings->skgen_symmetry_limit = 0.1f;
- sce->toolsettings->skgen_postpro = SKGEN_SMOOTH;
- sce->toolsettings->skgen_postpro_passes = 3;
- sce->toolsettings->skgen_options = SKGEN_FILTER_INTERNAL|SKGEN_FILTER_EXTERNAL|SKGEN_FILTER_SMART|SKGEN_SUB_CORRELATION|SKGEN_HARMONIC;
- sce->toolsettings->skgen_subdivisions[0] = SKGEN_SUB_CORRELATION;
- sce->toolsettings->skgen_subdivisions[1] = SKGEN_SUB_LENGTH;
- sce->toolsettings->skgen_subdivisions[2] = SKGEN_SUB_ANGLE;
-
-
- sce->toolsettings->skgen_retarget_angle_weight = 1.0f;
- sce->toolsettings->skgen_retarget_length_weight = 1.0f;
- sce->toolsettings->skgen_retarget_distance_weight = 1.0f;
-
- /* Skeleton Sketching */
- sce->toolsettings->bone_sketching = 0;
- sce->toolsettings->skgen_retarget_roll = SK_RETARGET_ROLL_VIEW;
}
}
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,
diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h
index 757c0eb8394..9e278c63904 100644
--- a/source/blender/makesdna/DNA_armature_types.h
+++ b/source/blender/makesdna/DNA_armature_types.h
@@ -99,8 +99,6 @@ typedef struct bArmature {
Bone *act_bone; /* active bone */
struct EditBone *act_edbone; /* active editbone (in editmode) */
- void *sketch; /* sketch struct for etch-a-ton */
-
int flag;
int drawtype;
int gevertdeformer; /* how vertex deformation is handled in the ge */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 8a09cced24b..58a9a748cfd 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -1262,37 +1262,10 @@ typedef struct ToolSettings {
/* Multires */
char multires_subdiv_type;
- /* Skeleton generation */
- short skgen_resolution;
- float skgen_threshold_internal;
- float skgen_threshold_external;
- float skgen_length_ratio;
- float skgen_length_limit;
- float skgen_angle_limit;
- float skgen_correlation_limit;
- float skgen_symmetry_limit;
- float skgen_retarget_angle_weight;
- float skgen_retarget_length_weight;
- float skgen_retarget_distance_weight;
- short skgen_options;
- char skgen_postpro;
- char skgen_postpro_passes;
- char skgen_subdivisions[3];
- char skgen_multi_level;
-
- /* Skeleton Sketching */
- struct Object *skgen_template;
- char bone_sketching;
- char bone_sketching_convert;
- char skgen_subdivision_number;
- char skgen_retarget_options;
- char skgen_retarget_roll;
- char skgen_side_string[8];
- char skgen_num_string[8];
-
/* Alt+RMB option */
char edge_mode;
char edge_mode_live_unwrap;
+ char _pad1;
/* Transform */
char snap_mode, snap_node_mode;
@@ -1312,10 +1285,11 @@ typedef struct ToolSettings {
char vgroupsubset; /* subset selection filter in wpaint */
/* UV painting */
- int use_uv_sculpt;
- int uv_sculpt_settings;
- int uv_sculpt_tool;
- int uv_relax_method;
+ char _pad2[2];
+ char use_uv_sculpt;
+ char uv_sculpt_settings;
+ char uv_sculpt_tool;
+ char uv_relax_method;
/* XXX: these sculpt_paint_* fields are deprecated, use the
* unified_paint_settings field instead! */
short sculpt_paint_settings DNA_DEPRECATED; short pad5;
@@ -2028,15 +2002,6 @@ typedef enum eGPencil_Placement_Flags {
#define BONE_SKETCHING_QUICK 2
#define BONE_SKETCHING_ADJUST 4
-/* ToolSettings.bone_sketching_convert */
-#define SK_CONVERT_CUT_FIXED 0
-#define SK_CONVERT_CUT_LENGTH 1
-#define SK_CONVERT_CUT_ADAPTATIVE 2
-#define SK_CONVERT_RETARGET 3
-
-/* ToolSettings.skgen_retarget_options */
-#define SK_RETARGET_AUTONAME 1
-
/* ToolSettings.skgen_retarget_roll */
#define SK_RETARGET_ROLL_NONE 0
#define SK_RETARGET_ROLL_VIEW 1
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 069e103c5e4..17b543c51a7 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -666,15 +666,6 @@ static PointerRNA rna_Scene_objects_get(CollectionPropertyIterator *iter)
/* End of read-only Iterator of all the scene objects. */
-static void rna_Scene_skgen_etch_template_set(PointerRNA *ptr, PointerRNA value)
-{
- ToolSettings *ts = (ToolSettings *)ptr->data;
- if (value.data && ((Object *)value.data)->type == OB_ARMATURE)
- ts->skgen_template = value.data;
- else
- ts->skgen_template = NULL;
-}
-
static void rna_Scene_set_set(PointerRNA *ptr, PointerRNA value)
{
Scene *scene = (Scene *)ptr->data;
@@ -2454,22 +2445,6 @@ static void rna_def_tool_settings(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
- static const EnumPropertyItem retarget_roll_items[] = {
- {SK_RETARGET_ROLL_NONE, "NONE", 0, "None", "Don't adjust roll"},
- {SK_RETARGET_ROLL_VIEW, "VIEW", 0, "View", "Roll bones to face the view"},
- {SK_RETARGET_ROLL_JOINT, "JOINT", 0, "Joint", "Roll bone to original joint plane offset"},
- {0, NULL, 0, NULL, NULL}
- };
-
- static const EnumPropertyItem sketch_convert_items[] = {
- {SK_CONVERT_CUT_FIXED, "FIXED", 0, "Fixed", "Subdivide stroke in fixed number of bones"},
- {SK_CONVERT_CUT_LENGTH, "LENGTH", 0, "Length", "Subdivide stroke in bones of specific length"},
- {SK_CONVERT_CUT_ADAPTATIVE, "ADAPTIVE", 0, "Adaptive",
- "Subdivide stroke adaptively, with more subdivision in curvier parts"},
- {SK_CONVERT_RETARGET, "RETARGET", 0, "Retarget", "Retarget template bone chain to stroke"},
- {0, NULL, 0, NULL, NULL}
- };
-
static const EnumPropertyItem edge_tag_items[] = {
{EDGE_MODE_SELECT, "SELECT", 0, "Select", ""},
{EDGE_MODE_TAG_SEAM, "SEAM", 0, "Tag Seam", ""},
@@ -2873,72 +2848,6 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "edge_mode_live_unwrap", 1);
RNA_def_property_ui_text(prop, "Live Unwrap", "Changing edges seam re-calculates UV unwrap");
- /* etch-a-ton */
- prop = RNA_def_property(srna, "use_bone_sketching", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "bone_sketching", BONE_SKETCHING);
- RNA_def_property_ui_text(prop, "Use Bone Sketching", "Use sketching to create and edit bones");
-/* RNA_def_property_ui_icon(prop, ICON_EDIT, 0); */
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- prop = RNA_def_property(srna, "use_etch_quick", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "bone_sketching", BONE_SKETCHING_QUICK);
- RNA_def_property_ui_text(prop, "Quick Sketching", "Automatically convert and delete on stroke end");
-
- prop = RNA_def_property(srna, "use_etch_overdraw", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "bone_sketching", BONE_SKETCHING_ADJUST);
- RNA_def_property_ui_text(prop, "Overdraw Sketching", "Adjust strokes by drawing near them");
-
- prop = RNA_def_property(srna, "use_etch_autoname", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "skgen_retarget_options", SK_RETARGET_AUTONAME);
- RNA_def_property_ui_text(prop, "Autoname Bones",
- "Automatically generate values to replace &N and &S suffix placeholders in template names");
-
- prop = RNA_def_property(srna, "etch_number", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "skgen_num_string");
- RNA_def_property_ui_text(prop, "Number", "Text to replace &N with (e.g. 'Finger.&N' -> 'Finger.1' or 'Finger.One')");
-
- prop = RNA_def_property(srna, "etch_side", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "skgen_num_string");
- RNA_def_property_ui_text(prop, "Side", "Text to replace &S with (e.g. 'Arm.&S' -> 'Arm.R' or 'Arm.Right')");
-
- prop = RNA_def_property(srna, "etch_template", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "skgen_template");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_struct_type(prop, "Object");
- RNA_def_property_pointer_funcs(prop, NULL, "rna_Scene_skgen_etch_template_set", NULL, NULL);
- RNA_def_property_ui_text(prop, "Template", "Template armature that will be retargeted to the stroke");
-
- prop = RNA_def_property(srna, "etch_subdivision_number", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "skgen_subdivision_number");
- RNA_def_property_range(prop, 1, 255);
- RNA_def_property_ui_text(prop, "Subdivisions", "Number of bones in the subdivided stroke");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- prop = RNA_def_property(srna, "etch_adaptive_limit", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "skgen_correlation_limit");
- RNA_def_property_range(prop, 0.00001, 1.0);
- RNA_def_property_ui_range(prop, 0.01, 1.0, 0.01, 2);
- RNA_def_property_ui_text(prop, "Limit", "Correlation threshold for number of bones in the subdivided stroke");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- prop = RNA_def_property(srna, "etch_length_limit", PROP_FLOAT, PROP_DISTANCE);
- RNA_def_property_float_sdna(prop, NULL, "skgen_length_limit");
- RNA_def_property_range(prop, 0.00001, 100000.0);
- RNA_def_property_ui_range(prop, 0.001, 100.0, 0.1, 3);
- RNA_def_property_ui_text(prop, "Length", "Maximum length of the subdivided bones");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- prop = RNA_def_property(srna, "etch_roll_mode", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_bitflag_sdna(prop, NULL, "skgen_retarget_roll");
- RNA_def_property_enum_items(prop, retarget_roll_items);
- RNA_def_property_ui_text(prop, "Retarget roll mode", "Method used to adjust the roll of bones when retargeting");
-
- prop = RNA_def_property(srna, "etch_convert_mode", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_bitflag_sdna(prop, NULL, "bone_sketching_convert");
- RNA_def_property_enum_items(prop, sketch_convert_items);
- RNA_def_property_ui_text(prop, "Stroke conversion method", "Method used to convert stroke to bones");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
/* Unified Paint Settings */
prop = RNA_def_property(srna, "unified_paint_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 0317c138e9c..3cf2575cfc7 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -434,11 +434,6 @@ void WM_exit_ext(bContext *C, const bool do_python)
ED_undosys_type_free();
-// XXX
-// BIF_GlobalReebFree();
-// BIF_freeRetarget();
- BIF_freeTemplates(C);
-
free_openrecent();
BKE_mball_cubeTable_free();