[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [17086] branches/etch-a-ton/source/blender /src: Subdivision schemes for continuous strokes:
Martin Poirier
theeth at yahoo.com
Wed Oct 15 21:31:32 CEST 2008
Revision: 17086
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=17086
Author: theeth
Date: 2008-10-15 21:31:32 +0200 (Wed, 15 Oct 2008)
Log Message:
-----------
Subdivision schemes for continuous strokes:
Subdivide in equal length bones
Subdivide by correlation (linearity limits)
Code borrowed in parts from the skeleton generator. Will be eventually reuse code more efficiently.
Modified Paths:
--------------
branches/etch-a-ton/source/blender/src/drawview.c
branches/etch-a-ton/source/blender/src/editarmature_sketch.c
Modified: branches/etch-a-ton/source/blender/src/drawview.c
===================================================================
--- branches/etch-a-ton/source/blender/src/drawview.c 2008-10-15 17:58:03 UTC (rev 17085)
+++ branches/etch-a-ton/source/blender/src/drawview.c 2008-10-15 19:31:32 UTC (rev 17086)
@@ -2305,6 +2305,16 @@
uiButSetFunc(but, convert_sketch_armature, NULL, NULL);
but = uiDefBut(block, BUT, B_REDR, "Delete", 10,185,150,20, 0, 0, 0, 0, 0, "Delete sketch");
uiButSetFunc(but, delete_sketch_armature, NULL, NULL);
+
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+
+ uiDefButBitS(block, TOG, SKGEN_CUT_LENGTH, B_DIFF, "Length", 10, 155, 60, 19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs in bones of equal length");
+ uiDefButF(block, NUM, B_DIFF, "L:", 70, 155, 90, 19, &G.scene->toolsettings->skgen_length_limit,0.1,50.0, 10, 0, "Maximum length of the bones when subdividing");
+
+ uiDefButBitS(block, TOG, SKGEN_CUT_CORRELATION, B_DIFF, "Correlation", 10, 135, 60, 19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs based on correlation");
+ uiDefButF(block, NUM, B_DIFF, "T:", 70, 135, 90, 19, &G.scene->toolsettings->skgen_correlation_limit,0.0, 1.0, 0.01, 0, "Specify the threshold correlation for subdivision");
uiBlockEndAlign(block);
Modified: branches/etch-a-ton/source/blender/src/editarmature_sketch.c
===================================================================
--- branches/etch-a-ton/source/blender/src/editarmature_sketch.c 2008-10-15 17:58:03 UTC (rev 17085)
+++ branches/etch-a-ton/source/blender/src/editarmature_sketch.c 2008-10-15 19:31:32 UTC (rev 17086)
@@ -21,6 +21,7 @@
*/
#include <string.h>
+#include <math.h>
#include "MEM_guardedalloc.h"
@@ -837,7 +838,7 @@
peelObjects(&depth_peels, dd->mval);
- if (stk->nb_points > 0) // && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS)
+ if (stk->nb_points > 0 && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS)
{
last_pt = stk->points + (stk->nb_points - 1);
}
@@ -955,12 +956,202 @@
}
/********************************************/
+float calcStrokeCorrelation(SK_Stroke *stk, 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];
+
+ 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;
+ }
+ else
+ {
+ return 1.0f;
+ }
+}
+
+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;
+
+ parent = addEditBone("Bone", &G.edbo, arm);
+ VECCOPY(parent->head, stk->points[start].p);
+ Mat4MulVecfl(invmat, parent->head);
+
+ for (i = start + 1; i < end; i++)
+ {
+ /* Calculate normal */
+ VecSubf(n, stk->points[i].p, parent->head);
+
+ if (calcStrokeCorrelation(stk, boneStart, i, parent->head, n) < CORRELATION_THRESHOLD)
+ {
+ VECCOPY(parent->tail, stk->points[i - 1].p);
+
+ child = addEditBone("Bone", &G.edbo, arm);
+ VECCOPY(child->head, parent->tail);
+ Mat4MulVecfl(invmat, parent->tail);
+ child->parent = parent;
+ child->flag |= BONE_CONNECTED;
+
+ parent = child; // new child is next parent
+ boneStart = i; // start next bone from current index
+ }
+ }
+
+ VECCOPY(parent->tail, stk->points[end].p);
+ Mat4MulVecfl(invmat, parent->tail);
+ lastBone = parent;
+ }
+
+ return lastBone;
+}
+
+EditBone * subdivideStrokeByLength(SK_Stroke *stk, int start, int end, float invmat[][4])
+{
+ bArmature *arm= G.obedit->data;
+ EditBone *lastBone = NULL;
+
+ if (G.scene->toolsettings->skgen_options & SKGEN_CUT_LENGTH)
+ {
+ EditBone *child = NULL;
+ EditBone *parent = NULL;
+ float lengthLimit = G.scene->toolsettings->skgen_length_limit;
+ int i;
+ int same = 0;
+
+ parent = addEditBone("Bone", &G.edbo, arm);
+ VECCOPY(parent->head, stk->points[start].p);
+
+ 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, 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
+ }
+ }
+ VECCOPY(parent->tail, stk->points[end].p);
+ Mat4MulVecfl(invmat, parent->tail);
+ lastBone = parent;
+ }
+
+ return lastBone;
+}
+
void sk_convertStroke(SK_Stroke *stk)
{
bArmature *arm= G.obedit->data;
SK_Point *head;
EditBone *parent = NULL;
float invmat[4][4]; /* move in caller function */
+ int head_index = 0;
int i;
head = NULL;
@@ -975,27 +1166,53 @@
{
if (head == NULL)
{
+ head_index = i;
head = pt;
}
else
{
- EditBone *bone;
+ EditBone *bone = NULL;
+ EditBone *new_parent;
- bone = addEditBone("Bone", &G.edbo, arm);
+ if (i - head_index > 1)
+ {
+ bone = subdivideStrokeByCorrelation(stk, head_index, i, invmat);
+
+ if (bone == NULL)
+ {
+ bone = subdivideStrokeByLength(stk, head_index, i, invmat);
+ }
+ }
- VECCOPY(bone->head, head->p);
- VECCOPY(bone->tail, pt->p);
+ if (bone == NULL)
+ {
+ bone = addEditBone("Bone", &G.edbo, arm);
+
+ VECCOPY(bone->head, head->p);
+ VECCOPY(bone->tail, pt->p);
+
+ Mat4MulVecfl(invmat, bone->head);
+ Mat4MulVecfl(invmat, bone->tail);
+ }
- Mat4MulVecfl(invmat, bone->head);
- Mat4MulVecfl(invmat, bone->tail);
+ new_parent = bone;
+ bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
+ /* move to end of chain */
+ while (bone->parent != NULL)
+ {
+ bone = bone->parent;
+ bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
+ }
+
if (parent != NULL)
{
bone->parent = parent;
bone->flag |= BONE_CONNECTED;
}
- parent = bone;
+ parent = new_parent;
+ head_index = i;
head = pt;
}
}
More information about the Bf-blender-cvs
mailing list