Generate and display multi resolution filtering graphs

This commit is contained in:
Martin Poirier
2008-07-04 17:05:06 +00:00
parent a4b6f74a48
commit 44e13eb8d5
4 changed files with 203 additions and 77 deletions

View File

@@ -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 {

View File

@@ -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

View File

@@ -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())

View File

@@ -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);