Skeleton Sketching
Cut gesture: drawing a line with RMB adds exact points (joints in the final skeleton) on strokes. Can cut multiple strokes at once as long as it cuts each one only once (this could be changed). Shape of the gesture doesn't matter, but eventually it would be straight lines shapes for cuts.
This commit is contained in:
@@ -388,6 +388,7 @@ void tubemap(float x, float y, float z, float *u, float *v);
|
||||
void spheremap(float x, float y, float z, float *u, float *v);
|
||||
|
||||
int LineIntersectLine(float v1[3], float v2[3], float v3[3], float v4[3], float i1[3], float i2[3]);
|
||||
int LineIntersectLineStrict(float v1[3], float v2[3], float v3[3], float v4[3], float vi[3], float *lambda);
|
||||
int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv);
|
||||
int RayIntersectsTriangle(float p1[3], float d[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv);
|
||||
int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, float v0[3], float v1[3], float v2[3], float *lambda, float *ipoint);
|
||||
|
||||
@@ -4221,6 +4221,67 @@ int LineIntersectLine(float v1[3], float v2[3], float v3[3], float v4[3], float
|
||||
}
|
||||
}
|
||||
|
||||
/* Intersection point strictly between the two lines
|
||||
* 0 when no intersection is found
|
||||
* */
|
||||
int LineIntersectLineStrict(float v1[3], float v2[3], float v3[3], float v4[3], float vi[3], float *lambda)
|
||||
{
|
||||
float a[3], b[3], c[3], ab[3], cb[3], ca[3], dir1[3], dir2[3];
|
||||
float d;
|
||||
float d1;
|
||||
|
||||
VecSubf(c, v3, v1);
|
||||
VecSubf(a, v2, v1);
|
||||
VecSubf(b, v4, v3);
|
||||
|
||||
VecCopyf(dir1, a);
|
||||
Normalize(dir1);
|
||||
VecCopyf(dir2, b);
|
||||
Normalize(dir2);
|
||||
d = Inpf(dir1, dir2);
|
||||
if (d == 1.0f || d == -1.0f || d == 0) {
|
||||
/* colinear or one vector is zero-length*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
d1 = d;
|
||||
|
||||
Crossf(ab, a, b);
|
||||
d = Inpf(c, ab);
|
||||
|
||||
/* test if the two lines are coplanar */
|
||||
if (d > -0.000001f && d < 0.000001f) {
|
||||
float f1, f2;
|
||||
Crossf(cb, c, b);
|
||||
Crossf(ca, c, a);
|
||||
|
||||
f1 = Inpf(cb, ab) / Inpf(ab, ab);
|
||||
f2 = Inpf(ca, ab) / Inpf(ab, ab);
|
||||
|
||||
if (f1 >= 0 && f1 <= 1 &&
|
||||
f2 >= 0 && f2 <= 1)
|
||||
{
|
||||
VecMulf(a, f1);
|
||||
VecAddf(vi, v1, a);
|
||||
|
||||
if (lambda != NULL)
|
||||
{
|
||||
*lambda = f1;
|
||||
}
|
||||
|
||||
return 1; /* intersection found */
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int AabbIntersectAabb(float min1[3], float max1[3], float min2[3], float max2[3])
|
||||
{
|
||||
return (min1[0]<max2[0] && min1[1]<max2[1] && min1[2]<max2[2] &&
|
||||
|
||||
@@ -93,6 +93,15 @@ typedef struct SK_DrawData
|
||||
SK_PType type;
|
||||
} SK_DrawData;
|
||||
|
||||
typedef struct SK_Intersection
|
||||
{
|
||||
struct SK_Intersection *next, *prev;
|
||||
SK_Stroke *stroke;
|
||||
int start;
|
||||
int end;
|
||||
float p[3];
|
||||
} SK_Intersection;
|
||||
|
||||
typedef struct SK_Sketch
|
||||
{
|
||||
ListBase strokes;
|
||||
@@ -419,6 +428,19 @@ void sk_growStrokeBuffer(SK_Stroke *stk)
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -1329,6 +1351,98 @@ void sk_convert(SK_Sketch *sketch)
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************* GESTURE *************************/
|
||||
|
||||
/* returns the maximum number of intersections per stroke */
|
||||
int sk_getIntersections(ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture)
|
||||
{
|
||||
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;
|
||||
|
||||
project_float(stk->points[s_i].p, s_p1);
|
||||
project_float(stk->points[s_i + 1].p, s_p2);
|
||||
|
||||
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;
|
||||
|
||||
project_float(gesture->points[g_i].p, g_p1);
|
||||
project_float(gesture->points[g_i + 1].p, g_p2);
|
||||
|
||||
if (LineIntersectLineStrict(s_p1, s_p2, g_p1, g_p2, vi, &lambda))
|
||||
{
|
||||
SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection");
|
||||
|
||||
isect->start = s_i;
|
||||
isect->end = s_i + 1;
|
||||
isect->stroke = stk;
|
||||
|
||||
VecSubf(isect->p, stk->points[s_i + 1].p, stk->points[s_i].p);
|
||||
VecMulf(isect->p, lambda);
|
||||
VecAddf(isect->p, isect->p, stk->points[s_i].p);
|
||||
|
||||
BLI_addtail(list, isect);
|
||||
|
||||
s_added++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
added = MAX2(s_added, added);
|
||||
}
|
||||
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
void sk_applyCutGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list)
|
||||
{
|
||||
SK_Intersection *isect;
|
||||
|
||||
for (isect = list->first; isect; isect = isect->next)
|
||||
{
|
||||
SK_Point pt;
|
||||
|
||||
pt.type = PT_EXACT;
|
||||
pt.mode = PT_PROJECT; /* take mode from neighbouring points */
|
||||
VECCOPY(pt.p, isect->p);
|
||||
|
||||
sk_insertStrokePoint(isect->stroke, &pt, isect->end);
|
||||
}
|
||||
}
|
||||
|
||||
void sk_applyGesture(SK_Sketch *sketch)
|
||||
{
|
||||
ListBase list;
|
||||
int added;
|
||||
|
||||
list.first = list.last = NULL;
|
||||
|
||||
added = sk_getIntersections(&list, sketch, sketch->gesture);
|
||||
|
||||
/* detect and apply */
|
||||
if (added == 1)
|
||||
{
|
||||
sk_applyCutGesture(sketch, sketch->gesture, &list);
|
||||
}
|
||||
|
||||
BLI_freelistN(&list);
|
||||
}
|
||||
|
||||
/********************************************/
|
||||
|
||||
void sk_deleteStrokes(SK_Sketch *sketch)
|
||||
@@ -1354,7 +1468,7 @@ void sk_selectAllSketch(SK_Sketch *sketch, int mode)
|
||||
if (mode == -1)
|
||||
{
|
||||
for (stk = sketch->strokes.first; stk; stk = stk->next)
|
||||
{
|
||||
{sk_applyGesture(sketch);
|
||||
stk->selected = 0;
|
||||
}
|
||||
}
|
||||
@@ -1468,7 +1582,8 @@ void sk_drawSketch(SK_Sketch *sketch, int with_names)
|
||||
}
|
||||
}
|
||||
|
||||
if (sketch->gesture != NULL)
|
||||
/* 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);
|
||||
@@ -1480,6 +1595,7 @@ void sk_drawSketch(SK_Sketch *sketch, int with_names)
|
||||
|
||||
if (last != NULL)
|
||||
{
|
||||
/* update point if in active area */
|
||||
if (area_is_active_area(G.vd->area))
|
||||
{
|
||||
SK_DrawData dd;
|
||||
@@ -1619,6 +1735,8 @@ int sk_paint(SK_Sketch *sketch, short mbut)
|
||||
|
||||
sk_endContinuousStroke(sketch->gesture);
|
||||
sk_filterLastContinuousStroke(sketch->gesture);
|
||||
sk_filterLastContinuousStroke(sketch->gesture);
|
||||
sk_filterLastContinuousStroke(sketch->gesture);
|
||||
|
||||
if (sketch->gesture->nb_points == 1)
|
||||
{
|
||||
@@ -1627,6 +1745,7 @@ int sk_paint(SK_Sketch *sketch, short mbut)
|
||||
else
|
||||
{
|
||||
/* apply gesture here */
|
||||
sk_applyGesture(sketch);
|
||||
printf("FOO!\n");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user