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:
Diffstat (limited to 'source/blender/src/editarmature_sketch.c')
-rw-r--r--source/blender/src/editarmature_sketch.c417
1 files changed, 196 insertions, 221 deletions
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]);