Generate and display multi resolution filtering graphs
This commit is contained in:
@@ -48,8 +48,10 @@ typedef struct ReebGraph {
|
||||
AxialSymmetry axial_symmetry;
|
||||
/*********************************/
|
||||
|
||||
int resolution;
|
||||
int totnodes;
|
||||
struct EdgeHash *emap;
|
||||
struct ReebGraph *link; /* for multi resolution filtering, points to higher levels */
|
||||
} ReebGraph;
|
||||
|
||||
typedef struct EmbedBucket {
|
||||
|
||||
@@ -832,16 +832,19 @@ typedef struct Scene {
|
||||
#define RETOPO_ELLIPSE 4
|
||||
|
||||
/* toolsettings->skgen_options */
|
||||
#define SKGEN_FILTER_INTERNAL 1
|
||||
#define SKGEN_FILTER_EXTERNAL 2
|
||||
#define SKGEN_SYMMETRY 4
|
||||
#define SKGEN_CUT_LENGTH 8
|
||||
#define SKGEN_CUT_ANGLE 16
|
||||
#define SKGEN_CUT_CORRELATION 32
|
||||
#define SKGEN_HARMONIC 64
|
||||
#define SKGEN_STICK_TO_EMBEDDING 128
|
||||
#define SKGEN_ADAPTIVE_DISTANCE 512
|
||||
#define SKGEN_FILTER_SMART 1024
|
||||
#define SKGEN_FILTER_INTERNAL (1 << 0)
|
||||
#define SKGEN_FILTER_EXTERNAL (1 << 1)
|
||||
#define SKGEN_SYMMETRY (1 << 2)
|
||||
#define SKGEN_CUT_LENGTH (1 << 3)
|
||||
#define SKGEN_CUT_ANGLE (1 << 4)
|
||||
#define SKGEN_CUT_CORRELATION (1 << 5)
|
||||
#define SKGEN_HARMONIC (1 << 6)
|
||||
#define SKGEN_STICK_TO_EMBEDDING (1 << 7)
|
||||
#define SKGEN_ADAPTIVE_DISTANCE (1 << 8)
|
||||
#define SKGEN_FILTER_SMART (1 << 9)
|
||||
#define SKGEN_DISP_LENGTH (1 << 10)
|
||||
#define SKGEN_DISP_WEIGHT (1 << 11)
|
||||
#define SKGEN_DISP_ORIG (1 << 12)
|
||||
|
||||
#define SKGEN_SUB_LENGTH 0
|
||||
#define SKGEN_SUB_ANGLE 1
|
||||
|
||||
@@ -5009,13 +5009,42 @@ static void skgen_graphfree(void *arg1, void *arg2)
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
}
|
||||
|
||||
static void editing_panel_mesh_skgen_display(Object *ob, Mesh *me)
|
||||
{
|
||||
uiBlock *block;
|
||||
uiBut *but;
|
||||
|
||||
block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_skgen_display", UI_EMBOSS, UI_HELV, curarea->win);
|
||||
uiNewPanelTabbed("Mesh Tools More", "Skgen");
|
||||
if(uiNewPanel(curarea, block, "Graph", "Editing", 960, 0, 318, 204)==0) return;
|
||||
|
||||
but = uiDefBut(block, BUT, B_DIFF, "Generate", 1025,170,125,19, 0, 0, 0, 0, 0, "Generate Graph from Mesh");
|
||||
uiButSetFunc(but, skgen_graphgen, NULL, NULL);
|
||||
but = uiDefBut(block, BUT, B_DIFF, "Free", 1150,170,125,19, 0, 0, 0, 0, 0, "Free Graph from Mesh");
|
||||
uiButSetFunc(but, skgen_graphfree, NULL, NULL);
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButS(block, NUM, B_DIFF, "Resolution:", 1025,150,225,19, &G.scene->toolsettings->skgen_resolution,10.0,1000.0, 0, 0, "Specifies the resolution of the graph's embedding");
|
||||
uiDefButBitS(block, TOG, SKGEN_HARMONIC, B_DIFF, "H", 1250,150, 25,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Apply harmonic smoothing to the weighting");
|
||||
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, "", 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, 53,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Filter external small arcs from graph");
|
||||
uiDefButBitS(block, TOG, SKGEN_FILTER_SMART, B_DIFF, "Sm", 1078,110, 30,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Smart Filtering");
|
||||
uiDefButF(block, NUM, B_DIFF, "", 1111,110,164,19, &G.scene->toolsettings->skgen_threshold_external,0.0, 1.0, 10, 0, "Specify the threshold ratio for filtering external arcs");
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
uiDefButBitS(block, TOG, SKGEN_DISP_LENGTH, REDRAWVIEW3D, "Length", 1025, 60, 83,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Show Length");
|
||||
uiDefButBitS(block, TOG, SKGEN_DISP_WEIGHT, REDRAWVIEW3D, "Weight", 1108, 60, 83,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Show Weight");
|
||||
uiDefButBitS(block, TOG, SKGEN_DISP_ORIG, REDRAWVIEW3D, "Original", 1191, 60, 84,19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Show Original Graph");
|
||||
}
|
||||
|
||||
static void editing_panel_mesh_skgen_retarget(Object *ob, Mesh *me)
|
||||
{
|
||||
uiBlock *block;
|
||||
|
||||
block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_skgen_retarget", UI_EMBOSS, UI_HELV, curarea->win);
|
||||
uiNewPanelTabbed("Mesh Tools More", "Editing");
|
||||
if(uiNewPanel(curarea, block, "Skeleton Retargetting", "Editing", 960, 0, 318, 204)==0) return;
|
||||
uiNewPanelTabbed("Mesh Tools More", "Skgen");
|
||||
if(uiNewPanel(curarea, block, "Retarget", "Editing", 960, 0, 318, 204)==0) return;
|
||||
|
||||
uiDefBut(block, BUT, B_RETARGET_SKELETON, "Retarget Skeleton", 1025,170,250,19, 0, 0, 0, 0, 0, "Retarget Selected Armature to this Mesh");
|
||||
|
||||
@@ -5050,14 +5079,10 @@ static void editing_panel_mesh_skgen(Object *ob, Mesh *me)
|
||||
int i;
|
||||
|
||||
block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_skgen", UI_EMBOSS, UI_HELV, curarea->win);
|
||||
uiNewPanelTabbed("Mesh Tools More", "Editing");
|
||||
if(uiNewPanel(curarea, block, "Skeleton Generator", "Editing", 960, 0, 318, 204)==0) return;
|
||||
uiNewPanelTabbed("Mesh Tools More", "Skgen");
|
||||
if(uiNewPanel(curarea, block, "Generator", "Editing", 960, 0, 318, 204)==0) return;
|
||||
|
||||
uiDefBut(block, BUT, B_GEN_SKELETON, "Generate Skeleton", 1025,170,125,19, 0, 0, 0, 0, 0, "Generate Skeleton from Mesh");
|
||||
but = uiDefBut(block, BUT, B_DIFF, "Generate", 1150,170,65,19, 0, 0, 0, 0, 0, "Generate Graph from Mesh");
|
||||
uiButSetFunc(but, skgen_graphgen, NULL, NULL);
|
||||
but = uiDefBut(block, BUT, B_DIFF, "Free", 1215,170,60,19, 0, 0, 0, 0, 0, "Free Graph from Mesh");
|
||||
uiButSetFunc(but, skgen_graphfree, NULL, NULL);
|
||||
uiDefBut(block, BUT, B_GEN_SKELETON, "Generate", 1025,170,250,19, 0, 0, 0, 0, 0, "Generate Skeleton from Mesh");
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButS(block, NUM, B_DIFF, "Resolution:", 1025,150,225,19, &G.scene->toolsettings->skgen_resolution,10.0,1000.0, 0, 0, "Specifies the resolution of the graph's embedding");
|
||||
@@ -6579,6 +6604,7 @@ void editing_panels()
|
||||
|
||||
editing_panel_mesh_skgen(ob, ob->data);
|
||||
editing_panel_mesh_skgen_retarget(ob, ob->data);
|
||||
editing_panel_mesh_skgen_display(ob, ob->data);
|
||||
|
||||
editing_panel_mesh_uvautocalculation();
|
||||
if (EM_texFaceCheck())
|
||||
|
||||
@@ -147,6 +147,12 @@ void REEB_freeGraph(ReebGraph *rg)
|
||||
// free edge map
|
||||
BLI_edgehash_free(rg->emap, NULL);
|
||||
|
||||
/* free linked graph */
|
||||
if (rg->link)
|
||||
{
|
||||
REEB_freeGraph(rg->link);
|
||||
}
|
||||
|
||||
MEM_freeN(rg);
|
||||
}
|
||||
|
||||
@@ -256,6 +262,9 @@ ReebGraph * copyReebGraph(ReebGraph *rg)
|
||||
ReebNode *node;
|
||||
ReebArc *arc;
|
||||
ReebGraph *cp_rg = newReebGraph();
|
||||
|
||||
cp_rg->resolution = rg->resolution;
|
||||
cp_rg->link = rg;
|
||||
|
||||
/* Copy nodes */
|
||||
for (node = rg->nodes.first; node; node = node->next)
|
||||
@@ -1366,6 +1375,59 @@ int filterSmartReebGraph(ReebGraph *rg, float threshold)
|
||||
return value;
|
||||
}
|
||||
|
||||
void filterGraph(ReebGraph *rg, short options, float threshold_internal, float threshold_external)
|
||||
{
|
||||
int done = 1;
|
||||
|
||||
/* filter until there's nothing more to do */
|
||||
while (done == 1)
|
||||
{
|
||||
done = 0; /* no work done yet */
|
||||
|
||||
if (options & SKGEN_FILTER_EXTERNAL)
|
||||
{
|
||||
done |= filterExternalReebGraph(rg, threshold_external * rg->resolution);
|
||||
}
|
||||
|
||||
verifyBuckets(rg);
|
||||
|
||||
if (options & SKGEN_FILTER_INTERNAL)
|
||||
{
|
||||
done |= filterInternalReebGraph(rg, threshold_internal * rg->resolution);
|
||||
}
|
||||
}
|
||||
|
||||
if (options & SKGEN_FILTER_SMART)
|
||||
{
|
||||
filterSmartReebGraph(rg, 0.5);
|
||||
BLI_rebuildAdjacencyList((BGraph*)rg);
|
||||
filterCyclesReebGraph(rg, 0.5);
|
||||
}
|
||||
|
||||
repositionNodes(rg);
|
||||
|
||||
/* Filtering might have created degree 2 nodes, so remove them */
|
||||
removeNormalNodes(rg);
|
||||
}
|
||||
|
||||
void finalizeGraph(ReebGraph *rg, char passes, char method)
|
||||
{
|
||||
int i;
|
||||
|
||||
BLI_rebuildAdjacencyList((BGraph*)rg);
|
||||
|
||||
sortNodes(rg);
|
||||
|
||||
sortArcs(rg);
|
||||
|
||||
for(i = 0; i < passes; i++)
|
||||
{
|
||||
postprocessGraph(rg, method);
|
||||
}
|
||||
|
||||
calculateGraphLength(rg);
|
||||
}
|
||||
|
||||
/************************************** WEIGHT SPREADING ***********************************************/
|
||||
|
||||
int compareVerts( const void* a, const void* b )
|
||||
@@ -1951,6 +2013,8 @@ ReebGraph * generateReebGraph(EditMesh *em, int subdivisions)
|
||||
|
||||
rg = newReebGraph();
|
||||
|
||||
rg->resolution = subdivisions;
|
||||
|
||||
totvert = BLI_countlist(&em->verts);
|
||||
totfaces = BLI_countlist(&em->faces);
|
||||
|
||||
@@ -1959,7 +2023,7 @@ ReebGraph * generateReebGraph(EditMesh *em, int subdivisions)
|
||||
/* Spread weight to minimize errors */
|
||||
spreadWeight(em);
|
||||
|
||||
renormalizeWeight(em, (float)subdivisions);
|
||||
renormalizeWeight(em, (float)rg->resolution);
|
||||
|
||||
/* Adding vertice */
|
||||
for(index = 0, eve = em->verts.first; eve; eve = eve->next)
|
||||
@@ -2746,11 +2810,69 @@ struct EmbedBucket * currentBucket(struct ReebArcIterator *iter)
|
||||
|
||||
/************************ PUBLIC FUNCTIONS *********************************************/
|
||||
|
||||
ReebGraph *BIF_ReebGraphMultiFromEditMesh(void)
|
||||
{
|
||||
EditMesh *em = G.editMesh;
|
||||
ReebGraph *rg = NULL;
|
||||
ReebGraph *rgi;
|
||||
|
||||
if (em == NULL)
|
||||
return NULL;
|
||||
|
||||
if (weightFromDistance(em) == 0)
|
||||
{
|
||||
error("No selected vertex\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
renormalizeWeight(em, 1.0f);
|
||||
|
||||
if (G.scene->toolsettings->skgen_options & SKGEN_HARMONIC)
|
||||
{
|
||||
weightToHarmonic(em);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_REEB
|
||||
weightToVCol(em, 0);
|
||||
#endif
|
||||
|
||||
rg = generateReebGraph(em, G.scene->toolsettings->skgen_resolution);
|
||||
|
||||
/* Remove arcs without embedding */
|
||||
filterNullReebGraph(rg);
|
||||
|
||||
repositionNodes(rg);
|
||||
|
||||
/* Filtering might have created degree 2 nodes, so remove them */
|
||||
removeNormalNodes(rg);
|
||||
|
||||
rg = copyReebGraph(rg);
|
||||
|
||||
for (rgi = rg; rgi; rgi = rgi->link)
|
||||
{
|
||||
/* don't fully filter last level */
|
||||
if (rgi->link)
|
||||
{
|
||||
filterGraph(rgi, G.scene->toolsettings->skgen_options, G.scene->toolsettings->skgen_threshold_internal, G.scene->toolsettings->skgen_threshold_external);
|
||||
}
|
||||
/* on last level, only smart filter and loop filter */
|
||||
else
|
||||
{
|
||||
filterGraph(rgi, SKGEN_FILTER_SMART, 0, 0);
|
||||
}
|
||||
|
||||
finalizeGraph(rgi, G.scene->toolsettings->skgen_postpro_passes, G.scene->toolsettings->skgen_postpro);
|
||||
|
||||
BLI_markdownSymmetry((BGraph*)rgi, rgi->nodes.first, G.scene->toolsettings->skgen_symmetry_limit);
|
||||
}
|
||||
|
||||
return rg;
|
||||
}
|
||||
|
||||
ReebGraph *BIF_ReebGraphFromEditMesh(void)
|
||||
{
|
||||
EditMesh *em = G.editMesh;
|
||||
ReebGraph *rg = NULL;
|
||||
int i;
|
||||
|
||||
if (em == NULL)
|
||||
return NULL;
|
||||
@@ -2795,63 +2917,17 @@ ReebGraph *BIF_ReebGraphFromEditMesh(void)
|
||||
printf("NULL FILTERED\n");
|
||||
printf("%i subgraphs\n", BLI_FlagSubgraphs((BGraph*)rg));
|
||||
|
||||
i = 1;
|
||||
/* filter until there's nothing more to do */
|
||||
while (i == 1)
|
||||
{
|
||||
i = 0; /* no work done yet */
|
||||
|
||||
if (G.scene->toolsettings->skgen_options & SKGEN_FILTER_EXTERNAL)
|
||||
{
|
||||
i |= filterExternalReebGraph(rg, G.scene->toolsettings->skgen_threshold_external * G.scene->toolsettings->skgen_resolution);
|
||||
}
|
||||
|
||||
verifyBuckets(rg);
|
||||
|
||||
if (G.scene->toolsettings->skgen_options & SKGEN_FILTER_INTERNAL)
|
||||
{
|
||||
i |= filterInternalReebGraph(rg, G.scene->toolsettings->skgen_threshold_internal * G.scene->toolsettings->skgen_resolution);
|
||||
}
|
||||
}
|
||||
filterGraph(rg, G.scene->toolsettings->skgen_options, G.scene->toolsettings->skgen_threshold_internal, G.scene->toolsettings->skgen_threshold_external);
|
||||
|
||||
if (G.scene->toolsettings->skgen_options & SKGEN_FILTER_SMART)
|
||||
{
|
||||
filterSmartReebGraph(rg, 0.5);
|
||||
BLI_rebuildAdjacencyList((BGraph*)rg);
|
||||
filterCyclesReebGraph(rg, 0.5);
|
||||
}
|
||||
finalizeGraph(rg, G.scene->toolsettings->skgen_postpro_passes, G.scene->toolsettings->skgen_postpro);
|
||||
|
||||
REEB_exportGraph(rg, -1);
|
||||
|
||||
#ifdef DEBUG_REEB
|
||||
arcToVCol(rg, em, 0);
|
||||
//angleToVCol(em, 1);
|
||||
#endif
|
||||
|
||||
verifyBuckets(rg);
|
||||
|
||||
repositionNodes(rg);
|
||||
|
||||
verifyBuckets(rg);
|
||||
|
||||
/* Filtering might have created degree 2 nodes, so remove them */
|
||||
removeNormalNodes(rg);
|
||||
|
||||
verifyBuckets(rg);
|
||||
|
||||
for(i = 0; i < G.scene->toolsettings->skgen_postpro_passes; i++)
|
||||
{
|
||||
postprocessGraph(rg, G.scene->toolsettings->skgen_postpro);
|
||||
}
|
||||
|
||||
BLI_rebuildAdjacencyList((BGraph*)rg);
|
||||
|
||||
sortNodes(rg);
|
||||
|
||||
sortArcs(rg);
|
||||
|
||||
REEB_exportGraph(rg, -1);
|
||||
|
||||
calculateGraphLength(rg);
|
||||
|
||||
printf("DONE\n");
|
||||
printf("%i subgraphs\n", BLI_FlagSubgraphs((BGraph*)rg));
|
||||
|
||||
@@ -2873,15 +2949,14 @@ void BIF_GlobalReebGraphFromEditMesh(void)
|
||||
|
||||
BIF_GlobalReebFree();
|
||||
|
||||
rg = BIF_ReebGraphFromEditMesh();
|
||||
rg = BIF_ReebGraphMultiFromEditMesh();
|
||||
|
||||
BLI_markdownSymmetry((BGraph*)rg, rg->nodes.first, G.scene->toolsettings->skgen_symmetry_limit);
|
||||
|
||||
GLOBAL_RG = rg;
|
||||
}
|
||||
|
||||
void REEB_draw()
|
||||
{
|
||||
ReebGraph *rg;
|
||||
ReebArc *arc;
|
||||
int i = 0;
|
||||
|
||||
@@ -2890,13 +2965,23 @@ void REEB_draw()
|
||||
return;
|
||||
}
|
||||
|
||||
if (GLOBAL_RG->link && G.scene->toolsettings->skgen_options & SKGEN_DISP_ORIG)
|
||||
{
|
||||
rg = GLOBAL_RG->link;
|
||||
}
|
||||
else
|
||||
{
|
||||
rg = GLOBAL_RG;
|
||||
}
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
for (arc = GLOBAL_RG->arcs.first; arc; arc = arc->next, i++)
|
||||
for (arc = rg->arcs.first; arc; arc = arc->next, i++)
|
||||
{
|
||||
ReebArcIterator iter;
|
||||
EmbedBucket *bucket;
|
||||
float vec[3];
|
||||
char text[64];
|
||||
char text[128];
|
||||
char *s = text;
|
||||
|
||||
initArcIterator(&iter, arc, arc->head);
|
||||
|
||||
@@ -2924,7 +3009,17 @@ void REEB_draw()
|
||||
|
||||
VecLerpf(vec, arc->head->p, arc->tail->p, 0.5f);
|
||||
|
||||
sprintf(text, "%i - %0.3f", i, arc->tail->weight - arc->head->weight);
|
||||
s += sprintf(s, "%i", i);
|
||||
|
||||
if (G.scene->toolsettings->skgen_options & SKGEN_DISP_WEIGHT)
|
||||
{
|
||||
s += sprintf(s, " - %0.3f", arc->tail->weight - arc->head->weight);
|
||||
}
|
||||
|
||||
if (G.scene->toolsettings->skgen_options & SKGEN_DISP_LENGTH)
|
||||
{
|
||||
s += sprintf(s, " - %0.3f", arc->length);
|
||||
}
|
||||
|
||||
glColor3f(0, 1, 0);
|
||||
glRasterPos3fv(vec);
|
||||
|
||||
Reference in New Issue
Block a user