diff options
-rw-r--r-- | source/blender/blenlib/BLI_graph.h | 14 | ||||
-rw-r--r-- | source/blender/blenlib/intern/graph.c | 55 | ||||
-rw-r--r-- | source/blender/include/BIF_generate.h | 44 | ||||
-rw-r--r-- | source/blender/include/reeb.h | 10 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_scene_types.h | 1 | ||||
-rw-r--r-- | source/blender/src/drawview.c | 4 | ||||
-rw-r--r-- | source/blender/src/editarmature.c | 303 | ||||
-rw-r--r-- | source/blender/src/editarmature_generate.c | 327 | ||||
-rw-r--r-- | source/blender/src/editarmature_retarget.c | 142 | ||||
-rw-r--r-- | source/blender/src/editarmature_sketch.c | 417 | ||||
-rw-r--r-- | source/blender/src/reeb.c | 226 |
11 files changed, 849 insertions, 694 deletions
diff --git a/source/blender/blenlib/BLI_graph.h b/source/blender/blenlib/BLI_graph.h index 7629dbf6ba8..f4fccfcbb2c 100644 --- a/source/blender/blenlib/BLI_graph.h +++ b/source/blender/blenlib/BLI_graph.h @@ -62,13 +62,25 @@ typedef struct 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 int (*StoppedFct)(void* iter); typedef struct BArcIterator { + HeadFct head; + TailFct tail; PeekFct peek; NextFct next; NextNFct nextN; diff --git a/source/blender/blenlib/intern/graph.c b/source/blender/blenlib/intern/graph.c index e2ed8f11ee2..ca82fcac844 100644 --- a/source/blender/blenlib/intern/graph.c +++ b/source/blender/blenlib/intern/graph.c @@ -465,8 +465,6 @@ int subtreeShape(BNode *node, BArc *rootArc, int include_root) int BLI_subtreeShape(BGraph *graph, BNode *node, BArc *rootArc, int include_root) { - BNode *test_node; - BLI_flagNodes(graph, 0); return subtreeShape(node, rootArc, include_root); } @@ -1090,3 +1088,56 @@ void BLI_markdownSymmetry(BGraph *graph, BNode *root_node, float limit) } } +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/include/BIF_generate.h b/source/blender/include/BIF_generate.h new file mode 100644 index 00000000000..32d89d32f78 --- /dev/null +++ b/source/blender/include/BIF_generate.h @@ -0,0 +1,44 @@ +/** + * $Id: $ + * + * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef BIF_GENERATE_H +#define BIF_GENERATE_H + +struct EditBone; +struct BArcIterator; +struct bArmature; +struct ListBase; + +typedef int(NextSubdivisionFunc)(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 BArcIterator *iter, int start, int end, float head[3], float p[3]); +int nextLengthSubdivision(struct BArcIterator *iter, int start, int end, float head[3], float p[3]); +int nextCorrelationSubdivision(struct BArcIterator *iter, int start, int end, float head[3], float p[3]); + +struct EditBone * subdivideArcBy(struct bArmature *arm, ListBase *editbones, struct BArcIterator *iter, float invmat[][4], float tmat[][3], NextSubdivisionFunc next_subdividion); + +void setBoneRollFromNormal(struct EditBone *bone, float *no, float invmat[][4], float tmat[][3]); + + +#endif /* BIF_GENERATE_H */ diff --git a/source/blender/include/reeb.h b/source/blender/include/reeb.h index 21c57495fb0..2f463d6194b 100644 --- a/source/blender/include/reeb.h +++ b/source/blender/include/reeb.h @@ -28,7 +28,7 @@ #ifndef REEB_H_ #define REEB_H_ -#define WITH_BF_REEB +//#define WITH_BF_REEB #include "DNA_listBase.h" @@ -120,6 +120,8 @@ typedef struct ReebArc { } ReebArc; typedef struct ReebArcIterator { + HeadFct head; + TailFct tail; PeekFct peek; NextFct next; NextNFct nextN; @@ -151,9 +153,9 @@ void renormalizeWeight(struct EditMesh *em, float newmax); ReebGraph * generateReebGraph(struct EditMesh *me, int subdivisions); ReebGraph * newReebGraph(); -void initArcIterator(struct ReebArcIterator *iter, struct ReebArc *arc, struct ReebNode *head); -void initArcIterator2(struct ReebArcIterator *iter, struct ReebArc *arc, int start, int end); -void initArcIteratorStart(struct ReebArcIterator *iter, struct ReebArc *arc, struct ReebNode *head, int start); +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); diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 10e8c534ab2..a5491578115 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -728,6 +728,7 @@ typedef struct Scene { /* scene->snap_flag */ #define SCE_SNAP 1 #define SCE_SNAP_ROTATE 2 +#define SCE_SNAP_PEEL_OBJECT 4 /* scene->snap_target */ #define SCE_SNAP_TARGET_CLOSEST 0 #define SCE_SNAP_TARGET_CENTER 1 diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index e652ea989d1..3dfec925474 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2294,7 +2294,7 @@ static void view3d_panel_bonesketch_spaces(short cntrl) static char joint_label[32]; uiBlock *block; uiBut *but; - int yco = 70, height = 140; + int yco = 130, height = 140; int nb_joints; /* replace with check call to sketching lib */ @@ -2382,7 +2382,9 @@ static void view3d_panel_bonesketch_spaces(short cntrl) BLI_snprintf(joint_label, 32, "%i joints", nb_joints); uiDefBut(block, LABEL, 1, joint_label, 10, yco, 200, 20, NULL, 0.0, 0.0, 0, 0, ""); + yco -= 20; + uiDefButBitS(block, TOG, SCE_SNAP_PEEL_OBJECT, B_DIFF, "Peel Objects", 10, yco, 200, 20, &G.scene->snap_flag, 0, 0, 0, 0, "Peel whole objects as one"); if(yco < 0) uiNewPanelHeight(block, height-yco); } diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index bae6fc5a0af..4521c9a8312 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -93,6 +93,7 @@ #include "BIF_space.h" #include "BIF_toolbox.h" #include "BIF_transform.h" +#include "BIF_generate.h" #include "BDR_editobject.h" #include "BDR_drawobject.h" @@ -4655,7 +4656,8 @@ EditBone * subdivideByAngle(ReebArc *arc, ReebNode *head, ReebNode *tail) EditBone *lastBone = NULL; if (G.scene->toolsettings->skgen_options & SKGEN_CUT_ANGLE) { - ReebArcIterator iter; + ReebArcIterator arc_iter; + BArcIterator *iter = (BArcIterator*)&arc_iter; float *previous = NULL, *current = NULL; EditBone *child = NULL; EditBone *parent = NULL; @@ -4668,18 +4670,18 @@ EditBone * subdivideByAngle(ReebArc *arc, ReebNode *head, ReebNode *tail) root = parent; - initArcIterator(&iter, arc, head); - iter.next(&iter); - previous = iter.p; + initArcIterator(iter, arc, head); + IT_next(iter); + previous = iter->p; - for (iter.next(&iter); - iter.stopped(&iter) == 0; - previous = iter.p, iter.next(&iter)) + for (IT_next(iter); + IT_stopped(iter) == 0; + previous = iter->p, IT_next(iter)) { float vec1[3], vec2[3]; float len1, len2; - current = iter.p; + current = iter->p; VecSubf(vec1, previous, parent->head); VecSubf(vec2, current, previous); @@ -4716,173 +4718,26 @@ EditBone * subdivideByAngle(ReebArc *arc, ReebNode *head, ReebNode *tail) return lastBone; } -float calcVariance(ReebArc *arc, int start, int end, float v0[3], float n[3]) +EditBone * test_subdivideByCorrelation(ReebArc *arc, ReebNode *head, ReebNode *tail) { - int len = 2 + abs(end - start); - - if (len > 2) - { - ReebArcIterator iter; - float avg_t = 0.0f; - float s_t = 0.0f; - float s_xyz = 0.0f; - - /* First pass, calculate average */ - for (initArcIterator2(&iter, arc, start, end), iter.next(&iter); - iter.stopped(&iter) == 0; - iter.next(&iter)) - { - float v[3]; - - VecSubf(v, iter.p, v0); - avg_t += Inpf(v, n); - } - - avg_t /= Inpf(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 (initArcIterator2(&iter, arc, start, end), iter.next(&iter); - iter.stopped(&iter) == 0; - iter.next(&iter)) - { - float v[3], d[3]; - float dt; - - VecSubf(v, iter.p, v0); - Projf(d, v, n); - VecSubf(v, v, d); - - dt = VecLength(d) - avg_t; - - s_t += dt * dt; - s_xyz += Inpf(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 s_xyz / s_t; - } - else - { - return 0; - } -} - -float calcDistance(ReebArc *arc, int start, int end, float head[3], float tail[3]) -{ - ReebArcIterator iter; - float max_dist = 0; - - /* calculate maximum distance */ - for (initArcIterator2(&iter, arc, start, end), iter.next(&iter); - iter.stopped(&iter) == 0; - iter.next(&iter)) - { - float v1[3], v2[3], c[3]; - float dist; - - VecSubf(v1, head, tail); - VecSubf(v2, iter.p, tail); - - Crossf(c, v1, v2); - - dist = Inpf(c, c) / Inpf(v1, v1); - - max_dist = dist > max_dist ? dist : max_dist; - } - - - return max_dist; -} - -EditBone * subdivideByCorrelation(ReebArc *arc, ReebNode *head, ReebNode *tail) -{ - ReebArcIterator iter; - float n[3]; - float ADAPTIVE_THRESHOLD = G.scene->toolsettings->skgen_correlation_limit; EditBone *lastBone = NULL; - - /* init iterator to get start and end from head */ - initArcIterator(&iter, arc, head); - - /* Calculate overall */ - VecSubf(n, arc->buckets[iter.end].p, head->p); - + if (G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION) { - EditBone *child = NULL; - EditBone *parent = NULL; - float normal[3] = {0, 0, 0}; - float avg_normal[3]; - int total = 0; - int boneStart = iter.start; - - parent = add_editbone("Bone"); - parent->flag = BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; - VECCOPY(parent->head, head->p); + float invmat[4][4] = { {1, 0, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 0}, + {0, 0, 0, 1}}; + float tmat[3][3] = { {1, 0, 0}, + {0, 1, 0}, + {0, 0, 1}}; + ReebArcIterator arc_iter; + BArcIterator *iter = (BArcIterator*)&arc_iter; + bArmature *arm= G.obedit->data; - while(iter.next(&iter)) - { - float btail[3]; - float value = 0; - - if (G.scene->toolsettings->skgen_options & SKGEN_STICK_TO_EMBEDDING) - { - VECCOPY(btail, iter.p); - } - else - { - float length; - - /* Calculate normal */ - VecSubf(n, iter.p, parent->head); - length = Normalize(n); - - total += 1; - VecAddf(normal, normal, n); - VECCOPY(avg_normal, normal); - VecMulf(avg_normal, 1.0f / total); - - VECCOPY(btail, avg_normal); - VecMulf(btail, length); - VecAddf(btail, btail, parent->head); - } - - if (G.scene->toolsettings->skgen_options & SKGEN_ADAPTIVE_DISTANCE) - { - value = calcDistance(arc, boneStart, iter.index, parent->head, btail); - } - else - { - float n[3]; - - VecSubf(n, btail, parent->head); - value = calcVariance(arc, boneStart, iter.index, parent->head, n); - } - - if (value > ADAPTIVE_THRESHOLD) - { - VECCOPY(parent->tail, btail); - - child = add_editbone("Bone"); - VECCOPY(child->head, parent->tail); - child->parent = parent; - child->flag |= BONE_CONNECTED|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; - - parent = child; // new child is next parent - boneStart = iter.index; // start from end - - normal[0] = normal[1] = normal[2] = 0; - total = 0; - } - } - - VECCOPY(parent->tail, tail->p); + initArcIterator(iter, arc, head); - lastBone = parent; /* set last bone in the chain */ + lastBone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextCorrelationSubdivision); } return lastBone; @@ -4915,106 +4770,26 @@ float arcLengthRatio(ReebArc *arc) return embedLength / arcLength; } -EditBone * subdivideByLength(ReebArc *arc, ReebNode *head, ReebNode *tail) +EditBone * test_subdivideByLength(ReebArc *arc, ReebNode *head, ReebNode *tail) { EditBone *lastBone = NULL; if ((G.scene->toolsettings->skgen_options & SKGEN_CUT_LENGTH) && arcLengthRatio(arc) >= G.scene->toolsettings->skgen_length_ratio) { - ReebArcIterator iter; - float *previous = NULL; - EditBone *child = NULL; - EditBone *parent = NULL; - float lengthLimit = G.scene->toolsettings->skgen_length_limit; - int same = 0; - - parent = add_editbone("Bone"); - parent->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; - VECCOPY(parent->head, head->p); - - initArcIterator(&iter, arc, head); - - iter.next(&iter); + float invmat[4][4] = { {1, 0, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 0}, + {0, 0, 0, 1}}; + float tmat[3][3] = { {1, 0, 0}, + {0, 1, 0}, + {0, 0, 1}}; + ReebArcIterator arc_iter; + BArcIterator *iter = (BArcIterator*)&arc_iter; + bArmature *arm= G.obedit->data; - while (iter.stopped(&iter) == 0) - { - float *vec0 = NULL; - float *vec1 = iter.p; - - /* first bucket. Previous is head */ - if (previous == NULL) - { - vec0 = head->p; - } - /* Previous is a valid bucket */ - else - { - vec0 = previous; - } - - /* If lengthLimit hits the current segment */ - if (VecLenf(vec1, parent->head) > lengthLimit) - { - if (same == 0) - { - float dv[3], off[3]; - float a, b, c, f; - - /* Solve quadratic distance equation */ - VecSubf(dv, vec1, vec0); - a = Inpf(dv, dv); - - VecSubf(off, vec0, parent->head); - b = 2 * Inpf(dv, off); - - c = Inpf(off, off) - (lengthLimit * lengthLimit); - - f = (-b + (float)sqrt(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) - { - VECCOPY(parent->tail, dv); - VecMulf(parent->tail, f); - VecAddf(parent->tail, parent->tail, vec0); - } - else - { - VECCOPY(parent->tail, vec1); - } - } - else - { - float dv[3]; - - VecSubf(dv, vec1, vec0); - Normalize(dv); - - VECCOPY(parent->tail, dv); - VecMulf(parent->tail, lengthLimit); - VecAddf(parent->tail, parent->tail, parent->head); - } - - child = add_editbone("Bone"); - VECCOPY(child->head, parent->tail); - child->parent = parent; - child->flag |= BONE_CONNECTED|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; - - parent = child; // new child is next parent - - same = 1; // mark as same - } - else - { - previous = iter.p; - iter.next(&iter); - same = 0; // Reset same - } - } - VECCOPY(parent->tail, tail->p); + initArcIterator(iter, arc, head); - lastBone = parent; /* set last bone in the chain */ + lastBone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextLengthSubdivision); } return lastBone; @@ -5107,13 +4882,13 @@ void generateSkeletonFromReebGraph(ReebGraph *rg) switch(G.scene->toolsettings->skgen_subdivisions[i]) { case SKGEN_SUB_LENGTH: - lastBone = subdivideByLength(arc, head, tail); + lastBone = test_subdivideByLength(arc, head, tail); break; case SKGEN_SUB_ANGLE: lastBone = subdivideByAngle(arc, head, tail); break; case SKGEN_SUB_CORRELATION: - lastBone = subdivideByCorrelation(arc, head, tail); + lastBone = test_subdivideByCorrelation(arc, head, tail); break; } } diff --git a/source/blender/src/editarmature_generate.c b/source/blender/src/editarmature_generate.c new file mode 100644 index 00000000000..c6e77488212 --- /dev/null +++ b/source/blender/src/editarmature_generate.c @@ -0,0 +1,327 @@ +/** + * $Id: editarmature_generate.c $ + * + * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + * editarmature.c: Interface for creating and posing armature objects + */ + +#include <string.h> +#include <math.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_listBase.h" +#include "DNA_scene_types.h" +#include "DNA_armature_types.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_graph.h" + +#include "BKE_utildefines.h" +#include "BKE_global.h" + +#include "BIF_editarmature.h" +#include "BIF_generate.h" + +void setBoneRollFromNormal(EditBone *bone, float *no, float invmat[][4], float tmat[][3]) +{ + if (no != NULL && !VecIsNull(no)) + { + float tangent[3], cotangent[3], normal[3]; + + VECCOPY(normal, no); + Mat3MulVecfl(tmat, normal); + + VecSubf(tangent, bone->tail, bone->head); + Crossf(cotangent, tangent, normal); + Crossf(normal, cotangent, tangent); + + Normalize(normal); + + bone->roll = rollBoneToVector(bone, normal); + } +} + +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); + VecSubf(v, iter->p, v0); + avg_t += Inpf(v, n); + } + + avg_t /= Inpf(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); + VecSubf(v, iter->p, v0); + Projf(d, v, n); + VecSubf(v, v, d); + + dt = VecLength(d) - avg_t; + + s_t += dt * dt; + s_xyz += Inpf(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(BArcIterator *iter, int start, int end, float 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 += VecLenf(v1, v2); + + v1 = v2; + } + + n = 0; + current_length = 0; + } + + n++; + + length_threshold = n * stroke_length / G.scene->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 += VecLenf(v1, v2); + + if (current_length >= length_threshold) + { + VECCOPY(p, v2); + return i; + } + + v1 = v2; + } + + stroke_length = 0; + + return -1; +} +int nextCorrelationSubdivision(BArcIterator *iter, int start, int end, float head[3], float p[3]) +{ + float correlation_threshold = G.scene->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); + VecSubf(n, iter->p, head); + + if (calcArcCorrelation(iter, start, i, start_p, n) < correlation_threshold) + { + IT_peek(iter, i - 1); + VECCOPY(p, iter->p); + return i - 1; + } + } + + return -1; +} + +int nextLengthSubdivision(BArcIterator *iter, int start, int end, float head[3], float p[3]) +{ + float lengthLimit = G.scene->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 (VecLenf(vec1, head) > lengthLimit) + { + if (same == 0) + { + float dv[3], off[3]; + float a, b, c, f; + + /* Solve quadratic distance equation */ + VecSubf(dv, vec1, vec0); + a = Inpf(dv, dv); + + VecSubf(off, vec0, head); + b = 2 * Inpf(dv, off); + + c = Inpf(off, off) - (lengthLimit * lengthLimit); + + f = (-b + (float)sqrt(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) + { + VECCOPY(p, dv); + VecMulf(p, f); + VecAddf(p, p, vec0); + } + else + { + VECCOPY(p, vec1); + } + } + else + { + float dv[3]; + + VecSubf(dv, vec1, vec0); + Normalize(dv); + + VECCOPY(p, dv); + VecMulf(p, lengthLimit); + VecAddf(p, p, head); + } + + return i - 1; /* restart at lower bound */ + } + else + { + i++; + same = 0; // Reset same + } + } + + return -1; +} + +EditBone * subdivideArcBy(bArmature *arm, ListBase *editbones, BArcIterator *iter, float invmat[][4], float tmat[][3], NextSubdivisionFunc next_subdividion) +{ + EditBone *lastBone = NULL; + EditBone *child = NULL; + EditBone *parent = NULL; + int bone_start = 0; + int end = iter->length; + int index; + + IT_head(iter); + + parent = addEditBone("Bone", editbones, arm); + VECCOPY(parent->head, iter->p); + + index = next_subdividion(iter, bone_start, end, parent->head, parent->tail); + while (index != -1) + { + IT_peek(iter, index); + + child = addEditBone("Bone", editbones, arm); + VECCOPY(child->head, parent->tail); + child->parent = parent; + child->flag |= BONE_CONNECTED; + + /* going to next bone, fix parent */ + Mat4MulVecfl(invmat, parent->tail); + Mat4MulVecfl(invmat, parent->head); + setBoneRollFromNormal(parent, iter->no, invmat, tmat); + + parent = child; // new child is next parent + bone_start = index; // start next bone from current index + + index = next_subdividion(iter, bone_start, end, parent->head, parent->tail); + } + + iter->tail(iter); + + VECCOPY(parent->tail, iter->p); + + /* fix last bone */ + Mat4MulVecfl(invmat, parent->tail); + Mat4MulVecfl(invmat, parent->head); + setBoneRollFromNormal(parent, iter->no, invmat, tmat); + lastBone = parent; + + return lastBone; +} diff --git a/source/blender/src/editarmature_retarget.c b/source/blender/src/editarmature_retarget.c index 280292abaf0..bb0fc08905c 100644 --- a/source/blender/src/editarmature_retarget.c +++ b/source/blender/src/editarmature_retarget.c @@ -1655,100 +1655,6 @@ static EditBone *add_editbonetolist(char *name, ListBase *list) return bone; } -EditBone * generateBonesForArc(RigGraph *rigg, ReebArc *arc, ReebNode *head, ReebNode *tail) -{ - ReebArcIterator iter; - float n[3]; - float ADAPTIVE_THRESHOLD = G.scene->toolsettings->skgen_correlation_limit; - EditBone *lastBone = NULL; - - /* init iterator to get start and end from head */ - initArcIterator(&iter, arc, head); - - /* Calculate overall */ - VecSubf(n, arc->buckets[iter.end].p, head->p); - - if (1 /* G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION */ ) - { - EmbedBucket *bucket = NULL; - EmbedBucket *previous = NULL; - EditBone *child = NULL; - EditBone *parent = NULL; - float normal[3] = {0, 0, 0}; - float avg_normal[3]; - int total = 0; - int boneStart = iter.start; - - parent = add_editbonetolist("Bone", rigg->editbones); - parent->flag = BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; - VECCOPY(parent->head, head->p); - - for (previous = iter.next(&iter), bucket = iter.next(&iter); - bucket; - previous = bucket, bucket = iter.next(&iter)) - { - float btail[3]; - float value = 0; - - if (G.scene->toolsettings->skgen_options & SKGEN_STICK_TO_EMBEDDING) - { - VECCOPY(btail, bucket->p); - } - else - { - float length; - - /* Calculate normal */ - VecSubf(n, bucket->p, parent->head); - length = Normalize(n); - - total += 1; - VecAddf(normal, normal, n); - VECCOPY(avg_normal, normal); - VecMulf(avg_normal, 1.0f / total); - - VECCOPY(btail, avg_normal); - VecMulf(btail, length); - VecAddf(btail, btail, parent->head); - } - - if (G.scene->toolsettings->skgen_options & SKGEN_ADAPTIVE_DISTANCE) - { - value = calcDistance(arc, boneStart, iter.index, parent->head, btail); - } - else - { - float n[3]; - - VecSubf(n, btail, parent->head); - value = calcVariance(arc, boneStart, iter.index, parent->head, n); - } - - if (value > ADAPTIVE_THRESHOLD) - { - VECCOPY(parent->tail, btail); - - child = add_editbonetolist("Bone", rigg->editbones); - VECCOPY(child->head, parent->tail); - child->parent = parent; - child->flag |= BONE_CONNECTED|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; - - parent = child; // new child is next parent - boneStart = iter.index; // start from end - - normal[0] = normal[1] = normal[2] = 0; - total = 0; - } - } - - VECCOPY(parent->tail, tail->p); - - lastBone = parent; /* set last bone in the chain */ - } - - return lastBone; -} - void generateMissingArcsFromNode(RigGraph *rigg, ReebNode *node, int multi_level_limit) { while (node->multi_level > multi_level_limit && node->link_up) @@ -1775,7 +1681,7 @@ void generateMissingArcsFromNode(RigGraph *rigg, ReebNode *node, int multi_level earc->flag = ARC_USED; - generateBonesForArc(rigg, earc, node, other); + //generateBonesForArc(rigg, earc, node, other); generateMissingArcsFromNode(rigg, other, multi_level_limit); } } @@ -2048,7 +1954,7 @@ static void printPositions(int *positions, int nb_positions) #define MAX_COST FLT_MAX /* FIX ME */ -static float costDistance(ReebArcIterator *iter, float *vec0, float *vec1, int i0, int i1) +static float costDistance(BArcIterator *iter, float *vec0, float *vec1, int i0, int i1) { EmbedBucket *bucket = NULL; float max_dist = 0; @@ -2068,7 +1974,7 @@ static float costDistance(ReebArcIterator *iter, float *vec0, float *vec1, int i { float dist; - bucket = iter->peek(iter, j); + bucket = IT_peek(iter, j); VecSubf(v2, bucket->p, vec1); @@ -2128,7 +2034,7 @@ static float costLength(float original_length, float current_length) } } -static float calcCostLengthDistance(ReebArcIterator *iter, float **vec_cache, RigEdge *edge, float *vec1, float *vec2, int i1, int i2) +static float calcCostLengthDistance(BArcIterator *iter, float **vec_cache, RigEdge *edge, float *vec1, float *vec2, int i1, int i2) { float vec[3]; float length; @@ -2139,7 +2045,7 @@ static float calcCostLengthDistance(ReebArcIterator *iter, float **vec_cache, Ri return costLength(edge->length, length) + costDistance(iter, vec1, vec2, i1, i2); } -static float calcCostAngleLengthDistance(ReebArcIterator *iter, float **vec_cache, RigEdge *edge, float *vec0, float *vec1, float *vec2, int i1, int i2) +static float calcCostAngleLengthDistance(BArcIterator *iter, float **vec_cache, RigEdge *edge, float *vec0, float *vec1, float *vec2, int i1, int i2) { float vec_second[3], vec_first[3]; float length2; @@ -2189,7 +2095,7 @@ static void copyMemoPositions(int *positions, MemoNode *table, int nb_positions, } } -static MemoNode * solveJoints(MemoNode *table, ReebArcIterator *iter, float **vec_cache, int nb_joints, int nb_positions, int previous, int current, RigEdge *edge, int joints_left) +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) { MemoNode *node; int index = indexMemoNode(nb_positions, previous, current, joints_left); @@ -2277,7 +2183,8 @@ static int testFlipArc(RigArc *iarc, RigNode *inode_start) static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *inode_start) { - ReebArcIterator iter; + ReebArcIterator arc_iter; + BArcIterator *iter = (BArcIterator*)&arc_iter; RigEdge *edge; EmbedBucket *bucket = NULL; ReebNode *node_start, *node_end; @@ -2332,15 +2239,15 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino positions_cache[0] = node_start->p; positions_cache[nb_positions + 1] = node_end->p; - initArcIterator(&iter, earc, node_start); + initArcIterator(iter, earc, node_start); for (i = 1; i <= nb_positions; i++) { - EmbedBucket *bucket = iter.peek(&iter, i); + EmbedBucket *bucket = IT_peek(iter, i); positions_cache[i] = bucket->p; } - result = solveJoints(table, &iter, positions_cache, nb_joints, earc->bcount, 0, 0, iarc->edges.first, nb_joints); + result = solveJoints(table, iter, positions_cache, nb_joints, earc->bcount, 0, 0, iarc->edges.first, nb_joints); min_cost = result->weight; copyMemoPositions(best_positions, table, earc->bcount, nb_joints); @@ -2422,7 +2329,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino } /* calculating cost */ - initArcIterator(&iter, earc, node_start); + initArcIterator(iter, earc, node_start); vec0 = NULL; vec1 = node_start->p; @@ -2443,13 +2350,13 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino if (i < nb_joints) { i2 = positions[i]; - bucket = iter.peek(&iter, positions[i]); + bucket = IT_peek(iter, positions[i]); vec2 = bucket->p; vec_cache[i + 1] = vec2; /* update cache for updated position */ } else { - i2 = iter.length; + i2 = iter->length; vec2 = node_end->p; } @@ -2485,7 +2392,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino new_cost += costLength(edge->length, length2); /* Distance Cost */ - new_cost += costDistance(&iter, vec1, vec2, i1, i2); + new_cost += costDistance(iter, vec1, vec2, i1, i2); cost_cache[i] = new_cost; } @@ -2518,7 +2425,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino } vec0 = node_start->p; - initArcIterator(&iter, earc, node_start); + initArcIterator(iter, earc, node_start); #ifndef USE_THREADS printPositions(best_positions, nb_joints); @@ -2535,7 +2442,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino float *no = NULL; if (i < nb_joints) { - bucket = iter.peek(&iter, best_positions[i]); + bucket = IT_peek(iter, best_positions[i]); vec1 = bucket->p; no = bucket->no; } @@ -2558,7 +2465,8 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_start) { - ReebArcIterator iter; + ReebArcIterator arc_iter; + BArcIterator *iter = (BArcIterator*)&arc_iter; ReebArc *earc = iarc->link_mesh; ReebNode *node_start, *node_end; RigEdge *edge; @@ -2580,9 +2488,9 @@ static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_ node_end = (ReebNode*)earc->tail; } - initArcIterator(&iter, earc, node_start); + initArcIterator(iter, earc, node_start); - bucket = iter.next(&iter); + bucket = IT_next(iter); vec0 = node_start->p; @@ -2593,15 +2501,15 @@ static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_ embedding_length += VecLenf(vec0, vec1); vec0 = vec1; - bucket = iter.next(&iter); + bucket = IT_next(iter); } embedding_length += VecLenf(node_end->p, vec1); /* fit bones */ - initArcIterator(&iter, earc, node_start); + initArcIterator(iter, earc, node_start); - bucket = iter.next(&iter); + bucket = IT_next(iter); vec0 = node_start->p; previous_vec = vec0; @@ -2616,7 +2524,7 @@ static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_ while (bucket && new_bone_length > length) { length += VecLenf(previous_vec, vec1); - bucket = iter.next(&iter); + bucket = IT_next(iter); previous_vec = vec1; vec1 = bucket->p; no = bucket->no; diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index d558445dec6..78af0a726c2 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -54,6 +54,7 @@ #include "BIF_editarmature.h" #include "BIF_sketch.h" #include "BIF_retarget.h" +#include "BIF_generate.h" #include "blendef.h" #include "mydevice.h" @@ -117,6 +118,26 @@ typedef struct SK_Sketch SK_Point next_point; } SK_Sketch; +typedef struct SK_StrokeIterator { + HeadFct head; + TailFct tail; + PeekFct peek; + NextFct next; + NextNFct nextN; + PreviousFct previous; + StoppedFct stopped; + + float *p, *no; + + int length; + int index; + /*********************************/ + SK_Stroke *stroke; + int start; + int end; + int stride; +} SK_StrokeIterator; + SK_Sketch *GLOBAL_sketch = NULL; SK_Point boneSnap; @@ -124,7 +145,7 @@ SK_Point boneSnap; /******************** PROTOTYPES ******************************/ -typedef int(NextSubdivisionFunc)(SK_Stroke*, int, int, float[3], float[3]); +void initStrokeIterator(BArcIterator *iter, SK_Stroke *stk, int start, int end); void sk_deleteSelectedStrokes(SK_Sketch *sketch); @@ -133,10 +154,6 @@ void sk_freeSketch(SK_Sketch *sketch); SK_Point *sk_lastStrokePoint(SK_Stroke *stk); -int nextFixedSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]); -int nextLengthSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]); -int nextCorrelationSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]); - /******************** TEMPLATES UTILS *************************/ char *TEMPLATES_MENU = NULL; @@ -990,18 +1007,20 @@ void sk_drawStroke(SK_Stroke *stk, int id, float color[3]) // glEnd(); } -void drawSubdividedStrokeBy(SK_Stroke *stk, int start, int end, NextSubdivisionFunc next_subdividion) +void drawSubdividedStrokeBy(BArcIterator *iter, NextSubdivisionFunc next_subdividion) { float head[3], tail[3]; - int bone_start = start; + int bone_start = 0; + int end = iter->length; int index; - VECCOPY(head, stk->points[start].p); + iter->head(iter); + VECCOPY(head, iter->p); glColor3f(0, 1, 1); glBegin(GL_POINTS); - index = next_subdividion(stk, bone_start, end, head, tail); + index = next_subdividion(iter, bone_start, end, head, tail); while (index != -1) { glVertex3fv(tail); @@ -1009,7 +1028,7 @@ void drawSubdividedStrokeBy(SK_Stroke *stk, int start, int end, NextSubdivisionF VECCOPY(head, tail); bone_start = index; // start next bone from current index - index = next_subdividion(stk, bone_start, end, head, tail); + index = next_subdividion(iter, bone_start, end, head, tail); } glEnd(); @@ -1040,17 +1059,22 @@ void sk_drawStrokeSubdivision(SK_Stroke *stk) { if (i - head_index > 1) { + SK_StrokeIterator sk_iter; + BArcIterator *iter = (BArcIterator*)&sk_iter; + + initStrokeIterator(iter, stk, head_index, i); + if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_CORRELATION) { - drawSubdividedStrokeBy(stk, head_index, i, nextCorrelationSubdivision); + drawSubdividedStrokeBy(iter, nextCorrelationSubdivision); } else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH) { - drawSubdividedStrokeBy(stk, head_index, i, nextLengthSubdivision); + drawSubdividedStrokeBy(iter, nextLengthSubdivision); } else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED) { - drawSubdividedStrokeBy(stk, head_index, i, nextFixedSubdivision); + drawSubdividedStrokeBy(iter, nextFixedSubdivision); } } @@ -1354,13 +1378,29 @@ int sk_getStrokeEmbedPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_D float vec[3]; float new_dist; - p1->flag = 0; - - for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next) + p1->flag = 1; + + /* if peeling objects, take the first and last from each object */ + if (G.scene->snap_flag & SCE_SNAP_PEEL_OBJECT) { - /* nothing to do here */ + SK_DepthPeel *peel; + for (peel = p1->next; peel; peel = peel->next) + { + if (peel->ob == p1->ob) + { + peel->flag = 1; + p2 = peel; + } + } + } + /* otherwise, pair first with second and so on */ + else + { + for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next) + { + /* nothing to do here */ + } } - if (p2) { @@ -1528,250 +1568,175 @@ void sk_initDrawData(SK_DrawData *dd) } /********************************************/ -/* bone is assumed to be in GLOBAL space */ -void setBoneRollFromPoint(EditBone *bone, SK_Point *pt, float invmat[][4], float tmat[][3]) -{ - float tangent[3], cotangent[3], normal[3]; - - VecSubf(tangent, bone->tail, bone->head); - Crossf(cotangent, tangent, pt->no); - Crossf(normal, cotangent, tangent); - - Mat3MulVecfl(tmat, normal); - Normalize(normal); - - bone->roll = rollBoneToVector(bone, normal); +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; } -float calcStrokeCorrelation(SK_Stroke *stk, int start, int end, float v0[3], float n[3]) +static SK_Point* setIteratorValues(SK_StrokeIterator *iter, int index) { - int len = 2 + abs(end - start); + SK_Point *pt = NULL; - if (len > 2) + if (index >= 0 && index < iter->length) { - 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]; - - VecSubf(v, stk->points[i].p, v0); - avg_t += Inpf(v, n); - } - - avg_t /= Inpf(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; - - VecSubf(v, stk->points[i].p, v0); - Projf(d, v, n); - VecSubf(v, v, d); - - dt = VecLength(d) - avg_t; - - s_t += dt * dt; - s_xyz += Inpf(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; + pt = &(iter->stroke->points[iter->start + (iter->stride * index)]); + iter->p = pt->p; + iter->no = pt->no; } else { - return 1.0f; + iter->p = NULL; + iter->no = NULL; } + + return pt; } -int nextFixedSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]) +void initStrokeIterator(BArcIterator *arg, SK_Stroke *stk, int start, int end) { - static float stroke_length = 0; - static float current_length; - static char n; - float length_threshold; - int i; + SK_StrokeIterator *iter = (SK_StrokeIterator*)arg; + + initIteratorFct(iter); + iter->stroke = stk; - if (stroke_length == 0) + if (start < end) { - current_length = 0; - for (i = start + 1; i <= end; i++) - { - stroke_length += VecLenf(stk->points[i].p, stk->points[i - 1].p); - } - - n = 0; - current_length = 0; + iter->start = start + 1; + iter->end = end - 1; + iter->stride = 1; } - - n++; - - length_threshold = n * stroke_length / G.scene->toolsettings->skgen_subdivision_number; - - /* < and not <= because we don't care about end, it is P_EXACT anyway */ - for (i = start + 1; i < end; i++) + else { - current_length += VecLenf(stk->points[i].p, stk->points[i - 1].p); - - if (current_length >= length_threshold) - { - VECCOPY(p, stk->points[i].p); - return i; - } + iter->start = start - 1; + iter->end = end + 1; + iter->stride = -1; } - stroke_length = 0; + iter->length = iter->stride * (iter->end - iter->start + 1); - return -1; + iter->index = -1; } -int nextCorrelationSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]) + + +static void* headPoint(void *arg) { - float correlation_threshold = G.scene->toolsettings->skgen_correlation_limit; - float n[3]; - int i; + SK_StrokeIterator *iter = (SK_StrokeIterator*)arg; + SK_Point *result = NULL; - for (i = start + 2; i <= end; i++) - { - /* Calculate normal */ - VecSubf(n, stk->points[i].p, head); - - if (calcStrokeCorrelation(stk, start, i, stk->points[start].p, n) < correlation_threshold) - { - VECCOPY(p, stk->points[i - 1].p); - return i - 1; - } - } + result = &(iter->stroke->points[iter->start - iter->stride]); + iter->p = result->p; + iter->no = result->no; - return -1; + return result; } -int nextLengthSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]) +static void* tailPoint(void *arg) { - float lengthLimit = G.scene->toolsettings->skgen_length_limit; - int same = 1; - int i; + SK_StrokeIterator *iter = (SK_StrokeIterator*)arg; + SK_Point *result = NULL; - i = start + 1; - while (i <= end) - { - float *vec0 = stk->points[i - 1].p; - float *vec1 = stk->points[i].p; - - /* If lengthLimit hits the current segment */ - if (VecLenf(vec1, head) > lengthLimit) - { - if (same == 0) - { - float dv[3], off[3]; - float a, b, c, f; - - /* Solve quadratic distance equation */ - VecSubf(dv, vec1, vec0); - a = Inpf(dv, dv); - - VecSubf(off, vec0, head); - b = 2 * Inpf(dv, off); - - c = Inpf(off, off) - (lengthLimit * lengthLimit); - - f = (-b + (float)sqrt(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) - { - VECCOPY(p, dv); - VecMulf(p, f); - VecAddf(p, p, vec0); - } - else - { - VECCOPY(p, vec1); - } - } - else - { - float dv[3]; - - VecSubf(dv, vec1, vec0); - Normalize(dv); - - VECCOPY(p, dv); - VecMulf(p, lengthLimit); - VecAddf(p, p, head); - } - - return i - 1; /* restart at lower bound */ - } - else - { - i++; - same = 0; // Reset same - } - } + result = &(iter->stroke->points[iter->end + iter->stride]); + iter->p = result->p; + iter->no = result->no; - return -1; + return result; } -EditBone * subdivideStrokeBy(SK_Stroke *stk, int start, int end, float invmat[][4], float tmat[][3], NextSubdivisionFunc next_subdividion) +static void* nextPoint(void *arg) { - bArmature *arm = G.obedit->data; - EditBone *lastBone = NULL; - EditBone *child = NULL; - EditBone *parent = NULL; - int bone_start = start; - int index; - - parent = addEditBone("Bone", &G.edbo, arm); - VECCOPY(parent->head, stk->points[start].p); + SK_StrokeIterator *iter = (SK_StrokeIterator*)arg; + SK_Point *result = NULL; - index = next_subdividion(stk, bone_start, end, parent->head, parent->tail); - while (index != -1) + if (iter->index < iter->length) { - setBoneRollFromPoint(parent, &stk->points[index], invmat, tmat); + iter->index++; + result = setIteratorValues(iter, iter->index); + } - child = addEditBone("Bone", &G.edbo, arm); - VECCOPY(child->head, parent->tail); - child->parent = parent; - child->flag |= BONE_CONNECTED; - - /* going to next bone, fix parent */ - Mat4MulVecfl(invmat, parent->tail); - Mat4MulVecfl(invmat, parent->head); + return result; +} - parent = child; // new child is next parent - bone_start = index; // start next bone from current index +static void* nextNPoint(void *arg, int n) +{ + SK_StrokeIterator *iter = (SK_StrokeIterator*)arg; + SK_Point *result = NULL; + + iter->index += n; - index = next_subdividion(stk, bone_start, end, parent->head, parent->tail); + /* check if passed end */ + if (iter->index < iter->length) + { + result = setIteratorValues(iter, iter->index); + } + else + { + /* stop iterator if passed end */ + iter->index = iter->length; } - VECCOPY(parent->tail, stk->points[end].p); + return result; +} - setBoneRollFromPoint(parent, &stk->points[end], invmat, tmat); +static void* peekPoint(void *arg, int n) +{ + SK_StrokeIterator *iter = (SK_StrokeIterator*)arg; + SK_Point *result = NULL; + int index = iter->index + n; - /* fix last bone */ - Mat4MulVecfl(invmat, parent->tail); - Mat4MulVecfl(invmat, parent->head); - lastBone = parent; + /* 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; - return lastBone; + 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; + } +} void sk_convertStroke(SK_Stroke *stk) { - bArmature *arm= G.obedit->data; + bArmature *arm = G.obedit->data; SK_Point *head; EditBone *parent = NULL; float invmat[4][4]; /* move in caller function */ @@ -1804,17 +1769,22 @@ void sk_convertStroke(SK_Stroke *stk) if (i - head_index > 1) { + SK_StrokeIterator sk_iter; + BArcIterator *iter = (BArcIterator*)&sk_iter; + + initStrokeIterator(iter, stk, head_index, i); + if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_CORRELATION) { - bone = subdivideStrokeBy(stk, head_index, i, invmat, tmat, nextCorrelationSubdivision); + bone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextCorrelationSubdivision); } else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH) { - bone = subdivideStrokeBy(stk, head_index, i, invmat, tmat, nextLengthSubdivision); + bone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextLengthSubdivision); } else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED) { - bone = subdivideStrokeBy(stk, head_index, i, invmat, tmat, nextFixedSubdivision); + bone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextFixedSubdivision); } } @@ -1824,10 +1794,10 @@ void sk_convertStroke(SK_Stroke *stk) VECCOPY(bone->head, head->p); VECCOPY(bone->tail, pt->p); - setBoneRollFromPoint(bone, pt, invmat, tmat); - + Mat4MulVecfl(invmat, bone->head); Mat4MulVecfl(invmat, bone->tail); + setBoneRollFromNormal(bone, pt->no, invmat, tmat); } new_parent = bone; @@ -1995,6 +1965,9 @@ int sk_getIntersections(ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture) 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; @@ -2002,6 +1975,8 @@ int sk_getSegments(SK_Stroke *segments, SK_Stroke *gesture) 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]; @@ -2009,7 +1984,7 @@ int sk_getSegments(SK_Stroke *segments, SK_Stroke *gesture) /* Calculate normal */ VecSubf(n, gesture->points[i].p, vec); - if (calcStrokeCorrelation(gesture, j, i, vec, n) < CORRELATION_THRESHOLD) + if (calcArcCorrelation(iter, j, i, vec, n) < CORRELATION_THRESHOLD) { j = i - 1; sk_appendStrokePoint(segments, &gesture->points[j]); diff --git a/source/blender/src/reeb.c b/source/blender/src/reeb.c index bb53269bf12..553a758c9d5 100644 --- a/source/blender/src/reeb.c +++ b/source/blender/src/reeb.c @@ -850,7 +850,8 @@ void fillArcEmptyBuckets(ReebArc *arc) static void ExtendArcBuckets(ReebArc *arc) { - ReebArcIterator iter; + ReebArcIterator arc_iter; + BArcIterator *iter = (BArcIterator*)&arc_iter; EmbedBucket *last_bucket, *first_bucket; float *previous = NULL; float average_length = 0, length; @@ -861,16 +862,16 @@ static void ExtendArcBuckets(ReebArc *arc) return; /* failsafe, shouldn't happen */ } - initArcIterator(&iter, arc, arc->head); - iter.next(&iter); - previous = iter.p; + initArcIterator(iter, arc, arc->head); + IT_next(iter); + previous = iter->p; - for ( iter.next(&iter); - iter.stopped(&iter) == 0; - previous = iter.p, iter.next(&iter) + for ( IT_next(iter); + IT_stopped(iter) == 0; + previous = iter->p, IT_next(iter) ) { - average_length += VecLenf(previous, iter.p); + average_length += VecLenf(previous, iter->p); } average_length /= (arc->bcount - 1); @@ -927,19 +928,20 @@ void extendGraphBuckets(ReebGraph *rg) void calculateArcLength(ReebArc *arc) { - ReebArcIterator iter; + ReebArcIterator arc_iter; + BArcIterator *iter = (BArcIterator*)&arc_iter; float *vec0, *vec1; arc->length = 0; - initArcIterator(&iter, arc, arc->head); + initArcIterator(iter, arc, arc->head); vec0 = arc->head->p; vec1 = arc->head->p; /* in case there's no embedding */ - while (iter.next(&iter)) + while (IT_next(iter)) { - vec1 = iter.p; + vec1 = iter->p; arc->length += VecLenf(vec0, vec1); @@ -996,28 +998,30 @@ void REEB_RadialSymmetry(BNode* root_node, RadialArc* ring, int count) * */ if (arc1->bcount > 0 && arc2->bcount > 0) { - ReebArcIterator iter1, iter2; + 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); + initArcIterator(iter1, arc1, (ReebNode*)root_node); + initArcIterator(iter2, arc2, (ReebNode*)root_node); - bucket1 = iter1.next(&iter1); - bucket2 = iter2.next(&iter2); + 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 = iter1.next(&iter1); + bucket1 = IT_next(iter1); } while(bucket1 && bucket2 && bucket2->val < bucket1->val) { - bucket2 = iter2.next(&iter2); + bucket2 = IT_next(iter2); } - for ( ;bucket1 && bucket2; bucket1 = iter1.next(&iter1), bucket2 = iter2.next(&iter2)) + for ( ;bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2)) { bucket2->nv += bucket1->nv; /* add counts */ @@ -1056,28 +1060,30 @@ void REEB_RadialSymmetry(BNode* root_node, RadialArc* ring, int count) * */ if (arc1->bcount > 0 && arc2->bcount > 0) { - ReebArcIterator iter1, iter2; + 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); + initArcIterator(iter1, arc1, node); + initArcIterator(iter2, arc2, node); - bucket1 = iter1.next(&iter1); - bucket2 = iter2.next(&iter2); + bucket1 = IT_next(iter1); + bucket2 = IT_next(iter2); /* Make sure they both start at the same value */ while(bucket1 && bucket1->val < bucket2->val) { - bucket1 = iter1.next(&iter1); + bucket1 = IT_next(iter1); } while(bucket2 && bucket2->val < bucket1->val) { - bucket2 = iter2.next(&iter2); + bucket2 = IT_next(iter2); } - for ( ;bucket1 && bucket2; bucket1 = iter1.next(&iter1), bucket2 = iter1.next(&iter2)) + for ( ;bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2)) { /* copy and mirror back to bucket2 */ bucket2->nv = bucket1->nv; @@ -1115,28 +1121,30 @@ void REEB_AxialSymmetry(BNode* root_node, BNode* node1, BNode* node2, struct BAr * */ if (arc1->bcount > 0 && arc2->bcount > 0) { - ReebArcIterator iter1, iter2; + 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); + initArcIterator(iter1, arc1, (ReebNode*)root_node); + initArcIterator(iter2, arc2, (ReebNode*)root_node); - bucket1 = iter1.next(&iter1); - bucket2 = iter2.next(&iter2); + bucket1 = IT_next(iter1); + bucket2 = IT_next(iter2); /* Make sure they both start at the same value */ while(bucket1 && bucket1->val < bucket2->val) { - bucket1 = iter1.next(&iter1); + bucket1 = IT_next(iter1); } while(bucket2 && bucket2->val < bucket1->val) { - bucket2 = iter1.next(&iter2); + bucket2 = IT_next(iter2); } - for ( ;bucket1 && bucket2; bucket1 = iter2.next(&iter1), bucket2 = iter2.next(&iter2)) + for ( ;bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2)) { bucket1->nv += bucket2->nv; /* add counts */ @@ -1763,15 +1771,16 @@ int filterSmartReebGraph(ReebGraph *rg, float threshold) EditFace *efa = BLI_ghashIterator_getValue(&ghi); #if 0 - ReebArcIterator iter; + 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); + initArcIterator(iter, arc, arc->head); - bucket = nextBucket(&iter); + bucket = nextBucket(iter); while (bucket != NULL) { @@ -1806,7 +1815,7 @@ int filterSmartReebGraph(ReebGraph *rg, float threshold) } previous = bucket; - bucket = nextBucket(&iter); + bucket = nextBucket(iter); } avg_angle += saacos(fabs(angle)); @@ -3296,14 +3305,18 @@ void arcToVCol(ReebGraph *rg, EditMesh *em, int index) /****************************************** BUCKET ITERATOR **************************************************/ -void* nextBucket(void *arg); -void* nextNBucket(void *arg, int n); -void* peekBucket(void *arg, int n); -void* previousBucket(void *arg); -int iteratorStopped(void *arg); +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); -void initIteratorFct(ReebArcIterator *iter) +static void initIteratorFct(ReebArcIterator *iter) { + iter->head = headNode; + iter->tail = tailNode; iter->peek = peekBucket; iter->next = nextBucket; iter->nextN = nextNBucket; @@ -3311,7 +3324,7 @@ void initIteratorFct(ReebArcIterator *iter) iter->stopped = iteratorStopped; } -void setIteratorValues(ReebArcIterator *iter, EmbedBucket *bucket) +static void setIteratorValues(ReebArcIterator *iter, EmbedBucket *bucket) { if (bucket) { @@ -3325,8 +3338,10 @@ void setIteratorValues(ReebArcIterator *iter, EmbedBucket *bucket) } } -void initArcIterator(ReebArcIterator *iter, ReebArc *arc, ReebNode *head) +void initArcIterator(BArcIterator *arg, ReebArc *arc, ReebNode *head) { + ReebArcIterator *iter = (ReebArcIterator*)arg; + initIteratorFct(iter); iter->arc = arc; @@ -3345,11 +3360,13 @@ void initArcIterator(ReebArcIterator *iter, ReebArc *arc, ReebNode *head) iter->length = arc->bcount; - iter->index = iter->start - iter->stride; + iter->index = -1; } -void initArcIteratorStart(struct ReebArcIterator *iter, struct ReebArc *arc, struct ReebNode *head, int start) +void initArcIteratorStart(BArcIterator *arg, struct ReebArc *arc, struct ReebNode *head, int start) { + ReebArcIterator *iter = (ReebArcIterator*)arg; + initIteratorFct(iter); iter->arc = arc; @@ -3366,7 +3383,7 @@ void initArcIteratorStart(struct ReebArcIterator *iter, struct ReebArc *arc, str iter->stride = -1; } - iter->index = iter->start - iter->stride; + iter->index = -1; iter->length = arc->bcount - start; @@ -3376,8 +3393,10 @@ void initArcIteratorStart(struct ReebArcIterator *iter, struct ReebArc *arc, str } } -void initArcIterator2(ReebArcIterator *iter, ReebArc *arc, int start, int end) +void initArcIterator2(BArcIterator *arg, ReebArc *arc, int start, int end) { + ReebArcIterator *iter = (ReebArcIterator*)arg; + initIteratorFct(iter); iter->arc = arc; @@ -3393,86 +3412,124 @@ void initArcIterator2(ReebArcIterator *iter, ReebArc *arc, int start, int end) iter->stride = -1; } - iter->index = iter->start - iter->stride; + iter->index = -1; iter->length = abs(iter->end - iter->start) + 1; } -void* nextBucket(void *arg) +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; + + 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; + + return node; +} + +static void* nextBucket(void *arg) { ReebArcIterator *iter = (ReebArcIterator*)arg; EmbedBucket *result = NULL; - if (iter->index != iter->end) + if (iter->index < iter->length) { - iter->index += iter->stride; - result = &(iter->arc->buckets[iter->index]); + iter->index++; + result = &(iter->arc->buckets[iter->start + (iter->stride * iter->index)]); } setIteratorValues(iter, result); return result; } -void* nextNBucket(void *arg, int n) +static void* nextNBucket(void *arg, int n) { ReebArcIterator *iter = (ReebArcIterator*)arg; EmbedBucket *result = NULL; - iter->index += n * iter->stride; + iter->index += n; /* check if passed end */ - if ((iter->stride == 1 && iter->index <= iter->end) || - (iter->stride == -1 && iter->index >= iter->end)) + if (iter->index < iter->length) { - result = &(iter->arc->buckets[iter->index]); + result = &(iter->arc->buckets[iter->start + (iter->stride * iter->index)]); } else { /* stop iterator if passed end */ - iter->index = iter->end; + iter->index = iter->length; } setIteratorValues(iter, result); return result; } -void* peekBucket(void *arg, int n) +static void* peekBucket(void *arg, int n) { ReebArcIterator *iter = (ReebArcIterator*)arg; EmbedBucket *result = NULL; - int index = iter->index + n * iter->stride; + int index = iter->index + n; /* check if passed end */ - if ((iter->stride == 1 && index <= iter->end && index >= iter->start) || - (iter->stride == -1 && index >= iter->end && index <= iter->start)) + if (index < iter->length) { - result = &(iter->arc->buckets[index]); + result = &(iter->arc->buckets[iter->start + (iter->stride * index)]); } setIteratorValues(iter, result); return result; } -void* previousBucket(void *arg) +static void* previousBucket(void *arg) { ReebArcIterator *iter = (ReebArcIterator*)arg; EmbedBucket *result = NULL; - if (iter->index != iter->start) + if (iter->index > 0) { - iter->index -= iter->stride; - result = &(iter->arc->buckets[iter->index]); + iter->index--; + result = &(iter->arc->buckets[iter->start + (iter->stride * iter->index)]); } setIteratorValues(iter, result); return result; } -int iteratorStopped(void *arg) +static int iteratorStopped(void *arg) { ReebArcIterator *iter = (ReebArcIterator*)arg; - if (iter->index == iter->end) + if (iter->index == iter->length) { return 1; } @@ -3711,7 +3768,8 @@ void REEB_draw() glDisable(GL_DEPTH_TEST); for (arc = rg->arcs.first; arc; arc = arc->next, i++) { - ReebArcIterator iter; + ReebArcIterator arc_iter; + BArcIterator *iter = (BArcIterator*)&arc_iter; float vec[3]; char text[128]; char *s = text; @@ -3723,10 +3781,10 @@ void REEB_draw() if (arc->bcount) { - initArcIterator(&iter, arc, arc->head); - for (iter.next(&iter); iter.stopped(&iter) == 0; iter.next(&iter)) + initArcIterator(iter, arc, arc->head); + for (IT_next(iter); IT_stopped(iter) == 0; IT_next(iter)) { - glVertex3fv(iter.p); + glVertex3fv(iter->p); } } @@ -3756,10 +3814,10 @@ void REEB_draw() if (arc->bcount) { - initArcIterator(&iter, arc, arc->head); - for (iter.next(&iter); iter.stopped(&iter) == 0; iter.next(&iter)) + initArcIterator(iter, arc, arc->head); + for (iter->next(iter); IT_stopped(iter) == 0; iter->next(iter)) { - glVertex3fv(iter.p); + glVertex3fv(iter->p); } } @@ -3777,10 +3835,10 @@ void REEB_draw() glColor3f(0.5f, 0.5f, 1); if (arc->bcount) { - initArcIterator(&iter, arc, arc->head); - for (iter.next(&iter); iter.stopped(&iter) == 0; iter.next(&iter)) + initArcIterator(iter, arc, arc->head); + for (iter->next(iter); IT_stopped(iter) == 0; iter->next(iter)) { - glVertex3fv(iter.p); + glVertex3fv(iter->p); } } glEnd(); |