Draw subdivision preview for quick strokes and selected strokes (those that would be converted).

Preview can be slightly off for quick strokes since subdivision will be affected by stroke smoothing applied only when a continuous stroke is finished.
This commit is contained in:
Martin Poirier
2008-10-21 16:40:42 +00:00
parent 0107b2729a
commit 62c708624d

View File

@@ -120,6 +120,9 @@ SK_Point boneSnap;
void sk_freeStroke(SK_Stroke *stk);
void sk_freeSketch(SK_Sketch *sketch);
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]);
/******************** PEELING *********************************/
typedef struct SK_DepthPeel
@@ -656,6 +659,110 @@ void sk_drawStroke(SK_Stroke *stk, int id, float color[3])
// glEnd();
}
int drawStrokeByCorrelation(SK_Stroke *stk, int start, int end)
{
if (G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION)
{
float head[3], tail[3];
int bone_start = start;
int index;
VECCOPY(head, stk->points[start].p);
glColor3f(0, 1, 1);
glBegin(GL_POINTS);
index = nextCorrelationSubdivision(stk, bone_start, end, head, tail);
while (index != -1)
{
glVertex3fv(tail);
VECCOPY(head, tail);
bone_start = index; // start next bone from current index
index = nextCorrelationSubdivision(stk, bone_start, end, head, tail);
}
glEnd();
return 1;
}
else
{
return 0;
}
}
int drawStrokeByLength(SK_Stroke *stk, int start, int end)
{
if (G.scene->toolsettings->skgen_options & SKGEN_CUT_LENGTH)
{
float head[3], tail[3];
int bone_start = start;
int index;
VECCOPY(head, stk->points[start].p);
glColor3f(0, 1, 1);
glBegin(GL_POINTS);
index = nextLengthSubdivision(stk, bone_start, end, head, tail);
while (index != -1)
{
glVertex3fv(tail);
VECCOPY(head, tail);
bone_start = index; // start next bone from current index
index = nextLengthSubdivision(stk, bone_start, end, head, tail);
}
glEnd();
return 1;
}
else
{
return 0;
}
}
void sk_drawStrokeSubdivision(SK_Stroke *stk)
{
int head_index = -1;
int i;
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
{
int done = 0;
if (i - head_index > 1)
{
done = drawStrokeByCorrelation(stk, head_index, i);
if (done == 0)
{
done = drawStrokeByLength(stk, head_index, i);
}
}
head_index = i;
}
}
}
}
SK_Point *sk_snapPointStroke(SK_Stroke *stk, short mval[2], int *dist)
{
SK_Point *pt = NULL;
@@ -683,19 +790,22 @@ SK_Point *sk_snapPointStroke(SK_Stroke *stk, short mval[2], int *dist)
return pt;
}
SK_Point *sk_snapPointArmature(ListBase *ebones, short mval[2], int *dist)
SK_Point *sk_snapPointArmature(Object *ob, ListBase *ebones, short mval[2], int *dist)
{
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)
{
project_short_noclip(bone->head, pval);
VECCOPY(vec, bone->head);
Mat4MulVecfl(ob->obmat, vec);
project_short_noclip(vec, pval);
pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
@@ -709,7 +819,9 @@ SK_Point *sk_snapPointArmature(ListBase *ebones, short mval[2], int *dist)
}
project_short_noclip(bone->tail, pval);
VECCOPY(vec, bone->tail);
Mat4MulVecfl(ob->obmat, vec);
project_short_noclip(vec, pval);
pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
@@ -851,7 +963,7 @@ int sk_getStrokeSnapPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *source_stk
/* check on bones */
{
SK_Point *spt = sk_snapPointArmature(&G.edbo, dd->mval, &dist);
SK_Point *spt = sk_snapPointArmature(G.obedit, &G.edbo, dd->mval, &dist);
if (spt != NULL)
{
@@ -1163,44 +1275,60 @@ float calcStrokeCorrelation(SK_Stroke *stk, int start, int end, float v0[3], flo
}
}
int nextCorrelationSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3])
{
float correlation_threshold = G.scene->toolsettings->skgen_correlation_limit;
float n[3];
int i;
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;
}
}
return -1;
}
EditBone * subdivideStrokeByCorrelation(SK_Stroke *stk, int start, int end, float invmat[][4])
{
bArmature *arm= G.obedit->data;
EditBone *lastBone = NULL;
float n[3];
float CORRELATION_THRESHOLD = G.scene->toolsettings->skgen_correlation_limit;
if (G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION)
{
EditBone *child = NULL;
EditBone *parent = NULL;
int boneStart = start;
int i;
int bone_start = start;
int index;
parent = addEditBone("Bone", &G.edbo, arm);
VECCOPY(parent->head, stk->points[start].p);
Mat4MulVecfl(invmat, parent->head);
for (i = start + 1; i < end; i++)
index = nextCorrelationSubdivision(stk, bone_start, end, parent->head, parent->tail);
while (index != -1)
{
/* Calculate normal */
VecSubf(n, stk->points[i].p, parent->head);
Mat4MulVecfl(invmat, parent->head); /* going to next bone, fix previous head */
if (calcStrokeCorrelation(stk, boneStart, i, parent->head, n) < CORRELATION_THRESHOLD)
{
VECCOPY(parent->tail, stk->points[i - 1].p);
Mat4MulVecfl(invmat, parent->tail);
child = addEditBone("Bone", &G.edbo, arm);
VECCOPY(child->head, parent->tail);
child->parent = parent;
child->flag |= BONE_CONNECTED;
parent = child; // new child is next parent
bone_start = index; // start next bone from current index
child = addEditBone("Bone", &G.edbo, arm);
VECCOPY(child->head, parent->tail);
child->parent = parent;
child->flag |= BONE_CONNECTED;
parent = child; // new child is next parent
boneStart = i; // start next bone from current index
}
index = nextCorrelationSubdivision(stk, bone_start, end, parent->head, parent->tail);
}
Mat4MulVecfl(invmat, parent->head);
VECCOPY(parent->tail, stk->points[end].p);
Mat4MulVecfl(invmat, parent->tail);
lastBone = parent;
@@ -1209,6 +1337,74 @@ EditBone * subdivideStrokeByCorrelation(SK_Stroke *stk, int start, int end, floa
return lastBone;
}
int nextLengthSubdivision(SK_Stroke *stk, 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 = 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
}
}
return -1;
}
EditBone * subdivideStrokeByLength(SK_Stroke *stk, int start, int end, float invmat[][4])
{
bArmature *arm= G.obedit->data;
@@ -1218,81 +1414,30 @@ EditBone * subdivideStrokeByLength(SK_Stroke *stk, int start, int end, float inv
{
EditBone *child = NULL;
EditBone *parent = NULL;
float lengthLimit = G.scene->toolsettings->skgen_length_limit;
int i;
int same = 0;
int bone_start = start;
int index;
parent = addEditBone("Bone", &G.edbo, arm);
VECCOPY(parent->head, stk->points[start].p);
i = start + 1;
while (i < end)
index = nextLengthSubdivision(stk, bone_start, end, parent->head, parent->tail);
while (index != -1)
{
float *vec0 = stk->points[i - 1].p;
float *vec1 = stk->points[i].p;
Mat4MulVecfl(invmat, parent->head); /* going to next bone, fix previous head */
/* 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);
}
/* put head in correct space */
Mat4MulVecfl(invmat, parent->head);
child = addEditBone("Bone", &G.edbo, arm);
VECCOPY(child->head, parent->tail);
child->parent = parent;
child->flag |= BONE_CONNECTED;
parent = child; // new child is next parent
same = 1; // mark as same
}
else
{
i++;
same = 0; // Reset same
}
child = addEditBone("Bone", &G.edbo, arm);
VECCOPY(child->head, parent->tail);
child->parent = parent;
child->flag |= BONE_CONNECTED;
parent = child; // new child is next parent
bone_start = index; // start next bone from current index
index = nextLengthSubdivision(stk, bone_start, end, parent->head, parent->tail);
}
Mat4MulVecfl(invmat, parent->head);
VECCOPY(parent->tail, stk->points[end].p);
Mat4MulVecfl(invmat, parent->tail);
lastBone = parent;
@@ -1899,6 +2044,11 @@ void sk_drawSketch(SK_Sketch *sketch, int with_names)
for (stk = sketch->strokes.first; stk; stk = stk->next)
{
sk_drawStroke(stk, -1, (stk->selected==1?selected_rgb:unselected_rgb));
if (stk->selected == 1)
{
sk_drawStrokeSubdivision(stk);
}
}
/* only draw gesture in active area */
@@ -1912,6 +2062,11 @@ void sk_drawSketch(SK_Sketch *sketch, int with_names)
{
SK_Point *last = sk_lastStrokePoint(sketch->active_stroke);
if (G.scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK)
{
sk_drawStrokeSubdivision(sketch->active_stroke);
}
if (last != NULL)
{
/* update point if in active area */