Adding subdivisions by correlation.
This is much nicer than subdivision by angle but is somewhat less intuitive for users. Added Bucket arc iterator, removing a lot of weird duplicated code in skeleton generator.
This commit is contained in:
@@ -44,7 +44,7 @@ struct ListBase;
|
||||
struct MemFile;
|
||||
|
||||
#define BLENDER_VERSION 245
|
||||
#define BLENDER_SUBVERSION 8
|
||||
#define BLENDER_SUBVERSION 9
|
||||
|
||||
#define BLENDER_MINVERSION 240
|
||||
#define BLENDER_MINSUBVERSION 0
|
||||
|
||||
@@ -6768,7 +6768,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
}
|
||||
}
|
||||
|
||||
if (main->versionfile < 245 || main->subversionfile < 8)
|
||||
if (main->versionfile < 245 || main->subversionfile < 9)
|
||||
{
|
||||
/* initialize skeleton generation toolsettings */
|
||||
for(sce=main->scene.first; sce; sce = sce->id.next)
|
||||
@@ -6779,10 +6779,13 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
sce->toolsettings->skgen_angle_limit = 45.0f;
|
||||
sce->toolsettings->skgen_length_ratio = 1.3f;
|
||||
sce->toolsettings->skgen_length_limit = 1.5f;
|
||||
sce->toolsettings->skgen_correlation_limit = 0.98f;
|
||||
sce->toolsettings->skgen_postpro = SKGEN_SMOOTH;
|
||||
sce->toolsettings->skgen_postpro_passes = 1;
|
||||
sce->toolsettings->skgen_options = SKGEN_FILTER_INTERNAL|SKGEN_FILTER_EXTERNAL|SKGEN_REPOSITION|SKGEN_CUT_LENGTH|SKGEN_CUT_ANGLE;
|
||||
|
||||
sce->toolsettings->skgen_options = SKGEN_FILTER_INTERNAL|SKGEN_FILTER_EXTERNAL|SKGEN_REPOSITION|SKGEN_CUT_LENGTH|SKGEN_SUB_CORRELATION;
|
||||
sce->toolsettings->skgen_subdivisions[0] = SKGEN_SUB_LENGTH;
|
||||
sce->toolsettings->skgen_subdivisions[1] = SKGEN_SUB_CORRELATION;
|
||||
sce->toolsettings->skgen_subdivisions[2] = SKGEN_SUB_ANGLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,14 @@ typedef struct ReebArc {
|
||||
int flags;
|
||||
} ReebArc;
|
||||
|
||||
typedef struct ReebArcIterator {
|
||||
struct ReebArc *arc;
|
||||
int index;
|
||||
int start;
|
||||
int end;
|
||||
int stride;
|
||||
} ReebArcIterator;
|
||||
|
||||
struct EditMesh;
|
||||
|
||||
void weightToHarmonic(struct EditMesh *em);
|
||||
@@ -85,6 +93,10 @@ ReebGraph * generateReebGraph(struct EditMesh *me, int subdivisions);
|
||||
|
||||
#define OTHER_NODE(arc, node) ((arc->v1 == node) ? arc->v2 : arc->v1)
|
||||
|
||||
void initArcIterator(struct ReebArcIterator *iter, struct ReebArc *arc, struct ReebNode *head);
|
||||
void initArcIterator2(struct ReebArcIterator *iter, struct ReebArc *arc, int start, int end);
|
||||
struct EmbedBucket * nextBucket(struct ReebArcIterator *iter);
|
||||
|
||||
int subtreeDepth(ReebNode *node);
|
||||
int countConnectedArcs(ReebGraph *rg, ReebNode *node);
|
||||
int hasAdjacencyList(ReebGraph *rg);
|
||||
|
||||
@@ -370,10 +370,13 @@ typedef struct ToolSettings {
|
||||
float skgen_length_ratio;
|
||||
float skgen_length_limit;
|
||||
float skgen_angle_limit;
|
||||
float skgen_correlation_limit;
|
||||
short skgen_options;
|
||||
char skgen_postpro;
|
||||
char skgen_postpro_passes;
|
||||
char skgen_subdivisions[3];
|
||||
|
||||
char pad3[1];
|
||||
} ToolSettings;
|
||||
|
||||
/* Used by all brushes to store their properties, which can be directly set
|
||||
@@ -682,7 +685,12 @@ typedef struct Scene {
|
||||
#define SKGEN_SYMMETRY 8
|
||||
#define SKGEN_CUT_LENGTH 16
|
||||
#define SKGEN_CUT_ANGLE 32
|
||||
#define SKGEN_LENGTH_FIRST 64
|
||||
#define SKGEN_CUT_CORRELATION 64
|
||||
|
||||
#define SKGEN_SUB_LENGTH 0
|
||||
#define SKGEN_SUB_ANGLE 1
|
||||
#define SKGEN_SUB_CORRELATION 2
|
||||
#define SKGEN_SUB_TOTAL 3
|
||||
|
||||
/* toolsettings->skgen_postpro */
|
||||
#define SKGEN_SMOOTH 0
|
||||
|
||||
@@ -4418,54 +4418,71 @@ static void verify_vertexgroup_name_func(void *datav, void *data2_unused)
|
||||
unique_vertexgroup_name((bDeformGroup*)datav, OBACT);
|
||||
}
|
||||
|
||||
static void skgen_reorder(void *arg1, void *arg2)
|
||||
static void skgen_reorder(void *option, void *arg2)
|
||||
{
|
||||
G.scene->toolsettings->skgen_options ^= SKGEN_LENGTH_FIRST;
|
||||
char tmp;
|
||||
switch ((int)option)
|
||||
{
|
||||
case 0:
|
||||
tmp = G.scene->toolsettings->skgen_subdivisions[0];
|
||||
G.scene->toolsettings->skgen_subdivisions[0] = G.scene->toolsettings->skgen_subdivisions[1];
|
||||
G.scene->toolsettings->skgen_subdivisions[1] = tmp;
|
||||
break;
|
||||
case 1:
|
||||
tmp = G.scene->toolsettings->skgen_subdivisions[2];
|
||||
G.scene->toolsettings->skgen_subdivisions[2] = G.scene->toolsettings->skgen_subdivisions[1];
|
||||
G.scene->toolsettings->skgen_subdivisions[1] = tmp;
|
||||
break;
|
||||
case 2:
|
||||
tmp = G.scene->toolsettings->skgen_subdivisions[0];
|
||||
G.scene->toolsettings->skgen_subdivisions[0] = G.scene->toolsettings->skgen_subdivisions[2];
|
||||
G.scene->toolsettings->skgen_subdivisions[2] = G.scene->toolsettings->skgen_subdivisions[1];
|
||||
G.scene->toolsettings->skgen_subdivisions[1] = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void editing_panel_mesh_skgen(Object *ob, Mesh *me)
|
||||
{
|
||||
uiBlock *block;
|
||||
uiBut *but;
|
||||
int i;
|
||||
|
||||
block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_skgen", UI_EMBOSS, UI_HELV, curarea->win);
|
||||
if(uiNewPanel(curarea, block, "Skeleton Generation", "Editing", 960, 0, 318, 204)==0) return;
|
||||
|
||||
uiDefBut(block, BUT, B_GEN_SKELETON, "Generate Skeleton", 1025,160,250,39, 0, 0, 0, 0, 0, "Generate Skeleton from Mesh");
|
||||
uiDefBut(block, BUT, B_GEN_SKELETON, "Generate Skeleton", 1025,170,250,19, 0, 0, 0, 0, 0, "Generate Skeleton from Mesh");
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButS(block, NUM, B_DIFF, "Resolution:", 1025,130,250,19, &G.scene->toolsettings->skgen_resolution,10.0,1000.0, 0, 0, "Specifies the resolution of the graph's embedding");
|
||||
uiDefButBitS(block, TOG, SKGEN_FILTER_INTERNAL, B_DIFF, "Filter In", 1025,110, 83,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Filter internal small arcs from graph");
|
||||
uiDefButF(block, NUM, B_DIFF, "Thresh:", 1111,110,164,19, &G.scene->toolsettings->skgen_threshold_internal,0.0, 1.0, 10, 0, "Specify the threshold ratio for filtering internal arcs");
|
||||
uiDefButBitS(block, TOG, SKGEN_FILTER_EXTERNAL, B_DIFF, "Filter Ex", 1025, 90, 83,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Filter external small arcs from graph");
|
||||
uiDefButF(block, NUM, B_DIFF, "Thresh:", 1111, 90,164,19, &G.scene->toolsettings->skgen_threshold_external,0.0, 1.0, 10, 0, "Specify the threshold ratio for filtering external arcs");
|
||||
uiDefButS(block, NUM, B_DIFF, "Resolution:", 1025,150,250,19, &G.scene->toolsettings->skgen_resolution,10.0,1000.0, 0, 0, "Specifies the resolution of the graph's embedding");
|
||||
uiDefButBitS(block, TOG, SKGEN_FILTER_INTERNAL, B_DIFF, "Filter In", 1025,130, 83,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Filter internal small arcs from graph");
|
||||
uiDefButF(block, NUM, B_DIFF, "Thresh:", 1111,130,164,19, &G.scene->toolsettings->skgen_threshold_internal,0.0, 1.0, 10, 0, "Specify the threshold ratio for filtering internal arcs");
|
||||
uiDefButBitS(block, TOG, SKGEN_FILTER_EXTERNAL, B_DIFF, "Filter Ex", 1025,110, 83,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Filter external small arcs from graph");
|
||||
uiDefButF(block, NUM, B_DIFF, "Thresh:", 1111,110,164,19, &G.scene->toolsettings->skgen_threshold_external,0.0, 1.0, 10, 0, "Specify the threshold ratio for filtering external arcs");
|
||||
|
||||
but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_MOVE_DOWN, 1025, 70, 16, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Change the order the subdivisions algorithm are applied");
|
||||
uiButSetFunc(but, skgen_reorder, NULL, NULL);
|
||||
if (G.scene->toolsettings->skgen_options & SKGEN_LENGTH_FIRST)
|
||||
for(i = 0; i < SKGEN_SUB_TOTAL; i++)
|
||||
{
|
||||
uiDefButBitS(block, TOG, SKGEN_CUT_LENGTH, B_DIFF, "Length", 1041, 70, 67,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs based on embedding");
|
||||
uiDefButF(block, NUM, B_DIFF, "Thresh:", 1111, 70, 82,19, &G.scene->toolsettings->skgen_length_ratio,1.0, 4.0, 10, 0, "Specify the ratio limit between straight arc and embeddings to trigger equal subdivisions");
|
||||
uiDefButF(block, NUM, B_DIFF, "Len:", 1193, 70, 82,19, &G.scene->toolsettings->skgen_length_limit,0.1,50.0, 10, 0, "Maximum length of the bones when subdividing");
|
||||
}
|
||||
else
|
||||
{
|
||||
uiDefButBitS(block, TOG, SKGEN_CUT_ANGLE, B_DIFF, "Angle", 1041, 70, 67,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs based on angle");
|
||||
uiDefButF(block, NUM, B_DIFF, "Thresh:", 1111, 70,164,19, &G.scene->toolsettings->skgen_angle_limit,0.0, 90.0, 10, 0, "Specify the threshold angle in degrees for subdivision");
|
||||
}
|
||||
|
||||
but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_MOVE_UP, 1025, 50, 16, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Change the order the subdivisions algorithm are applied");
|
||||
uiButSetFunc(but, skgen_reorder, NULL, NULL);
|
||||
if (G.scene->toolsettings->skgen_options & SKGEN_LENGTH_FIRST)
|
||||
{
|
||||
uiDefButBitS(block, TOG, SKGEN_CUT_ANGLE, B_DIFF, "Angle", 1041, 50, 67,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs based on angle");
|
||||
uiDefButF(block, NUM, B_DIFF, "Thresh:", 1111, 50,164,19, &G.scene->toolsettings->skgen_angle_limit,0.0, 90.0, 10, 0, "Specify the threshold angle in degrees for subdivision");
|
||||
}
|
||||
else
|
||||
{
|
||||
uiDefButBitS(block, TOG, SKGEN_CUT_LENGTH, B_DIFF, "Length", 1041, 50, 67,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs based on embedding");
|
||||
uiDefButF(block, NUM, B_DIFF, "Thresh:", 1111, 50, 82,19, &G.scene->toolsettings->skgen_length_ratio,1.0, 4.0, 10, 0, "Specify the ratio limit between straight arc and embeddings to trigger equal subdivisions");
|
||||
uiDefButF(block, NUM, B_DIFF, "Len:", 1193, 50, 82,19, &G.scene->toolsettings->skgen_length_limit,0.1,50.0, 10, 0, "Maximum length of the bones when subdividing");
|
||||
int y = 90 - 20 * i;
|
||||
|
||||
but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_MOVE_DOWN, 1025, y, 16, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Change the order the subdivisions algorithm are applied");
|
||||
uiButSetFunc(but, skgen_reorder, (void *)i, NULL);
|
||||
|
||||
switch(G.scene->toolsettings->skgen_subdivisions[i])
|
||||
{
|
||||
case SKGEN_SUB_LENGTH:
|
||||
uiDefButBitS(block, TOG, SKGEN_CUT_LENGTH, B_DIFF, "Length", 1041, y, 67,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs based on embedding length");
|
||||
uiDefButF(block, NUM, B_DIFF, "Thresh:", 1111, y, 82,19, &G.scene->toolsettings->skgen_length_ratio,1.0, 4.0, 10, 0, "Specify the ratio limit between straight arc and embeddings to trigger equal subdivisions");
|
||||
uiDefButF(block, NUM, B_DIFF, "Len:", 1193, y, 82,19, &G.scene->toolsettings->skgen_length_limit,0.1,50.0, 10, 0, "Maximum length of the bones when subdividing");
|
||||
break;
|
||||
case SKGEN_SUB_ANGLE:
|
||||
uiDefButBitS(block, TOG, SKGEN_CUT_ANGLE, B_DIFF, "Angle", 1041, y, 67,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs based on angle");
|
||||
uiDefButF(block, NUM, B_DIFF, "Thresh:", 1111, y,164,19, &G.scene->toolsettings->skgen_angle_limit,0.0, 90.0, 10, 0, "Specify the threshold angle in degrees for subdivision");
|
||||
break;
|
||||
case SKGEN_SUB_CORRELATION:
|
||||
uiDefButBitS(block, TOG, SKGEN_CUT_CORRELATION, B_DIFF, "Correlation", 1041, y, 67,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs based on correlation");
|
||||
uiDefButF(block, NUM, B_DIFF, "Thresh:", 1111, y,164,19, &G.scene->toolsettings->skgen_correlation_limit,0.0, 1.0, 0.01, 0, "Specify the threshold correlation for subdivision");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uiDefButBitS(block, TOG, SKGEN_REPOSITION, B_DIFF, "Reposition", 1025, 30,250,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Reposition nodes based on embedding instead of original vertice positions");
|
||||
|
||||
@@ -3291,29 +3291,23 @@ EditBone * subdivideByAngle(ReebArc *arc, ReebNode *head, ReebNode *tail)
|
||||
EditBone *lastBone = NULL;
|
||||
if (G.scene->toolsettings->skgen_options & SKGEN_CUT_ANGLE)
|
||||
{
|
||||
ReebArcIterator iter;
|
||||
EmbedBucket *current = NULL;
|
||||
EmbedBucket *previous = NULL;
|
||||
EditBone *child = NULL;
|
||||
EditBone *parent = NULL;
|
||||
float angleLimit = (float)cos(G.scene->toolsettings->skgen_angle_limit * M_PI / 180.0f);
|
||||
int index = 0;
|
||||
int stride = 1;
|
||||
|
||||
// If head is the highest node, invert stride and start index
|
||||
if (head == arc->v2)
|
||||
{
|
||||
stride *= -1;
|
||||
index = arc->bcount -1;
|
||||
}
|
||||
|
||||
parent = add_editbone("Bone");
|
||||
VECCOPY(parent->head, head->p);
|
||||
|
||||
for(index += stride; index >= 0 && index < arc->bcount; index += stride)
|
||||
for(initArcIterator(&iter, arc, head), previous = nextBucket(&iter), current = nextBucket(&iter); current; previous = current, current = nextBucket(&iter))
|
||||
{
|
||||
float vec1[3], vec2[3];
|
||||
float len1, len2;
|
||||
|
||||
VecSubf(vec1, arc->buckets[index - stride].p, parent->head);
|
||||
VecSubf(vec2, arc->buckets[index].p, arc->buckets[index - stride].p);
|
||||
VecSubf(vec1, previous->p, parent->head);
|
||||
VecSubf(vec2, current->p, previous->p);
|
||||
|
||||
len1 = Normalize(vec1);
|
||||
len2 = Normalize(vec2);
|
||||
@@ -3322,7 +3316,7 @@ EditBone * subdivideByAngle(ReebArc *arc, ReebNode *head, ReebNode *tail)
|
||||
|
||||
if (len1 > 0.0f && len2 > 0.0f && Inpf(vec1, vec2) < angleLimit)
|
||||
{
|
||||
VECCOPY(parent->tail, arc->buckets[index - stride].p);
|
||||
VECCOPY(parent->tail, previous->p);
|
||||
|
||||
child = add_editbone("Bone");
|
||||
VECCOPY(child->head, parent->tail);
|
||||
@@ -3340,48 +3334,146 @@ EditBone * subdivideByAngle(ReebArc *arc, ReebNode *head, ReebNode *tail)
|
||||
return lastBone;
|
||||
}
|
||||
|
||||
float calcCorrelation(ReebArc *arc, int start, int end, float v0[3], float n[3])
|
||||
{
|
||||
int len = 2 + abs(end - start);
|
||||
|
||||
if (len > 2)
|
||||
{
|
||||
ReebArcIterator iter;
|
||||
EmbedBucket *bucket = NULL;
|
||||
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), bucket = nextBucket(&iter); bucket; bucket = nextBucket(&iter))
|
||||
{
|
||||
float v[3];
|
||||
|
||||
VecSubf(v, bucket->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), bucket = nextBucket(&iter); bucket; bucket = nextBucket(&iter))
|
||||
{
|
||||
float v[3], d[3];
|
||||
float dt;
|
||||
|
||||
VecSubf(v, bucket->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 * subdivideByCorrelation(ReebArc *arc, ReebNode *head, ReebNode *tail)
|
||||
{
|
||||
ReebArcIterator iter;
|
||||
float n[3];
|
||||
float CORRELATION_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 &&
|
||||
calcCorrelation(arc, iter.start, iter.end, head->p, n) < CORRELATION_THRESHOLD)
|
||||
{
|
||||
EmbedBucket *bucket = NULL;
|
||||
EmbedBucket *previous = NULL;
|
||||
EditBone *child = NULL;
|
||||
EditBone *parent = NULL;
|
||||
int boneStart = iter.start;
|
||||
|
||||
parent = add_editbone("Bone");
|
||||
VECCOPY(parent->head, head->p);
|
||||
|
||||
for(previous = nextBucket(&iter), bucket = nextBucket(&iter); bucket; previous = bucket, bucket = nextBucket(&iter))
|
||||
{
|
||||
/* Calculate normal */
|
||||
VecSubf(n, bucket->p, parent->head);
|
||||
|
||||
if (calcCorrelation(arc, boneStart, iter.index, parent->head, n) < CORRELATION_THRESHOLD)
|
||||
{
|
||||
VECCOPY(parent->tail, previous->p);
|
||||
|
||||
child = add_editbone("Bone");
|
||||
VECCOPY(child->head, parent->tail);
|
||||
child->parent = parent;
|
||||
child->flag |= BONE_CONNECTED;
|
||||
|
||||
parent = child; // new child is next parent
|
||||
boneStart = iter.index; // start from end
|
||||
}
|
||||
}
|
||||
|
||||
VECCOPY(parent->tail, tail->p);
|
||||
|
||||
lastBone = parent; /* set last bone in the chain */
|
||||
}
|
||||
|
||||
return lastBone;
|
||||
}
|
||||
|
||||
EditBone * 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;
|
||||
EmbedBucket *bucket = NULL;
|
||||
EmbedBucket *previous = NULL;
|
||||
EditBone *child = NULL;
|
||||
EditBone *parent = NULL;
|
||||
int same = 0;
|
||||
int index = 0;
|
||||
int stride = 1;
|
||||
float lengthLimit = G.scene->toolsettings->skgen_length_limit;
|
||||
int same = 0;
|
||||
|
||||
//printf("----------new arc---------\n");
|
||||
|
||||
// If head is the highest node, invert stride and start index
|
||||
if (head == arc->v2)
|
||||
{
|
||||
stride *= -1;
|
||||
index = arc->bcount -1;
|
||||
}
|
||||
initArcIterator(&iter, arc, head);
|
||||
|
||||
parent = add_editbone("Bone");
|
||||
VECCOPY(parent->head, head->p);
|
||||
|
||||
while (index >= 0 && index < arc->bcount)
|
||||
|
||||
bucket = nextBucket(&iter);
|
||||
while (bucket != NULL)
|
||||
{
|
||||
float *vec0 = NULL;
|
||||
float *vec1 = arc->buckets[index].p;
|
||||
float *vec1 = bucket->p;
|
||||
|
||||
/* first bucket. Previous is head */
|
||||
if (index == 0 || index == arc->bcount - 1)
|
||||
if (previous == NULL)
|
||||
{
|
||||
vec0 = head->p;
|
||||
}
|
||||
/* Previous are valid buckets */
|
||||
/* Previous is a valid bucket */
|
||||
else
|
||||
{
|
||||
vec0 = arc->buckets[index - 1].p;
|
||||
vec0 = previous->p;
|
||||
}
|
||||
|
||||
//printf("distance vec1 -> head = %f\n", VecLenf(vec1, parent->head));
|
||||
/* If lengthLimit hits the current segment */
|
||||
if (VecLenf(vec1, parent->head) > lengthLimit)
|
||||
{
|
||||
@@ -3418,8 +3510,6 @@ EditBone * subdivideByLength(ReebArc *arc, ReebNode *head, ReebNode *tail)
|
||||
{
|
||||
float dv[3];
|
||||
|
||||
//printf("same\n");
|
||||
|
||||
VecSubf(dv, vec1, vec0);
|
||||
Normalize(dv);
|
||||
|
||||
@@ -3428,8 +3518,6 @@ EditBone * subdivideByLength(ReebArc *arc, ReebNode *head, ReebNode *tail)
|
||||
VecAddf(parent->tail, parent->tail, parent->head);
|
||||
}
|
||||
|
||||
//printvecf("new joint", parent->tail);
|
||||
|
||||
child = add_editbone("Bone");
|
||||
VECCOPY(child->head, parent->tail);
|
||||
child->parent = parent;
|
||||
@@ -3441,9 +3529,8 @@ EditBone * subdivideByLength(ReebArc *arc, ReebNode *head, ReebNode *tail)
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("++next bucket++\n");
|
||||
// Next bucket
|
||||
index += stride;
|
||||
previous = bucket;
|
||||
bucket = nextBucket(&iter);
|
||||
same = 0; // Reset same
|
||||
}
|
||||
}
|
||||
@@ -3494,6 +3581,7 @@ void generateSkeletonFromReebGraph(ReebGraph *rg)
|
||||
EditBone *firstBone = NULL;
|
||||
EditBone *parentBone = NULL;
|
||||
ReebNode *head, *tail;
|
||||
int i;
|
||||
|
||||
/* if arc is a symetry axis, internal bones go up the tree */
|
||||
if (arc->flags == 1 && arc->v2->degree != 1)
|
||||
@@ -3527,23 +3615,20 @@ void generateSkeletonFromReebGraph(ReebGraph *rg)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Subdivide by length, then by angle */
|
||||
if (G.scene->toolsettings->skgen_options & SKGEN_LENGTH_FIRST)
|
||||
/* Loop over subdivision methods */
|
||||
for(i = 0; lastBone == NULL && i < SKGEN_SUB_TOTAL; i++)
|
||||
{
|
||||
lastBone = subdivideByLength(arc, head, tail);
|
||||
if (lastBone == NULL)
|
||||
switch(G.scene->toolsettings->skgen_subdivisions[i])
|
||||
{
|
||||
lastBone = subdivideByAngle(arc, head, tail);
|
||||
}
|
||||
}
|
||||
/* Or angle, then length */
|
||||
else
|
||||
{
|
||||
lastBone = subdivideByAngle(arc, head, tail);
|
||||
if (lastBone == NULL)
|
||||
{
|
||||
lastBone = subdivideByLength(arc, head, tail);
|
||||
case SKGEN_SUB_LENGTH:
|
||||
lastBone = subdivideByLength(arc, head, tail);
|
||||
break;
|
||||
case SKGEN_SUB_ANGLE:
|
||||
lastBone = subdivideByAngle(arc, head, tail);
|
||||
break;
|
||||
case SKGEN_SUB_CORRELATION:
|
||||
lastBone = subdivideByCorrelation(arc, head, tail);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1922,6 +1922,62 @@ void weightToVCol(EditMesh *em)
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************** BUCKET ITERATOR **************************************************/
|
||||
|
||||
void initArcIterator(ReebArcIterator *iter, ReebArc *arc, ReebNode *head)
|
||||
{
|
||||
iter->arc = arc;
|
||||
|
||||
if (head == arc->v1)
|
||||
{
|
||||
iter->start = 0;
|
||||
iter->end = arc->bcount - 1;
|
||||
iter->stride = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->start = arc->bcount - 1;
|
||||
iter->end = 0;
|
||||
iter->stride = -1;
|
||||
}
|
||||
|
||||
iter->index = iter->start - iter->stride;
|
||||
}
|
||||
|
||||
void initArcIterator2(ReebArcIterator *iter, ReebArc *arc, int start, int end)
|
||||
{
|
||||
iter->arc = arc;
|
||||
|
||||
iter->start = start;
|
||||
iter->end = end;
|
||||
|
||||
if (end > start)
|
||||
{
|
||||
iter->stride = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->stride = -1;
|
||||
}
|
||||
|
||||
iter->index = iter->start - iter->stride;
|
||||
}
|
||||
|
||||
EmbedBucket * nextBucket(ReebArcIterator *iter)
|
||||
{
|
||||
EmbedBucket *result = NULL;
|
||||
|
||||
if (iter->index != iter->end)
|
||||
{
|
||||
iter->index += iter->stride;
|
||||
result = &(iter->arc->buckets[iter->index]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/****************************************** MAIN EDIT METHOD **************************************************/
|
||||
|
||||
void generateSkeleton(void)
|
||||
{
|
||||
EditMesh *em = G.editMesh;
|
||||
|
||||
Reference in New Issue
Block a user